diff --git a/DEPS b/DEPS
index b167905..d2fefb7 100644
--- a/DEPS
+++ b/DEPS
@@ -199,11 +199,11 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling Skia
   # and whatever else without interference from each other.
-  'skia_revision': '0a69b4bb071c7868dda1cd734351146898a74aba',
+  'skia_revision': 'be2a8614c5d6155e98ac6d5431349947da41fa0c',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling V8
   # and whatever else without interference from each other.
-  'v8_revision': '1e60bce4522aa7c92b1010988f8815f96c8243b7',
+  'v8_revision': '6cbcce5b4a6305bfc281c520ca0d24fa6d0c9a39',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling swarming_client
   # and whatever else without interference from each other.
@@ -211,7 +211,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling ANGLE
   # and whatever else without interference from each other.
-  'angle_revision': '2ed9671a0dddaab9c2582b62d3e479895ee0d333',
+  'angle_revision': '62b8364eafc717bfa9c35af5304b7ad5959e7134',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling SwiftShader
   # and whatever else without interference from each other.
@@ -266,7 +266,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling catapult
   # and whatever else without interference from each other.
-  'catapult_revision': '3889691dd695c91c212b36d857d73089cb1b8f53',
+  'catapult_revision': '178c01be65a4a5458769084606cbc6504dde10f7',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libFuzzer
   # and whatever else without interference from each other.
@@ -274,7 +274,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling devtools-frontend
   # and whatever else without interference from each other.
-  'devtools_frontend_revision': 'e2ffb37426336eb63db537529022fadf263ebba6',
+  'devtools_frontend_revision': 'bcd6b5c3ff8aa390dcd16f05afe69454229d21d5',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling libprotobuf-mutator
   # and whatever else without interference from each other.
@@ -314,7 +314,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
-  'dawn_revision': '7faa362ea9c2bffbb8e9cc2e2d9f4f4af2fe4dde',
+  'dawn_revision': '111ba65a5e3dbd23a58dd63991e92e9300f44d13',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling feed
   # and whatever else without interference from each other.
@@ -1135,7 +1135,7 @@
   },
 
   'src/third_party/libjpeg_turbo':
-    Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '09efc26aff7983f4377a1743a197ca3d74796d7d',
+    Var('chromium_git') + '/chromium/deps/libjpeg_turbo.git' + '@' + '518d81558c797486e125e37cb529d65b560a6ea0',
 
   'src/third_party/liblouis/src': {
       'url': Var('chromium_git') + '/external/liblouis-github.git' + '@' + '03d7d72d983d47c17f7de95bbeae89fe33e41943',
@@ -1266,7 +1266,7 @@
   },
 
   'src/third_party/perfetto':
-    Var('android_git') + '/platform/external/perfetto.git' + '@' + '44ba8e1708abec70b1c85015aae59026fb214c83',
+    Var('android_git') + '/platform/external/perfetto.git' + '@' + '8fccd82e4e02ac89d83739225d4118b59e8ba1cf',
 
   'src/third_party/perl': {
       'url': Var('chromium_git') + '/chromium/deps/perl.git' + '@' + '6f3e5028eb65d0b4c5fdd792106ac4c84eee1eb3',
@@ -1546,7 +1546,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/linux-amd64',
-          'version': '1TBlbVMfJAvbrsCVFRL54CvG6OJv660nvwlbVn3QedoC',
+          'version': 'UBQI89SqFeAIiGdjUUikXKgyMRFxDbvtqVUceCn1kcwC',
         },
       ],
       'dep_type': 'cipd',
@@ -1556,7 +1556,7 @@
       'packages': [
         {
           'package': 'skia/tools/goldctl/windows-amd64',
-          'version': 'AefJEwE3M-ke_pwYEVGy2Ct2Ra80EaxvK1KADBuG8-EC',
+          'version': 'kIBp6ZuMA5QTpwxtMM3NtSMezpaetuByhNmVTMg8TtMC',
         },
       ],
       'dep_type': 'cipd',
@@ -1580,7 +1580,7 @@
     Var('chromium_git') + '/v8/v8.git' + '@' +  Var('v8_revision'),
 
   'src-internal': {
-    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@76d89fa22033c340522095168b69c33ad97e4a57',
+    'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@c9846ef0a8288bd025b33e08438511b2439b47eb',
     'condition': 'checkout_src_internal',
   },
 
@@ -1599,7 +1599,7 @@
     'packages': [
       {
         'package': 'chromeos_internal/apps/media_app/app',
-        'version': 'CahPFs6jLT-RYm6-kxrLmP917a316i02uOphMFmENT0C',
+        'version': 'ze58P0cJwOmw_WVAzh3TDsg4AbgoRTTor2emAc_jh6EC',
       },
     ],
     'condition': 'checkout_chromeos and checkout_src_internal',
diff --git a/ash/ash_strings.grd b/ash/ash_strings.grd
index ebf2c17a..4042a00f 100644
--- a/ash/ash_strings.grd
+++ b/ash/ash_strings.grd
@@ -2998,10 +2998,13 @@
 
       <!-- For CameraMicTrayItemView -->
       <message name="IDS_ASH_CAMERA_MIC_VM_USING_CAMERA" desc="Tooltip message shown at the systray camera indicator when a VM is using the camera">
-        A virtual machine is using your camera
+        An application is using your camera
+      </message>
+      <message name="IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC" desc="Tooltip message shown at the systray camera indicator when a VM is using both the camera and mic">
+        An application is using your camera and microphone
       </message>
       <message name="IDS_ASH_CAMERA_MIC_VM_USING_MIC" desc="Tooltip message shown at the systray microphone indicator when a VM is using the microphone">
-        A virtual machine is using your microphone
+        An application is using your microphone
       </message>
 
       <message name="IDS_ASH_MESSAGE_CENTER_UNLOCK_TO_PERFORM_ACTION" desc="The short message to encourage user to unlock the device so that Chrome OS can perform the notification action selected by user after unlocking.">
diff --git a/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA.png.sha1
index 1e4cfd0..e51c069 100644
--- a/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA.png.sha1
+++ b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA.png.sha1
@@ -1 +1 @@
-d591db48d6c57816890d85213d98f10f6c322a6b
\ No newline at end of file
+27e7bb4609c6891d64bc47c2e232c6d410634d7e
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC.png.sha1
new file mode 100644
index 0000000..75601f0b
--- /dev/null
+++ b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC.png.sha1
@@ -0,0 +1 @@
+b5feac7cdbfe35bc8a2bc68a9d41106327310574
\ No newline at end of file
diff --git a/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_MIC.png.sha1 b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_MIC.png.sha1
index e2d2dacc..ec1e0878 100644
--- a/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_MIC.png.sha1
+++ b/ash/ash_strings_grd/IDS_ASH_CAMERA_MIC_VM_USING_MIC.png.sha1
@@ -1 +1 @@
-22591a040bd7307c93d9a3c760ed8c976a0b6e22
\ No newline at end of file
+aba716d721efb63bb24f6bd83a3f8d9c609556a4
\ No newline at end of file
diff --git a/ash/drag_drop/drag_drop_controller.cc b/ash/drag_drop/drag_drop_controller.cc
index bcee359..3d9a69c 100644
--- a/ash/drag_drop/drag_drop_controller.cc
+++ b/ash/drag_drop/drag_drop_controller.cc
@@ -23,6 +23,8 @@
 #include "ui/aura/window_delegate.h"
 #include "ui/aura/window_event_dispatcher.h"
 #include "ui/base/cursor/mojom/cursor_type.mojom-shared.h"
+#include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
+#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
 #include "ui/base/dragdrop/os_exchange_data_provider.h"
@@ -81,6 +83,17 @@
   }
 }
 
+bool IsDragDropAllowed(const ui::OSExchangeData* drag_data,
+                       aura::client::DragUpdateInfo& drag_info,
+                       bool is_drop) {
+  DCHECK(drag_data);
+
+  return ui::DataTransferPolicyController::HasInstance()
+             ? ui::DataTransferPolicyController::Get()->IsDragDropAllowed(
+                   drag_data->GetSource(), &drag_info.data_endpoint, is_drop)
+             : true;
+}
+
 }  // namespace
 
 class DragDropTrackerDelegate : public aura::WindowDelegate {
@@ -464,14 +477,19 @@
       e.set_flags(event.flags());
       ui::Event::DispatcherApi(&e).set_target(target);
       drag_info = delegate->OnDragUpdated(e);
+      bool is_drop_allowed = IsDragDropAllowed(drag_data_.get(), drag_info,
+                                               /*is_drop=*/false);
       gfx::NativeCursor cursor = ui::mojom::CursorType::kNoDrop;
-      if (drag_info.drag_operation & ui::DragDropTypes::DRAG_COPY)
-        cursor = ui::mojom::CursorType::kCopy;
-      else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_LINK)
-        cursor = ui::mojom::CursorType::kAlias;
-      else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_MOVE)
-        cursor = ui::mojom::CursorType::kGrabbing;
-
+      if (is_drop_allowed) {
+        if (drag_info.drag_operation & ui::DragDropTypes::DRAG_COPY)
+          cursor = ui::mojom::CursorType::kCopy;
+        else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_LINK)
+          cursor = ui::mojom::CursorType::kAlias;
+        else if (drag_info.drag_operation & ui::DragDropTypes::DRAG_MOVE)
+          cursor = ui::mojom::CursorType::kGrabbing;
+      } else {
+        drag_info.drag_operation = ui::DragDropTypes::DRAG_NONE;
+      }
       Shell::Get()->cursor_manager()->SetCursor(cursor);
     }
   }
@@ -506,8 +524,6 @@
 
 void DragDropController::Drop(aura::Window* target,
                               const ui::LocatedEvent& event) {
-  Shell::Get()->cursor_manager()->SetCursor(ui::mojom::CursorType::kPointer);
-
   // We must guarantee that a target gets a OnDragEntered before Drop. WebKit
   // depends on not getting a Drop without DragEnter. This behavior is
   // consistent with drag/drop on other platforms.
@@ -515,6 +531,14 @@
     DragUpdate(target, event);
   DCHECK(target == drag_window_);
 
+  if (!IsDragDropAllowed(drag_data_.get(), current_drag_info_,
+                         /*is_drop=*/true)) {
+    DragCancel();
+    return;
+  }
+
+  Shell::Get()->cursor_manager()->SetCursor(ui::mojom::CursorType::kPointer);
+
   aura::client::DragDropDelegate* delegate =
       aura::client::GetDragDropDelegate(target);
   if (delegate) {
diff --git a/ash/drag_drop/drag_drop_controller_unittest.cc b/ash/drag_drop/drag_drop_controller_unittest.cc
index 7310734..8e48223d 100644
--- a/ash/drag_drop/drag_drop_controller_unittest.cc
+++ b/ash/drag_drop/drag_drop_controller_unittest.cc
@@ -31,6 +31,7 @@
 #include "ui/base/clipboard/clipboard.h"
 #include "ui/base/clipboard/scoped_clipboard_writer.h"
 #include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
+#include "ui/base/data_transfer_policy/data_transfer_policy_controller.h"
 #include "ui/base/dragdrop/drag_drop_types.h"
 #include "ui/base/dragdrop/mojom/drag_drop_types.mojom-shared.h"
 #include "ui/base/dragdrop/os_exchange_data.h"
@@ -245,7 +246,8 @@
     kNotInvoked,
     kDragEnteredInvoked,
     kDragUpdateInvoked,
-    kPerformDropInvoked
+    kPerformDropInvoked,
+    kDragExitInvoked
   };
 
   explicit EventTargetTestDelegate(aura::Window* window) : window_(window) {}
@@ -267,7 +269,11 @@
         ui::DragDropTypes::DRAG_MOVE,
         ui::DataTransferEndpoint(ui::EndpointType::kDefault));
   }
-  void OnDragExited() override { ADD_FAILURE(); }
+  void OnDragExited() override {
+    EXPECT_TRUE(State::kDragEnteredInvoked == state_ ||
+                State::kDragUpdateInvoked == state_);
+    state_ = State::kDragExitInvoked;
+  }
   int OnPerformDrop(const ui::DropTargetEvent& event,
                     std::unique_ptr<ui::OSExchangeData> data) override {
     EXPECT_EQ(State::kDragUpdateInvoked, state_);
@@ -1474,4 +1480,95 @@
   }
 }
 
+namespace {
+
+class MockDataTransferPolicyController
+    : public ui::DataTransferPolicyController {
+ public:
+  MOCK_METHOD2(IsClipboardReadAllowed,
+               bool(const ui::DataTransferEndpoint* const data_src,
+                    const ui::DataTransferEndpoint* const data_dst));
+  MOCK_METHOD3(IsDragDropAllowed,
+               bool(const ui::DataTransferEndpoint* const data_src,
+                    const ui::DataTransferEndpoint* const data_dst,
+                    const bool is_drop));
+};
+
+}  // namespace
+
+TEST_F(DragDropControllerTest, DlpAllowDragDrop) {
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
+      aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), -1,
+      gfx::Rect(0, 0, 100, 100)));
+  EventTargetTestDelegate delegate(window.get());
+  aura::client::SetDragDropDelegate(window.get(), &delegate);
+
+  MockDataTransferPolicyController dlp_contoller;
+
+  // Posted task will be run when the inner loop runs in StartDragAndDrop.
+  ui::test::EventGenerator generator(window->GetRootWindow(), window.get());
+  generator.PressLeftButton();
+
+  auto data(std::make_unique<ui::OSExchangeData>());
+  data->SetString(base::UTF8ToUTF16("I am being dragged"));
+
+  // Drag update.
+  EXPECT_CALL(dlp_contoller, IsDragDropAllowed(_, _, /*is_drop=*/false))
+      .WillOnce(::testing::Return(true));
+  // Drop.
+  EXPECT_CALL(dlp_contoller, IsDragDropAllowed(_, _, /*is_drop=*/true))
+      .WillOnce(::testing::Return(true));
+
+  drag_drop_controller_->StartDragAndDrop(
+      std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5),
+      ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse);
+
+  // For drag enter
+  generator.MoveMouseBy(0, 1);
+  // For drag update
+  generator.MoveMouseBy(0, 1);
+  // For perform drop
+  generator.ReleaseLeftButton();
+
+  EXPECT_EQ(EventTargetTestDelegate::State::kPerformDropInvoked,
+            delegate.state());
+}
+
+TEST_F(DragDropControllerTest, DlpDisallowDragDrop) {
+  std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithDelegate(
+      aura::test::TestWindowDelegate::CreateSelfDestroyingDelegate(), -1,
+      gfx::Rect(0, 0, 100, 100)));
+  EventTargetTestDelegate delegate(window.get());
+  aura::client::SetDragDropDelegate(window.get(), &delegate);
+
+  MockDataTransferPolicyController dlp_contoller;
+
+  // Posted task will be run when the inner loop runs in StartDragAndDrop.
+  ui::test::EventGenerator generator(window->GetRootWindow(), window.get());
+  generator.PressLeftButton();
+
+  auto data(std::make_unique<ui::OSExchangeData>());
+  data->SetString(base::UTF8ToUTF16("I am being dragged"));
+
+  // Drag update.
+  EXPECT_CALL(dlp_contoller, IsDragDropAllowed(_, _, /*is_drop=*/false))
+      .WillOnce(::testing::Return(false));
+  // Drop.
+  EXPECT_CALL(dlp_contoller, IsDragDropAllowed(_, _, /*is_drop=*/true))
+      .WillOnce(::testing::Return(false));
+
+  drag_drop_controller_->StartDragAndDrop(
+      std::move(data), window->GetRootWindow(), window.get(), gfx::Point(5, 5),
+      ui::DragDropTypes::DRAG_MOVE, ui::mojom::DragEventSource::kMouse);
+
+  // For drag enter
+  generator.MoveMouseBy(0, 1);
+  // For drag update
+  generator.MoveMouseBy(0, 1);
+  // For perform drop
+  generator.ReleaseLeftButton();
+
+  EXPECT_EQ(EventTargetTestDelegate::State::kDragExitInvoked, delegate.state());
+}
+
 }  // namespace ash
diff --git a/ash/media/media_controller_impl.cc b/ash/media/media_controller_impl.cc
index 0cd8d9e5..1ef88de 100644
--- a/ash/media/media_controller_impl.cc
+++ b/ash/media/media_controller_impl.cc
@@ -93,9 +93,10 @@
 }
 
 void MediaControllerImpl::NotifyVmMediaNotificationState(bool camera,
-                                                         bool mic) {
+                                                         bool mic,
+                                                         bool camera_and_mic) {
   for (auto& observer : observers_)
-    observer.OnVmMediaNotificationChanged(camera, mic);
+    observer.OnVmMediaNotificationChanged(camera, mic, camera_and_mic);
 }
 
 void MediaControllerImpl::HandleMediaPlayPause() {
diff --git a/ash/media/media_controller_impl.h b/ash/media/media_controller_impl.h
index 22ce112..c280434 100644
--- a/ash/media/media_controller_impl.h
+++ b/ash/media/media_controller_impl.h
@@ -26,8 +26,13 @@
   // Called when media capture state has changed.
   virtual void OnMediaCaptureChanged(
       const base::flat_map<AccountId, MediaCaptureState>& capture_states) {}
-  // Called when a VM's media notifications have changed.
-  virtual void OnVmMediaNotificationChanged(bool camera, bool mic) {}
+  // Called when VMs' media capture notifications change. Each VM can have 0 or
+  // 1 media notification. It can either be a "camera", "mic", or "camera and
+  // mic" notification. Each of the argument is true if a notification of the
+  // corresponding type is active.
+  virtual void OnVmMediaNotificationChanged(bool camera,
+                                            bool mic,
+                                            bool camera_and_mic) {}
 
  protected:
   virtual ~MediaCaptureObserver() {}
@@ -57,7 +62,9 @@
   void SetForceMediaClientKeyHandling(bool enabled) override;
   void NotifyCaptureState(const base::flat_map<AccountId, MediaCaptureState>&
                               capture_states) override;
-  void NotifyVmMediaNotificationState(bool camera, bool mic) override;
+  void NotifyVmMediaNotificationState(bool camera,
+                                      bool mic,
+                                      bool camera_and_mic) override;
 
   // If media session accelerators are enabled then these methods will use the
   // media session service to control playback. Otherwise it will forward to
diff --git a/ash/public/cpp/media_controller.h b/ash/public/cpp/media_controller.h
index 86a47a3..160d57ba 100644
--- a/ash/public/cpp/media_controller.h
+++ b/ash/public/cpp/media_controller.h
@@ -41,9 +41,16 @@
   // MediaCaptureState representing every user's state.
   virtual void NotifyCaptureState(
       const base::flat_map<AccountId, MediaCaptureState>& capture_states) = 0;
-  // Called when a VM's media notifications change. There is no `AccountId` in
-  // the argument because only the primary account/profile can launch a VM.
-  virtual void NotifyVmMediaNotificationState(bool camera, bool mic) = 0;
+  // Called when VMs' media capture notifications change. Each VM can have 0 or
+  // 1 media notification. It can either be a "camera", "mic", or "camera and
+  // mic" notification. Each of the argument is true if a notification of the
+  // corresponding type is active.
+  //
+  // There is no `AccountId` in the argument because only the primary
+  // account/profile can launch a VM.
+  virtual void NotifyVmMediaNotificationState(bool camera,
+                                              bool mic,
+                                              bool camera_and_mic) = 0;
 
  protected:
   MediaController();
diff --git a/ash/system/unified/camera_mic_tray_item_view.cc b/ash/system/unified/camera_mic_tray_item_view.cc
index ae713d2..45eaf8a4 100644
--- a/ash/system/unified/camera_mic_tray_item_view.cc
+++ b/ash/system/unified/camera_mic_tray_item_view.cc
@@ -59,10 +59,13 @@
 }
 
 void CameraMicTrayItemView::OnVmMediaNotificationChanged(bool camera,
-                                                         bool mic) {
+                                                         bool mic,
+                                                         bool camera_and_mic) {
   switch (type_) {
     case Type::kCamera:
-      active_ = camera;
+      active_ = camera || camera_and_mic;
+      with_mic_ = camera_and_mic;
+      FetchMessage();
       break;
     case Type::kMic:
       active_ = mic;
@@ -110,7 +113,9 @@
 void CameraMicTrayItemView::FetchMessage() {
   switch (type_) {
     case Type::kCamera:
-      message_ = l10n_util::GetStringUTF16(IDS_ASH_CAMERA_MIC_VM_USING_CAMERA);
+      message_ = l10n_util::GetStringUTF16(
+          with_mic_ ? IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC
+                    : IDS_ASH_CAMERA_MIC_VM_USING_CAMERA);
       break;
     case Type::kMic:
       message_ = l10n_util::GetStringUTF16(IDS_ASH_CAMERA_MIC_VM_USING_MIC);
diff --git a/ash/system/unified/camera_mic_tray_item_view.h b/ash/system/unified/camera_mic_tray_item_view.h
index 9cfa9a3..6a66aac5 100644
--- a/ash/system/unified/camera_mic_tray_item_view.h
+++ b/ash/system/unified/camera_mic_tray_item_view.h
@@ -43,7 +43,9 @@
   void HandleLocaleChange() override;
 
   // MediaCaptureObserver:
-  void OnVmMediaNotificationChanged(bool camera, bool mic) override;
+  void OnVmMediaNotificationChanged(bool camera,
+                                    bool mic,
+                                    bool camera_and_mic) override;
 
  private:
   void Update();
@@ -51,6 +53,7 @@
 
   const Type type_;
   bool active_ = false;
+  bool with_mic_ = false;  // Only for `type_ == kCamera`.
   bool is_primary_session_ = false;
   base::string16 message_;
 };
diff --git a/ash/system/unified/camera_mic_tray_item_view_unittest.cc b/ash/system/unified/camera_mic_tray_item_view_unittest.cc
index c68de5e..eec6fb2 100644
--- a/ash/system/unified/camera_mic_tray_item_view_unittest.cc
+++ b/ash/system/unified/camera_mic_tray_item_view_unittest.cc
@@ -8,10 +8,12 @@
 #include <utility>
 
 #include "ash/public/cpp/media_controller.h"
+#include "ash/strings/grit/ash_strings.h"
 #include "ash/test/ash_test_base.h"
 #include "base/test/scoped_feature_list.h"
 #include "chromeos/constants/chromeos_features.h"
 #include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
 
 namespace ash {
 
@@ -19,17 +21,15 @@
 using Type = CameraMicTrayItemView::Type;
 }  // namespace
 
-class CameraMicTrayItemViewTest : public AshTestBase,
-                                  public testing::WithParamInterface<Type> {
+class BaseCameraMicTrayItemViewTest : public AshTestBase {
  public:
-  // AshTestBase:
-  void SetUp() override {
+  void SetUpWithType(Type type) {
     scoped_feature_list_.InitAndEnableFeature(
         chromeos::features::kVmCameraMicIndicatorsAndNotifications);
     AshTestBase::SetUp();
 
     camera_mic_tray_item_view_ =
-        std::make_unique<CameraMicTrayItemView>(GetPrimaryShelf(), GetParam());
+        std::make_unique<CameraMicTrayItemView>(GetPrimaryShelf(), type);
 
     // Relogin to make sure `OnActiveUserSessionChanged` is triggered.
     ClearLogin();
@@ -46,30 +46,59 @@
   std::unique_ptr<CameraMicTrayItemView> camera_mic_tray_item_view_;
 };
 
-TEST_P(CameraMicTrayItemViewTest, OnVmMediaNotificationChanged) {
+class CameraMicTrayItemViewTest : public BaseCameraMicTrayItemViewTest,
+                                  public testing::WithParamInterface<Type> {
+ public:
+  // AshTestBase:
+  void SetUp() override { SetUpWithType(GetParam()); }
+};
+
+TEST_P(CameraMicTrayItemViewTest, GetVisible) {
   Type type = GetParam();
   EXPECT_FALSE(camera_mic_tray_item_view_->GetVisible());
 
-  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(/*camera=*/true,
-                                                           /*mic=*/false);
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/false,
+      /*camera_and_mic=*/false);
   EXPECT_EQ(camera_mic_tray_item_view_->GetVisible(), type == Type::kCamera);
 
-  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(/*camera=*/false,
-                                                           /*mic=*/true);
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/false,
+      /*mic=*/false,
+      /*camera_and_mic=*/true);
+  EXPECT_EQ(camera_mic_tray_item_view_->GetVisible(), type == Type::kCamera);
+
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/false,
+      /*mic=*/true,
+      /*camera_and_mic=*/false);
   EXPECT_EQ(camera_mic_tray_item_view_->GetVisible(), type == Type::kMic);
 
-  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(/*camera=*/true,
-                                                           /*mic=*/true);
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/true,
+      /*camera_and_mic=*/false);
   EXPECT_TRUE(camera_mic_tray_item_view_->GetVisible());
 
-  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(/*camera=*/false,
-                                                           /*mic=*/false);
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/true,
+      /*camera_and_mic=*/true);
+  EXPECT_TRUE(camera_mic_tray_item_view_->GetVisible());
+
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/false,
+      /*mic=*/false,
+      /*camera_and_mic=*/false);
   EXPECT_FALSE(camera_mic_tray_item_view_->GetVisible());
 }
 
 TEST_P(CameraMicTrayItemViewTest, HideForNonPrimaryUser) {
-  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(/*camera=*/true,
-                                                           /*mic=*/true);
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/true,
+      /*camera_and_mic=*/true);
   EXPECT_TRUE(camera_mic_tray_item_view_->GetVisible());
 
   SimulateUserLogin("user2@test.com");
@@ -80,4 +109,36 @@
                          CameraMicTrayItemViewTest,
                          testing::Values(Type::kCamera, Type::kMic));
 
+// For testing that the camera tray item switch the message depending on whether
+// the "camera and mic" notification is active.
+class CameraMicTrayItemViewMessageTest : public BaseCameraMicTrayItemViewTest {
+  // AshTestBase:
+  void SetUp() override { SetUpWithType(Type::kCamera); }
+};
+
+TEST_F(CameraMicTrayItemViewMessageTest, Message) {
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/false,
+      /*camera_and_mic=*/false);
+  EXPECT_EQ(camera_mic_tray_item_view_->GetAccessibleNameString(),
+            l10n_util::GetStringUTF16(IDS_ASH_CAMERA_MIC_VM_USING_CAMERA));
+
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/false,
+      /*mic=*/false,
+      /*camera_and_mic=*/true);
+  EXPECT_EQ(
+      camera_mic_tray_item_view_->GetAccessibleNameString(),
+      l10n_util::GetStringUTF16(IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC));
+
+  camera_mic_tray_item_view_->OnVmMediaNotificationChanged(
+      /*camera=*/true,
+      /*mic=*/false,
+      /*camera_and_mic=*/true);
+  EXPECT_EQ(
+      camera_mic_tray_item_view_->GetAccessibleNameString(),
+      l10n_util::GetStringUTF16(IDS_ASH_CAMERA_MIC_VM_USING_CAMERA_AND_MIC));
+}
+
 }  // namespace ash
diff --git a/base/allocator/partition_allocator/partition_root.h b/base/allocator/partition_allocator/partition_root.h
index 51192dd..c594eb05 100644
--- a/base/allocator/partition_allocator/partition_root.h
+++ b/base/allocator/partition_allocator/partition_root.h
@@ -325,7 +325,11 @@
   }
 
   bool UsesGigaCage() const {
-    return features::IsPartitionAllocGigaCageEnabled() && allow_ref_count;
+    return features::IsPartitionAllocGigaCageEnabled()
+#if ENABLE_REF_COUNT_FOR_BACKUP_REF_PTR
+           && allow_ref_count
+#endif
+        ;
   }
 
   ALWAYS_INLINE bool IsScannable() const {
diff --git a/build/config/compiler/BUILD.gn b/build/config/compiler/BUILD.gn
index 5ea2f21..5928c56 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -627,9 +627,6 @@
         # Experimentally determined to yield a reasonable trade-off between
         # build time, run-time performance, and binary size.
         "-mllvm:-import-instr-limit=10",
-
-        # TODO(https://crbug.com/1127713): Investigate, remove.
-        "-mllvm:-enable-dse-memoryssa=false",
       ]
     } else {
       ldflags += [ "-flto=thin" ]
diff --git a/cc/metrics/compositor_frame_reporting_controller.cc b/cc/metrics/compositor_frame_reporting_controller.cc
index d2cbf4a..2ff29e6 100644
--- a/cc/metrics/compositor_frame_reporting_controller.cc
+++ b/cc/metrics/compositor_frame_reporting_controller.cc
@@ -78,9 +78,18 @@
   if (reporters_[PipelineStage::kBeginImplFrame]) {
     auto& reporter = reporters_[PipelineStage::kBeginImplFrame];
     DCHECK(reporter->did_finish_impl_frame());
-    DCHECK(reporter->did_not_produce_frame());
-    reporter->TerminateFrame(FrameTerminationStatus::kDidNotProduceFrame,
-                             reporter->did_not_produce_frame_time());
+    // TODO(1144353): This is a speculative fix. This code should only be
+    // reached after the previous frame have been explicitly marked as 'did not
+    // produce frame', i.e. this code should have a DCHECK instead of a
+    // conditional:
+    //   DCHECK(reporter->did_not_produce_frame()).
+    if (reporter->did_not_produce_frame()) {
+      reporter->TerminateFrame(FrameTerminationStatus::kDidNotProduceFrame,
+                               reporter->did_not_produce_frame_time());
+    } else {
+      reporter->TerminateFrame(FrameTerminationStatus::kReplacedByNewReporter,
+                               Now());
+    }
   }
   auto reporter = std::make_unique<CompositorFrameReporter>(
       active_trackers_, args, latency_ukm_reporter_.get(),
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
index 317e970..5eeb0d0c 100644
--- a/chrome/BUILD.gn
+++ b/chrome/BUILD.gn
@@ -1105,6 +1105,8 @@
       "$root_out_dir/$chrome_product_full_name.app/Contents/MacOS/$chrome_product_full_name",
       "$root_out_dir/AlertNotificationService.xpc/Contents/MacOS/AlertNotificationService",
       "$root_out_dir/chrome_crashpad_handler",
+      "$root_out_dir/libEGL.dylib",
+      "$root_out_dir/libGLESv2.dylib",
       "$root_out_dir/libswiftshader_libEGL.dylib",
       "$root_out_dir/libswiftshader_libGLESv2.dylib",
       _framework_binary_path,
@@ -1137,6 +1139,8 @@
         ":chrome_framework",
         "//chrome/browser/ui/cocoa/notifications:alert_notification_xpc_service",
         "//components/crash/core/app:chrome_crashpad_handler",
+        "//third_party/angle:libEGL",
+        "//third_party/angle:libGLESv2",
         "//third_party/breakpad:dump_syms",
         "//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL",
         "//third_party/swiftshader/src/OpenGL/libGLESv2:swiftshader_libGLESv2",
@@ -1159,6 +1163,8 @@
         "$root_out_dir/$chrome_framework_name.dSYM",
         "$root_out_dir/$chrome_product_full_name.dSYM",
         "$root_out_dir/chrome_crashpad_handler.dSYM",
+        "$root_out_dir/libEGL.dylib.dSYM",
+        "$root_out_dir/libGLESv2.dylib.dSYM",
         "$root_out_dir/libswiftshader_libEGL.dylib.dSYM",
         "$root_out_dir/libswiftshader_libGLESv2.dylib.dSYM",
       ]
@@ -1168,6 +1174,8 @@
         ":chrome_framework",
         "//chrome/browser/ui/cocoa/notifications:alert_notification_xpc_service",
         "//components/crash/core/app:chrome_crashpad_handler",
+        "//third_party/angle:libEGL",
+        "//third_party/angle:libGLESv2",
         "//third_party/swiftshader/src/OpenGL/libEGL:swiftshader_libEGL",
         "//third_party/swiftshader/src/OpenGL/libGLESv2:swiftshader_libGLESv2",
       ]
diff --git a/chrome/android/BUILD.gn b/chrome/android/BUILD.gn
index 228d878..2e204a7 100644
--- a/chrome/android/BUILD.gn
+++ b/chrome/android/BUILD.gn
@@ -194,7 +194,6 @@
     "//chrome/android/webapk/libs/common:splash_resources",
     "//chrome/app:java_strings_grd",
     "//chrome/browser/feedback/android:java_resources",
-    "//chrome/browser/incognito/interstitial/android:java_resources",
     "//chrome/browser/password_check/android:java_resources",
     "//chrome/browser/signin/services/android:java_resources",
     "//chrome/browser/signin/ui/android:java_resources",
@@ -318,7 +317,6 @@
     "//chrome/browser/image_descriptions:java",
     "//chrome/browser/image_editor/public:java",
     "//chrome/browser/image_fetcher:java",
-    "//chrome/browser/incognito/interstitial/android:java",
     "//chrome/browser/metrics_settings/android:java",
     "//chrome/browser/notifications/chime/android:java",
     "//chrome/browser/offline_pages/android:java",
diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni
index 1a1ec57..ef945c4 100644
--- a/chrome/android/chrome_java_resources.gni
+++ b/chrome/android/chrome_java_resources.gni
@@ -632,7 +632,6 @@
   "java/res/drawable/ic_error.xml",
   "java/res/drawable/ic_error_googred_36dp.xml",
   "java/res/drawable/ic_event_round.xml",
-  "java/res/drawable/ic_expand_more_in_circle_24dp.xml",
   "java/res/drawable/ic_file_download_scheduled_24dp.xml",
   "java/res/drawable/ic_find_in_page.xml",
   "java/res/drawable/ic_fingerprint_grey500_36dp.xml",
@@ -727,15 +726,6 @@
   "java/res/layout/account_chooser_dialog_title.xml",
   "java/res/layout/account_divider_preference.xml",
   "java/res/layout/account_management_account_row.xml",
-  "java/res/layout/account_picker_bottom_sheet_continue_button.xml",
-  "java/res/layout/account_picker_bottom_sheet_header.xml",
-  "java/res/layout/account_picker_bottom_sheet_view.xml",
-  "java/res/layout/account_picker_state_auth_error.xml",
-  "java/res/layout/account_picker_state_collapsed.xml",
-  "java/res/layout/account_picker_state_expanded.xml",
-  "java/res/layout/account_picker_state_general_error.xml",
-  "java/res/layout/account_picker_state_no_account.xml",
-  "java/res/layout/account_picker_state_signin_in_progress.xml",
   "java/res/layout/add_languages_main.xml",
   "java/res/layout/add_to_homescreen_dialog.xml",
   "java/res/layout/add_to_menu_dialog.xml",
diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni
index 78afbdf9..7c06a37 100644
--- a/chrome/android/chrome_java_sources.gni
+++ b/chrome/android/chrome_java_sources.gni
@@ -236,6 +236,7 @@
   "java/src/org/chromium/chrome/browser/browserservices/ui/view/DisclosureNotification.java",
   "java/src/org/chromium/chrome/browser/browserservices/ui/view/DisclosureSnackbar.java",
   "java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifier.java",
+  "java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierStatics.java",
   "java/src/org/chromium/chrome/browser/browserservices/verification/Relationship.java",
   "java/src/org/chromium/chrome/browser/browserservices/verification/VerificationResultStore.java",
   "java/src/org/chromium/chrome/browser/browsing_data/BrowsingDataBridge.java",
@@ -1248,11 +1249,6 @@
   "java/src/org/chromium/chrome/browser/signin/SigninPromoUtil.java",
   "java/src/org/chromium/chrome/browser/signin/SigninUtils.java",
   "java/src/org/chromium/chrome/browser/signin/SyncPromoView.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java",
-  "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java",
   "java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerDelegateImpl.java",
   "java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java",
   "java/src/org/chromium/chrome/browser/site_settings/CookieControlsServiceBridge.java",
diff --git a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
index 4fc8276..510a15c 100644
--- a/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
+++ b/chrome/android/features/autofill_assistant/javatests/src/org/chromium/chrome/browser/autofill_assistant/AutofillAssistantBottomsheetTest.java
@@ -37,6 +37,7 @@
 import static org.chromium.chrome.browser.autofill_assistant.proto.ConfigureBottomSheetProto.ViewportResizing.RESIZE_VISUAL_VIEWPORT;
 
 import android.graphics.Rect;
+import android.os.Build.VERSION_CODES;
 
 import androidx.test.espresso.Espresso;
 import androidx.test.espresso.ViewAction;
@@ -55,6 +56,7 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.Criteria;
 import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.DisableIf;
 import org.chromium.base.test.util.DisabledTest;
 import org.chromium.chrome.autofill_assistant.R;
 import org.chromium.chrome.browser.autofill_assistant.proto.ActionProto;
@@ -239,7 +241,10 @@
 
     @Test
     @MediumTest
-    public void testHandleHeader() {
+    @DisableIf.Build(message = "Flaky on Android P, see https://crbug.com/1166168",
+            sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q)
+    public void
+    testHandleHeader() {
         AutofillAssistantTestService testService = new AutofillAssistantTestService(
                 Collections.singletonList(makeScript(RESIZE_LAYOUT_VIEWPORT, HANDLE_HEADER, true)));
         startAutofillAssistant(mTestRule.getActivity(), testService);
@@ -261,7 +266,10 @@
 
     @Test
     @MediumTest
-    public void testHandleHeaderCarousels() {
+    @DisableIf.Build(message = "Flaky on Android P, see https://crbug.com/1166168",
+            sdk_is_greater_than = VERSION_CODES.O_MR1, sdk_is_less_than = VERSION_CODES.Q)
+    public void
+    testHandleHeaderCarousels() {
         AutofillAssistantTestService testService =
                 new AutofillAssistantTestService(Collections.singletonList(
                         makeScript(RESIZE_LAYOUT_VIEWPORT, HANDLE_HEADER_CAROUSELS, true)));
diff --git a/chrome/android/java/DEPS b/chrome/android/java/DEPS
index f6f7503..e41acfa 100644
--- a/chrome/android/java/DEPS
+++ b/chrome/android/java/DEPS
@@ -5,6 +5,7 @@
   "+chrome/browser/banners/android/java",
   "+chrome/browser/device",
   "+chrome/browser/privacy",
+  "+chrome/browser/privacy_sandbox",
   "+chrome/browser/profiles/android/java",
   "+chrome/browser/share/android",
   "+chrome/browser/tab",
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierStatics.java b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierStatics.java
new file mode 100644
index 0000000..e30397d
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/browserservices/verification/OriginVerifierStatics.java
@@ -0,0 +1,30 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.browserservices.verification;
+
+import org.chromium.components.embedder_support.util.Origin;
+
+import androidx.annotation.VisibleForTesting;
+
+/**
+ * Adds a layer of indirection to calls to static methods on {@link OriginVerifier}. This allows us
+ * to modify that class a bit more freely without having to worry about downstream relying on its
+ * static methods.
+ *
+ * This should be temporary, see https://crbug.com/1164866
+ */
+class OriginVerifierStatics {
+    /** Calls {@link OriginVerifier#clearCachedVerificationsForTesting}. */
+    @VisibleForTesting
+    public static void clearCachedVerificationsForTesting() {
+        OriginVerifier.clearCachedVerificationsForTesting();
+    }
+
+    /** Calls {@link OriginVerifier#addVerificationOverride}. */
+    public static void addVerificationOverride(
+            String packageName, Origin origin, int relationship) {
+        OriginVerifier.addVerificationOverride(packageName, origin, relationship);
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
index ca2f6cb..103b16c6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/init/ProcessInitializationHandler.java
@@ -127,6 +127,9 @@
     private static final Object SNAPSHOT_DATABASE_LOCK = new Object();
     private static final String SNAPSHOT_DATABASE_NAME = "snapshots.db";
 
+    // The feature param for determining whether the PhotoPicker should animate thumbnails.
+    private static final String FEATURE_PARAM_ANIMATE_THUMBNAILS = "animate_thumbnails";
+
     private static ProcessInitializationHandler sInstance;
 
     private boolean mInitializedPreNative;
@@ -223,32 +226,31 @@
         ChromeLifetimeController.initialize();
         Clipboard.getInstance().setImageFileProvider(new ClipboardImageFileProvider());
 
-        if (ChromeFeatureList.isEnabled(ChromeFeatureList.NEW_PHOTO_PICKER)) {
-            DecoderServiceHost.setIntentSupplier(() -> {
-                return new Intent(ContextUtils.getApplicationContext(), DecoderService.class);
-            });
+        DecoderServiceHost.setIntentSupplier(() -> {
+            return new Intent(ContextUtils.getApplicationContext(), DecoderService.class);
+        });
 
-            SelectFileDialog.setPhotoPickerDelegate(new PhotoPickerDelegate() {
-                @Override
-                public PhotoPicker showPhotoPicker(WindowAndroid windowAndroid,
-                        PhotoPickerListener listener, boolean allowMultiple,
-                        List<String> mimeTypes) {
-                    PhotoPickerDialog dialog = new PhotoPickerDialog(windowAndroid,
-                            windowAndroid.getContext().get().getContentResolver(), listener,
-                            allowMultiple, mimeTypes);
-                    dialog.getWindow().getAttributes().windowAnimations =
-                            R.style.PickerDialogAnimation;
-                    dialog.show();
-                    return dialog;
-                }
+        SelectFileDialog.setPhotoPickerDelegate(new PhotoPickerDelegate() {
+            @Override
+            public PhotoPicker showPhotoPicker(WindowAndroid windowAndroid,
+                    PhotoPickerListener listener, boolean allowMultiple, List<String> mimeTypes) {
+                PhotoPickerDialog dialog = new PhotoPickerDialog(windowAndroid,
+                        windowAndroid.getContext().get().getContentResolver(), listener,
+                        allowMultiple,
+                        ChromeFeatureList.getFieldTrialParamByFeatureAsBoolean(
+                                ChromeFeatureList.PHOTO_PICKER_VIDEO_SUPPORT,
+                                FEATURE_PARAM_ANIMATE_THUMBNAILS, false),
+                        mimeTypes);
+                dialog.getWindow().getAttributes().windowAnimations = R.style.PickerDialogAnimation;
+                dialog.show();
+                return dialog;
+            }
 
-                @Override
-                public boolean supportsVideos() {
-                    return ChromeFeatureList.isEnabled(
-                            ChromeFeatureList.PHOTO_PICKER_VIDEO_SUPPORT);
-                }
-            });
-        }
+            @Override
+            public boolean supportsVideos() {
+                return ChromeFeatureList.isEnabled(ChromeFeatureList.PHOTO_PICKER_VIDEO_SUPPORT);
+            }
+        });
 
         ContactsPicker.setContactsPickerDelegate(
                 (WindowAndroid windowAndroid, ContactsPickerListener listener,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
index a13690e..1ffc7c4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java
@@ -46,6 +46,8 @@
 import org.chromium.chrome.browser.safety_check.SafetyCheckUpdatesDelegateImpl;
 import org.chromium.chrome.browser.signin.SigninActivityLauncherImpl;
 import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarManageable;
 import org.chromium.components.browser_ui.settings.FragmentSettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsLauncher;
 import org.chromium.components.browser_ui.settings.SettingsUtils;
@@ -68,7 +70,7 @@
  *    {@link SettingsUtils#getShowShadowOnScrollListener(View, View)}.
  */
 public class SettingsActivity extends ChromeBaseAppCompatActivity
-        implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback {
+        implements PreferenceFragmentCompat.OnPreferenceStartFragmentCallback, SnackbarManageable {
     /**
      * Preference fragments may implement this interface to intercept "Back" button taps in this
      * activity.
@@ -96,6 +98,8 @@
     /** An instance of settings launcher that can be injected into a fragment */
     private SettingsLauncher mSettingsLauncher = new SettingsLauncherImpl();
 
+    private SnackbarManager mSnackbarManager;
+
     @SuppressLint("InlinedApi")
     @Override
     protected void onCreate(Bundle savedInstanceState) {
@@ -165,9 +169,18 @@
     @Override
     public void onAttachedToWindow() {
         super.onAttachedToWindow();
+        ViewGroup contentView = findViewById(android.R.id.content);
+        mSnackbarManager = new SnackbarManager(this, contentView, null);
 
         Fragment fragment = getMainFragment();
 
+        if (fragment instanceof SiteSettingsPreferenceFragment) {
+            ChromeSiteSettingsDelegate delegate =
+                    (ChromeSiteSettingsDelegate) (((SiteSettingsPreferenceFragment) fragment)
+                                                          .getSiteSettingsDelegate());
+            delegate.setSnackbarManager(mSnackbarManager);
+        }
+
         ViewGroup listView = null;
         if (fragment instanceof PreferenceFragmentCompat) {
             listView = ((PreferenceFragmentCompat) fragment).getListView();
@@ -178,8 +191,8 @@
         if (listView == null) return;
 
         // Append action bar shadow to layout.
-        View inflatedView = getLayoutInflater().inflate(
-                R.layout.settings_action_bar_shadow, findViewById(android.R.id.content));
+        View inflatedView =
+                getLayoutInflater().inflate(R.layout.settings_action_bar_shadow, contentView);
 
         // Display shadow on scroll.
         listView.getViewTreeObserver().addOnScrollChangedListener(
@@ -331,6 +344,11 @@
         }
     }
 
+    @Override
+    public SnackbarManager getSnackbarManager() {
+        return mSnackbarManager;
+    }
+
     private void ensureActivityNotExported() {
         if (sActivityNotExportedChecked) return;
         sActivityNotExportedChecked = true;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java
index 9e1f9a9..668c88a3 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/SharingServiceProxy.java
@@ -57,20 +57,17 @@
      * Sends a shared clipboard message to the device specified by GUID.
      * @param guid The guid of the receiver device.
      * @param text The text to send.
-     * @param retries The number of retries so far.
      * @param callback The result of the operation. Runs |callback| with a
      *         org.chromium.chrome.browser.sharing.SharingSendMessageResult enum value.
      */
-    public void sendSharedClipboardMessage(
-            String guid, String text, int retries, Callback<Integer> callback) {
+    public void sendSharedClipboardMessage(String guid, String text, Callback<Integer> callback) {
         if (sNativeSharingServiceProxyAndroid == 0) {
             callback.onResult(SharingSendMessageResult.INTERNAL_ERROR);
             return;
         }
 
         Natives jni = SharingServiceProxyJni.get();
-        jni.sendSharedClipboardMessage(
-                sNativeSharingServiceProxyAndroid, guid, text, retries, callback);
+        jni.sendSharedClipboardMessage(sNativeSharingServiceProxyAndroid, guid, text, callback);
     }
 
     /**
@@ -131,7 +128,7 @@
     interface Natives {
         void initSharingService(Profile profile);
         void sendSharedClipboardMessage(long nativeSharingServiceProxyAndroid, String guid,
-                String text, int retries, Callback<Integer> callback);
+                String text, Callback<Integer> callback);
         void getDeviceCandidates(long nativeSharingServiceProxyAndroid,
                 ArrayList<DeviceInfo> deviceInfo, int requiredFeature);
         void addDeviceCandidatesInitializedObserver(
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
index 3ea75c3..2be6986e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardMessageHandler.java
@@ -30,7 +30,6 @@
     private static final String EXTRA_DEVICE_GUID = "SharedClipboard.EXTRA_DEVICE_GUID";
     private static final String EXTRA_DEVICE_CLIENT_NAME =
             "SharedClipboard.EXTRA_DEVICE_CLIENT_NAME";
-    private static final String EXTRA_RETRIES = "SharedClipboard.EXTRA_RETRIES";
 
     /**
      * Handles the tapping of an incoming notification when text is shared with current device.
@@ -54,9 +53,8 @@
             String guid = IntentUtils.safeGetStringExtra(intent, EXTRA_DEVICE_GUID);
             String name = IntentUtils.safeGetStringExtra(intent, EXTRA_DEVICE_CLIENT_NAME);
             String text = IntentUtils.safeGetStringExtra(intent, Intent.EXTRA_TEXT);
-            int retries = IntentUtils.safeGetIntExtra(intent, EXTRA_RETRIES, /*defaultValue=*/1);
 
-            showSendingNotification(guid, name, text, retries);
+            showSendingNotification(guid, name, text);
         }
     }
 
@@ -67,9 +65,8 @@
      * @param guid The guid of the receiver device.
      * @param name The name of the receiver device.
      * @param text The text shared from the sender device.
-     * @param retries The number of retries so far.
      */
-    public static void showSendingNotification(String guid, String name, String text, int retries) {
+    public static void showSendingNotification(String guid, String name, String text) {
         if (TextUtils.isEmpty(guid) || TextUtils.isEmpty(name) || TextUtils.isEmpty(text)) {
             return;
         }
@@ -88,7 +85,7 @@
         // TODO(crbug.com/1015411): Wait for device info in a more central place.
         SharingServiceProxy.getInstance().addDeviceCandidatesInitializedObserver(() -> {
             SharingServiceProxy.getInstance().sendSharedClipboardMessage(
-                    guid, text, retries, result -> {
+                    guid, text, result -> {
                         if (result == SharingSendMessageResult.SUCCESSFUL) {
                             SharingNotificationUtil.dismissNotification(
                                     NotificationConstants.GROUP_SHARED_CLIPBOARD,
@@ -107,8 +104,7 @@
                                         new Intent(context, TryAgainReceiver.class)
                                                 .putExtra(Intent.EXTRA_TEXT, text)
                                                 .putExtra(EXTRA_DEVICE_GUID, guid)
-                                                .putExtra(EXTRA_DEVICE_CLIENT_NAME, name)
-                                                .putExtra(EXTRA_RETRIES, retries + 1),
+                                                .putExtra(EXTRA_DEVICE_CLIENT_NAME, name),
                                         PendingIntent.FLAG_UPDATE_CURRENT);
                             }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
index 5cc953967..0e26847 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sharing/shared_clipboard/SharedClipboardShareActivity.java
@@ -131,8 +131,7 @@
         SharedClipboardMetrics.recordDeviceClick(position);
         SharedClipboardMetrics.recordTextSize(text != null ? text.length() : 0);
 
-        SharedClipboardMessageHandler.showSendingNotification(
-                device.guid, device.clientName, text, /*retries=*/0);
+        SharedClipboardMessageHandler.showSendingNotification(device.guid, device.clientName, text);
         finish();
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
index d08e5bf..d6da252 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/signin/SigninUtils.java
@@ -19,12 +19,12 @@
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
 import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.account_picker.AccountPickerDelegateImpl;
 import org.chromium.chrome.browser.signin.services.IdentityServicesProvider;
 import org.chromium.chrome.browser.signin.services.SigninManager;
 import org.chromium.chrome.browser.signin.services.SigninMetricsUtils;
 import org.chromium.chrome.browser.signin.services.WebSigninBridge;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.sync.settings.AccountManagementFragment;
 import org.chromium.chrome.browser.tabmodel.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModel;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
index f93eec5..e931dd0 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsDelegate.java
@@ -19,10 +19,13 @@
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.notifications.channels.SiteChannelsManager;
+import org.chromium.chrome.browser.privacy_sandbox.PrivacySandboxSnackbarController;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.settings.ChromeManagedPreferenceDelegate;
+import org.chromium.chrome.browser.settings.SettingsLauncherImpl;
 import org.chromium.chrome.browser.ui.favicon.FaviconHelper;
 import org.chromium.chrome.browser.ui.favicon.FaviconHelper.FaviconImageCallback;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.webapps.WebappRegistry;
 import org.chromium.components.browser_ui.settings.ManagedPreferenceDelegate;
 import org.chromium.components.browser_ui.site_settings.SiteSettingsCategory;
@@ -52,12 +55,23 @@
     private final Context mContext;
     private final BrowserContextHandle mBrowserContext;
     private ManagedPreferenceDelegate mManagedPreferenceDelegate;
+    private PrivacySandboxSnackbarController mPrivacySandboxController;
 
     public ChromeSiteSettingsDelegate(Context context, BrowserContextHandle browserContext) {
         mContext = context;
         mBrowserContext = browserContext;
     }
 
+    /**
+     * Used to set an instance of {@link SnackbarManager} by the parent activity.
+     */
+    public void setSnackbarManager(SnackbarManager manager) {
+        if (manager != null) {
+            mPrivacySandboxController = new PrivacySandboxSnackbarController(
+                    mContext, manager, new SettingsLauncherImpl());
+        }
+    }
+
     @Override
     public BrowserContextHandle getBrowserContextHandle() {
         return mBrowserContext;
@@ -220,4 +234,22 @@
     public Set<String> getAllDelegatedNotificationOrigins() {
         return TrustedWebActivityPermissionManager.get().getAllDelegatedOrigins();
     }
+
+    @Override
+    public void maybeDisplayPrivacySandboxSnackbar() {
+        if (mPrivacySandboxController == null
+                || !ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS)) {
+            return;
+        }
+        mPrivacySandboxController.showSnackbar();
+    }
+
+    @Override
+    public void dismissPrivacySandboxSnackbar() {
+        if (mPrivacySandboxController == null
+                || !ChromeFeatureList.isEnabled(ChromeFeatureList.PRIVACY_SANDBOX_SETTINGS)) {
+            return;
+        }
+        mPrivacySandboxController.dismissSnackbar();
+    }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
index e9e794f..8d1b68f 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -204,30 +204,27 @@
             }
             signOutPreference.setTitle(getSignOutPreferenceText());
             signOutPreference.setOnPreferenceClickListener(preference -> {
-                if (!isVisible() || !isResumed()) return false;
-
-                if (mSignedInAccountName != null) {
-                    SigninMetricsUtils.logProfileAccountManagementMenu(
-                            ProfileAccountManagementMetrics.TOGGLE_SIGNOUT, mGaiaServiceType);
-
-                    if (IdentityServicesProvider.get()
-                                    .getIdentityManager(Profile.getLastUsedRegularProfile())
-                                    .getPrimaryAccountInfo(ConsentLevel.SYNC)
-                            != null) {
-                        // Only show the sign-out dialog if the user has given sync consent.
-                        SignOutDialogFragment signOutFragment =
-                                SignOutDialogFragment.create(mGaiaServiceType);
-                        signOutFragment.setTargetFragment(AccountManagementFragment.this, 0);
-                        signOutFragment.show(getFragmentManager(), SIGN_OUT_DIALOG_TAG);
-                    } else {
-                        IdentityServicesProvider.get()
-                                .getSigninManager(Profile.getLastUsedRegularProfile())
-                                .signOut(SignoutReason.USER_CLICKED_SIGNOUT_SETTINGS, null, false);
-                    }
-                    return true;
+                if (!isVisible() || !isResumed() || mSignedInAccountName == null) {
+                    return false;
                 }
+                SigninMetricsUtils.logProfileAccountManagementMenu(
+                        ProfileAccountManagementMetrics.TOGGLE_SIGNOUT, mGaiaServiceType);
 
-                return false;
+                if (IdentityServicesProvider.get()
+                                .getIdentityManager(Profile.getLastUsedRegularProfile())
+                                .getPrimaryAccountInfo(ConsentLevel.SYNC)
+                        != null) {
+                    // Only show the sign-out dialog if the user has given sync consent.
+                    SignOutDialogFragment signOutFragment =
+                            SignOutDialogFragment.create(mGaiaServiceType);
+                    signOutFragment.setTargetFragment(AccountManagementFragment.this, 0);
+                    signOutFragment.show(getFragmentManager(), SIGN_OUT_DIALOG_TAG);
+                } else {
+                    IdentityServicesProvider.get()
+                            .getSigninManager(Profile.getLastUsedRegularProfile())
+                            .signOut(SignoutReason.USER_CLICKED_SIGNOUT_SETTINGS, null, false);
+                }
+                return true;
             });
         }
     }
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java
index a7111eb..c2ad939 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetRenderTest.java
@@ -42,7 +42,7 @@
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate;
 import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.test.ChromeJUnit4RunnerDelegate;
 import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
index bc8c081..2ca3d1a 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/signin/AccountPickerBottomSheetTest.java
@@ -49,14 +49,14 @@
 import org.chromium.base.test.util.CommandLineFlags;
 import org.chromium.base.test.util.CriteriaHelper;
 import org.chromium.base.test.util.MetricsUtils.HistogramDelta;
-import org.chromium.chrome.R;
 import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncher;
 import org.chromium.chrome.browser.flags.ChromeFeatureList;
 import org.chromium.chrome.browser.flags.ChromeSwitches;
 import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate;
 import org.chromium.chrome.browser.preferences.ChromePreferenceKeys;
 import org.chromium.chrome.browser.preferences.SharedPreferencesManager;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetCoordinator;
+import org.chromium.chrome.browser.signin.ui.R;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetCoordinator;
 import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.browser.tabmodel.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModel;
diff --git a/chrome/app/chromeos_strings.grdp b/chrome/app/chromeos_strings.grdp
index 70c7ad6..4ba908a4 100644
--- a/chrome/app/chromeos_strings.grdp
+++ b/chrome/app/chromeos_strings.grdp
@@ -5014,16 +5014,13 @@
 
   <!-- Strings for Oobe fingerprint enrollment screen -->
   <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE" desc="The title of the dialog that allow users to register their fingerprint.">
-    Set up your fingerprint to unlock your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph> faster
+    Unlock faster with your fingerprint
   </message>
   <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_POWER_BUTTON_DESCRIPTION" desc="The label that explains that the fingerprint sensor is in the power button.">
-    Touch the power button with your finger
+    Touch the power button with your finger. Your data is stored securely and never leaves your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>.
   </message>
   <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_GENERAL_DESCRIPTION" desc="The label that explains the location of the fingerprint sensor on the device.">
-      Touch the fingerprint sensor with your finger
-  </message>
-  <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_FOOTER" desc="Footer message for the fingerprint setup screen">
-      Your fingerprint data is stored securely and never leaves your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>.
+    Touch the fingerprint sensor with your finger. Your data is stored securely and never leaves your <ph name="DEVICE_TYPE">$1<ex>Chromebook</ex></ph>.
   </message>
   <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_PROGRESS_TITLE" desc="The title of the dialog that shows where the fingerprint sensor is.">
     Lift, then touch again
@@ -5052,10 +5049,10 @@
   <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_NEW_FINGERPRINT_DEFAULT_NAME_3" desc="The default name for third newly added fingerprint.">
     Finger 3
   </message>
-  <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER" desc="Text in the fingerprint setup screen telling users what to move finger to capture the different parts of fingerprint.">
-    Move your finger slightly to add the different parts of your fingerprint.
+  <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER" desc="Text in the fingerprint setup screen telling users to lift their finger to capture the different parts of fingerprint.">
+    Keep lifting your finger to add the different parts of your fingerprint
   </message>
-  <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_TRY_AGAIN" desc="Text in the fingerprint setup screen telling users what to scan their finger again.">
+  <message name="IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_TRY_AGAIN" desc="Text in the fingerprint setup screen telling users to scan their finger again.">
     Try again.
   </message>
 
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_FOOTER.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_FOOTER.png.sha1
deleted file mode 100644
index adbbc65b..0000000
--- a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_FOOTER.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-11bc40ec49d69e06a5f1129da1ec43891c20d10e
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER.png.sha1
index 4e1bc54..47b8d26f 100644
--- a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER.png.sha1
+++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_INSTRUCTION_MOVE_FINGER.png.sha1
@@ -1 +1 @@
-0aa420cbdd6f271aa13288688e3fe83347f649b2
\ No newline at end of file
+40eafc15947667ce759612e53e37039ab57fde3a
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_DESCRIPTION.png.sha1
deleted file mode 100644
index 4e1bc54..0000000
--- a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_DESCRIPTION.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-0aa420cbdd6f271aa13288688e3fe83347f649b2
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_GENERAL_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_GENERAL_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..cf369e6
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_GENERAL_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+fc343e6f384fb9347d483de80e0722e70cb8540a
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_POWER_BUTTON_DESCRIPTION.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_POWER_BUTTON_DESCRIPTION.png.sha1
new file mode 100644
index 0000000..e5315d4
--- /dev/null
+++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_SENSOR_POWER_BUTTON_DESCRIPTION.png.sha1
@@ -0,0 +1 @@
+4b1e922d26d25d7bbd1d4f99c44a802f619a8116
\ No newline at end of file
diff --git a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE.png.sha1 b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE.png.sha1
index 64b6172..e5315d4 100644
--- a/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE.png.sha1
+++ b/chrome/app/chromeos_strings_grdp/IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE.png.sha1
@@ -1 +1 @@
-f256e5b231840df1d529f5694ef395226cdc477a
\ No newline at end of file
+4b1e922d26d25d7bbd1d4f99c44a802f619a8116
\ No newline at end of file
diff --git a/chrome/app/profiles_strings.grdp b/chrome/app/profiles_strings.grdp
index eff833b..2dff859d 100644
--- a/chrome/app/profiles_strings.grdp
+++ b/chrome/app/profiles_strings.grdp
@@ -765,7 +765,10 @@
       ...
     </message>
     <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE" desc="Profile picker profile type choice subtitle">
-      Sign in to Sync your bookmarks, passwords, history and more on all your devices
+      To access your Chrome stuff across all your devices, sign in, then turn on sync.
+    </message>
+    <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE_V2" desc="Profile picker profile type choice subtitle">
+      To access your Chrome stuff across all your devices, sign in so that you can turn on sync.
     </message>
     <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_SIGNIN_BUTTON_LABEL" desc="Label for a button that prompts user to sign in">
       Turn on sync...
@@ -785,11 +788,8 @@
     <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE" desc="Label of a button to finish the profile creation.">
       Done
     </message>
-    <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_OK" desc="Label of a button to confirm avatar selection.">
-      OK
-    </message>
-    <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_CANCEL" desc="Label of a button to cancel avatar selection.">
-      Cancel
+    <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE" desc="Label of a button to close avatar selection.">
+      Done
     </message>
     <message name="IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_INPUT_NAME" desc="Name of the input to configure the profile name in the profile customization window.">
       Add a name or a label like Work, Personal, or Kids
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_CANCEL.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_CANCEL.png.sha1
deleted file mode 100644
index 41c8f387..0000000
--- a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_CANCEL.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-16bfabb2890a322b958bc80c683251f779fdb9dd
\ No newline at end of file
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE.png.sha1
new file mode 100644
index 0000000..3b93cc9
--- /dev/null
+++ b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE.png.sha1
@@ -0,0 +1 @@
+5ba0789ffe586195c0e4a1e43480da46d73e44e7
\ No newline at end of file
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_OK.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_OK.png.sha1
deleted file mode 100644
index 41c8f387..0000000
--- a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_OK.png.sha1
+++ /dev/null
@@ -1 +0,0 @@
-16bfabb2890a322b958bc80c683251f779fdb9dd
\ No newline at end of file
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE.png.sha1
index 6fcb86e1..188313ce 100644
--- a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE.png.sha1
+++ b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE.png.sha1
@@ -1 +1 @@
-ff9106fc0cc3efef5eb51f7ba2ab0b799fa9b256
\ No newline at end of file
+d11144bc8bc505baf22f44152b590dc96c796574
\ No newline at end of file
diff --git a/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE_V2.png.sha1 b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE_V2.png.sha1
new file mode 100644
index 0000000..4a2c007
--- /dev/null
+++ b/chrome/app/profiles_strings_grdp/IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_PROFILE_TYPE_CHOICE_SUBTITLE_V2.png.sha1
@@ -0,0 +1 @@
+6cdbd1b209a8657e0a790d1ec671d522e0c54344
\ No newline at end of file
diff --git a/chrome/browser/DEPS b/chrome/browser/DEPS
index 0144889..fae08de0 100644
--- a/chrome/browser/DEPS
+++ b/chrome/browser/DEPS
@@ -59,6 +59,7 @@
   "+components/bookmarks/common",
   "+components/bookmarks/managed",
   "+components/bookmarks/test",
+  "+components/browser_ui/photo_picker",
   "+components/browser_ui/settings",
   "+components/browser_ui/util",
   "+components/browser_ui/widget",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc
index 89e5fcc..12c9c4c 100644
--- a/chrome/browser/about_flags.cc
+++ b/chrome/browser/about_flags.cc
@@ -200,6 +200,7 @@
 #include "chrome/browser/flags/android/chrome_feature_list.h"
 #include "chrome/browser/notifications/chime/android/features.h"
 #include "chrome/browser/webapps/android/features.h"
+#include "components/browser_ui/photo_picker/android/features.h"
 #include "components/browser_ui/site_settings/android/features.h"
 #include "components/external_intents/android/external_intents_feature_list.h"
 #else  // OS_ANDROID
@@ -2003,6 +2004,16 @@
          base::size(kOmniboxSearchEngineLogoLoupeEverywhereVariationConstant),
          nullptr}};
 
+const FeatureEntry::FeatureParam
+    kPhotoPickerVideoSupportEnabledWithAnimatedThumbnails[] = {
+        {"animate_thumbnails", "true"}};
+const FeatureEntry::FeatureVariation
+    kPhotoPickerVideoSupportFeatureVariations[] = {
+        {"(with animated thumbnails)",
+         kPhotoPickerVideoSupportEnabledWithAnimatedThumbnails,
+         base::size(kPhotoPickerVideoSupportEnabledWithAnimatedThumbnails),
+         nullptr}};
+
 const FeatureEntry::FeatureParam kTabbedAppOverflowMenuRegroupBackward[] = {
     {"action_bar", "backward_button"}};
 const FeatureEntry::FeatureParam kTabbedAppOverflowMenuRegroupShare[] = {
@@ -6252,7 +6263,10 @@
     {"photo-picker-video-support",
      flag_descriptions::kPhotoPickerVideoSupportName,
      flag_descriptions::kPhotoPickerVideoSupportDescription, kOsAndroid,
-     FEATURE_VALUE_TYPE(chrome::android::kPhotoPickerVideoSupport)},
+     FEATURE_WITH_PARAMS_VALUE_TYPE(
+         photo_picker::features::kPhotoPickerVideoSupport,
+         kPhotoPickerVideoSupportFeatureVariations,
+         "PhotoPickerVideoSupportFeatureVariations")},
 #endif  // defined(OS_ANDROID)
 
     {"freeze-user-agent", flag_descriptions::kFreezeUserAgentName,
diff --git a/chrome/browser/android/bookmarks/bookmark_bridge.cc b/chrome/browser/android/bookmarks/bookmark_bridge.cc
index 52ef5096..5cef7cc 100644
--- a/chrome/browser/android/bookmarks/bookmark_bridge.cc
+++ b/chrome/browser/android/bookmarks/bookmark_bridge.cc
@@ -757,7 +757,12 @@
   if (partner_bookmarks_shim_->IsPartnerBookmark(node)) {
     partner_bookmarks_shim_->RemoveBookmark(node);
   } else if (type == BookmarkType::BOOKMARK_TYPE_READING_LIST) {
-    reading_list_manager_->Delete(node->url());
+    // Inside the Delete method, node will be destroyed and node->url will be
+    // also destroyed. This causes heap-use-after-free at
+    // ReadingListModelImpl::RemoveEntryByURLImpl. To avoid the
+    // heap-use-after-free, make a copy of node->url() and use it.
+    GURL url(node->url());
+    reading_list_manager_->Delete(url);
   } else {
     bookmark_model_->Remove(node);
   }
diff --git a/chrome/browser/autofill/android/personal_data_manager_android.cc b/chrome/browser/autofill/android/personal_data_manager_android.cc
index 6609905..d05901b 100644
--- a/chrome/browser/autofill/android/personal_data_manager_android.cc
+++ b/chrome/browser/autofill/android/personal_data_manager_android.cc
@@ -648,7 +648,7 @@
   AutofillProfile* profile = personal_data_manager_->GetProfileByGUID(
       ConvertJavaStringToUTF8(env, jguid));
   if (profile)
-    personal_data_manager_->RecordUseOf(*profile);
+    personal_data_manager_->RecordUseOf(profile);
 }
 
 void PersonalDataManagerAndroid::SetProfileUseStatsForTesting(
@@ -692,7 +692,7 @@
   CreditCard* card = personal_data_manager_->GetCreditCardByGUID(
       ConvertJavaStringToUTF8(env, jguid));
   if (card)
-    personal_data_manager_->RecordUseOf(*card);
+    personal_data_manager_->RecordUseOf(card);
 }
 
 void PersonalDataManagerAndroid::SetCreditCardUseStatsForTesting(
diff --git a/chrome/browser/autofill/automated_tests/cache_replayer.cc b/chrome/browser/autofill/automated_tests/cache_replayer.cc
index 3b63617..ba98e55 100644
--- a/chrome/browser/autofill/automated_tests/cache_replayer.cc
+++ b/chrome/browser/autofill/automated_tests/cache_replayer.cc
@@ -218,11 +218,11 @@
     const std::vector<network::DataElement>* data_elements) {
   std::string result;
   for (const network::DataElement& element : *data_elements) {
-    DCHECK_EQ(element.type(), network::mojom::DataElementType::kBytes);
+    DCHECK_EQ(element.type(), network::DataElement::Tag::kBytes);
     // Provide the length of the bytes explicitly, not to rely on the null
     // termination.
-    result.append(element.bytes(),
-                  base::checked_cast<size_t>(element.length()));
+    const auto piece = element.As<network::DataElementBytes>().AsStringPiece();
+    result.append(piece.data(), piece.size());
   }
   return result;
 }
diff --git a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.cc b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.cc
index b5e8a5d..7b53b004 100644
--- a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.cc
+++ b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.cc
@@ -62,7 +62,7 @@
 constexpr VmCameraMicManager::NotificationType
     VmCameraMicManager::kCameraNotification;
 constexpr VmCameraMicManager::NotificationType
-    VmCameraMicManager::kCameraWithMicNotification;
+    VmCameraMicManager::kCameraAndMicNotification;
 
 VmCameraMicManager* VmCameraMicManager::Get() {
   static base::NoDestructor<VmCameraMicManager> manager;
@@ -169,23 +169,11 @@
   return false;
 }
 
-bool VmCameraMicManager::IsNotificationActive(DeviceType device) const {
+bool VmCameraMicManager::IsNotificationActive(
+    NotificationType notification) const {
   for (const auto& vm_info : vm_info_map_) {
-    const NotificationType& notification_type =
-        vm_info.second.notification_type();
-    switch (device) {
-      case DeviceType::kMic:
-        if (notification_type == kMicNotification) {
-          return true;
-        }
-        break;
-      case DeviceType::kCamera:
-        // Both the "camera only" and "camera and mic" notifications use the
-        // camera icon.
-        if (notification_type[static_cast<size_t>(DeviceType::kCamera)]) {
-          return true;
-        }
-        break;
+    if (vm_info.second.notification_type() == notification) {
+      return true;
     }
   }
   return false;
diff --git a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h
index 04f8fb7..1a4a092 100644
--- a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h
+++ b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager.h
@@ -43,6 +43,16 @@
     kMaxValue = kCamera,
   };
 
+  using NotificationType =
+      std::bitset<static_cast<size_t>(DeviceType::kMaxValue) + 1>;
+  static constexpr NotificationType kMicNotification{
+      1 << static_cast<size_t>(DeviceType::kMic)};
+  static constexpr NotificationType kCameraNotification{
+      1 << static_cast<size_t>(DeviceType::kCamera)};
+  static constexpr NotificationType kCameraAndMicNotification{
+      (1 << static_cast<size_t>(DeviceType::kMic)) |
+      (1 << static_cast<size_t>(DeviceType::kCamera))};
+
   class Observer : public base::CheckedObserver {
    public:
     virtual void OnVmCameraMicActiveChanged(VmCameraMicManager*) {}
@@ -64,27 +74,13 @@
   // Return true if any of the VMs is using the device. Note that if the camera
   // privacy switch is on, this always returns false for `kCamera`.
   bool IsDeviceActive(DeviceType device) const;
+  // Return true if any of the VMs is displaying the `notification`.
+  bool IsNotificationActive(NotificationType notification) const;
 
-  // When a VM is using both camera and mic, we only show a single "camera and
-  // mic" notification, which is considered a camera notification but not a mic
-  // notification because it uses the camera icon. So, if only "camera only" or
-  // "camera and mic" notifications are shown, this function returns true for
-  // `kCamera` but false for `kMic`. If a "mic only" notification is shown, this
-  // function returns true for `kMic`.
-  bool IsNotificationActive(DeviceType device) const;
  private:
   friend class VmCameraMicManagerTest;
 
-  using NotificationType =
-      std::bitset<static_cast<size_t>(DeviceType::kMaxValue) + 1>;
   static constexpr NotificationType kNoNotification{};
-  static constexpr NotificationType kMicNotification{
-      1 << static_cast<size_t>(DeviceType::kMic)};
-  static constexpr NotificationType kCameraNotification{
-      1 << static_cast<size_t>(DeviceType::kCamera)};
-  static constexpr NotificationType kCameraWithMicNotification{
-      (1 << static_cast<size_t>(DeviceType::kMic)) |
-      (1 << static_cast<size_t>(DeviceType::kCamera))};
 
   class VmInfo {
    public:
diff --git a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_unittest.cc b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_unittest.cc
index 778b2df..43274fca 100644
--- a/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_unittest.cc
+++ b/chrome/browser/chromeos/camera_mic/vm_camera_mic_manager_unittest.cc
@@ -27,6 +27,7 @@
 using testing::UnorderedElementsAre;
 using VmType = chromeos::VmCameraMicManager::VmType;
 using DeviceType = chromeos::VmCameraMicManager::DeviceType;
+using NotificationType = chromeos::VmCameraMicManager::NotificationType;
 
 constexpr VmType kCrostiniVm = VmType::kCrostiniVm;
 constexpr VmType kPluginVm = VmType::kPluginVm;
@@ -34,6 +35,13 @@
 constexpr DeviceType kCamera = DeviceType::kCamera;
 constexpr DeviceType kMic = DeviceType::kMic;
 
+constexpr NotificationType kMicNotification =
+    chromeos::VmCameraMicManager::kMicNotification;
+constexpr NotificationType kCameraNotification =
+    chromeos::VmCameraMicManager::kCameraNotification;
+constexpr NotificationType kCameraAndMicNotification =
+    chromeos::VmCameraMicManager::kCameraAndMicNotification;
+
 class FakeNotificationDisplayService : public NotificationDisplayService {
  public:
   FakeNotificationDisplayService() = default;
@@ -67,10 +75,18 @@
 
 struct IsActiveTestParam {
   ActiveMap active_map;
-  DeviceActiveMap device_expectations;
-  DeviceActiveMap notification_expectations;
+  // Device types that are expected to be active.
+  std::vector<DeviceType> device_expectations;
+  // Notification types that are expected to be active.
+  std::vector<NotificationType> notification_expectations;
 };
 
+template <typename T, typename V>
+bool contains(const T& container, const V& value) {
+  return std::find(container.begin(), container.end(), value) !=
+         container.end();
+}
+
 }  // namespace
 
 namespace chromeos {
@@ -78,25 +94,19 @@
 class VmCameraMicManagerTest : public testing::Test {
  public:
   // Define here to access `VmCameraMicManager` private members.
-  using NotificationType = VmCameraMicManager::NotificationType;
-  static constexpr NotificationType kMicNotification =
-      VmCameraMicManager::kMicNotification;
-  static constexpr NotificationType kCameraNotification =
-      VmCameraMicManager::kCameraNotification;
-  static constexpr NotificationType kCameraWithMicNotification =
-      VmCameraMicManager::kCameraWithMicNotification;
   struct NotificationTestParam {
     ActiveMap active_map;
     std::set<std::string> expected_notifications;
 
     NotificationTestParam(
         const ActiveMap& active_map,
-        const std::vector<std::pair<VmType, NotificationType>>& notifications) {
+        const std::vector<std::pair<VmType, NotificationType>>&
+            expected_notifications) {
       this->active_map = active_map;
-      for (const auto& vm_notification : notifications) {
-        auto result =
-            expected_notifications.insert(VmCameraMicManager::GetNotificationId(
-                vm_notification.first, vm_notification.second));
+      for (const auto& vm_notification : expected_notifications) {
+        auto result = this->expected_notifications.insert(
+            VmCameraMicManager::GetNotificationId(vm_notification.first,
+                                                  vm_notification.second));
         CHECK(result.second);
       }
     }
@@ -178,22 +188,26 @@
   SetCameraAccessing(kPluginVm, false);
   SetCameraPrivacyIsOn(kPluginVm, false);
   EXPECT_FALSE(vm_camera_mic_manager_->IsDeviceActive(kCamera));
-  EXPECT_FALSE(vm_camera_mic_manager_->IsNotificationActive(kCamera));
+  EXPECT_FALSE(
+      vm_camera_mic_manager_->IsNotificationActive(kCameraNotification));
 
   SetCameraAccessing(kPluginVm, true);
   SetCameraPrivacyIsOn(kPluginVm, false);
   EXPECT_TRUE(vm_camera_mic_manager_->IsDeviceActive(kCamera));
-  EXPECT_TRUE(vm_camera_mic_manager_->IsNotificationActive(kCamera));
+  EXPECT_TRUE(
+      vm_camera_mic_manager_->IsNotificationActive(kCameraNotification));
 
   SetCameraAccessing(kPluginVm, false);
   SetCameraPrivacyIsOn(kPluginVm, true);
   EXPECT_FALSE(vm_camera_mic_manager_->IsDeviceActive(kCamera));
-  EXPECT_FALSE(vm_camera_mic_manager_->IsNotificationActive(kCamera));
+  EXPECT_FALSE(
+      vm_camera_mic_manager_->IsNotificationActive(kCameraNotification));
 
   SetCameraAccessing(kPluginVm, true);
   SetCameraPrivacyIsOn(kPluginVm, true);
   EXPECT_FALSE(vm_camera_mic_manager_->IsDeviceActive(kCamera));
-  EXPECT_FALSE(vm_camera_mic_manager_->IsNotificationActive(kCamera));
+  EXPECT_FALSE(
+      vm_camera_mic_manager_->IsNotificationActive(kCameraNotification));
 }
 
 // Test `IsDeviceActive()` and `IsNotificationActive()`.
@@ -204,17 +218,15 @@
 TEST_P(VmCameraMicManagerIsActiveTest, IsNotificationActive) {
   SetActive(GetParam().active_map);
 
-  for (const auto& device_and_expectation : GetParam().device_expectations) {
-    EXPECT_EQ(
-        vm_camera_mic_manager_->IsDeviceActive(device_and_expectation.first),
-        device_and_expectation.second);
+  for (auto device : {kCamera, kMic}) {
+    EXPECT_EQ(vm_camera_mic_manager_->IsDeviceActive(device),
+              contains(GetParam().device_expectations, device));
   }
 
-  for (const auto& device_and_expectation :
-       GetParam().notification_expectations) {
-    EXPECT_EQ(vm_camera_mic_manager_->IsNotificationActive(
-                  device_and_expectation.first),
-              device_and_expectation.second);
+  for (auto notification :
+       {kCameraNotification, kMicNotification, kCameraAndMicNotification}) {
+    EXPECT_EQ(vm_camera_mic_manager_->IsNotificationActive(notification),
+              contains(GetParam().notification_expectations, notification));
   }
 }
 
@@ -227,32 +239,32 @@
                 {kCrostiniVm, {{kCamera, 0}, {kMic, 0}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 0}, {kMic, 0}},
-            /*notificatoin_expectations=*/{{kCamera, 0}, {kMic, 0}},
+            /*device_expectations=*/{},
+            /*notificatoin_expectations=*/{},
         },
         IsActiveTestParam{
             /*active_map=*/{
                 {kCrostiniVm, {{kCamera, 0}, {kMic, 0}}},
                 {kPluginVm, {{kCamera, 1}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 0}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 0}},
+            /*device_expectations=*/{kCamera},
+            /*notificatoin_expectations=*/{kCameraNotification},
         },
         IsActiveTestParam{
             /*active_map=*/{
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 0}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 0}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 0}},
+            /*device_expectations=*/{kCamera},
+            /*notificatoin_expectations=*/{kCameraNotification},
         },
         IsActiveTestParam{
             /*active_map=*/{
                 {kCrostiniVm, {{kCamera, 0}, {kMic, 1}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 0}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 0}, {kMic, 1}},
+            /*device_expectations=*/{kMic},
+            /*notificatoin_expectations=*/{kMicNotification},
         },
         // Only a crostini "camera icon" notification is displayed.
         IsActiveTestParam{
@@ -260,8 +272,8 @@
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 1}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 0}},
+            /*device_expectations=*/{kCamera, kMic},
+            /*notificatoin_expectations=*/{kCameraAndMicNotification},
         },
         // Crostini "camera icon" notification and pluginvm mic notification are
         // displayed.
@@ -270,8 +282,9 @@
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 1}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 1}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 1}},
+            /*device_expectations=*/{kCamera, kMic},
+            /*notificatoin_expectations=*/
+            {kCameraAndMicNotification, kMicNotification},
         },
         // Crostini "camera icon" notification and pluginvm camera notification
         // are displayed.
@@ -280,8 +293,9 @@
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 1}}},
                 {kPluginVm, {{kCamera, 1}, {kMic, 0}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 0}},
+            /*device_expectations=*/{kCamera, kMic},
+            /*notificatoin_expectations=*/
+            {kCameraAndMicNotification, kCameraNotification},
         },
         // Crostini camera notification and pluginvm mic notification are
         // displayed.
@@ -290,8 +304,9 @@
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 0}}},
                 {kPluginVm, {{kCamera, 0}, {kMic, 1}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 1}},
+            /*device_expectations=*/{kCamera, kMic},
+            /*notificatoin_expectations=*/
+            {kCameraNotification, kMicNotification},
         },
         // Crostini and pluginvm "camera icon" notifications are displayed.
         IsActiveTestParam{
@@ -299,8 +314,8 @@
                 {kCrostiniVm, {{kCamera, 1}, {kMic, 1}}},
                 {kPluginVm, {{kCamera, 1}, {kMic, 1}}},
             },
-            /*device_expectations=*/{{kCamera, 1}, {kMic, 1}},
-            /*notificatoin_expectations=*/{{kCamera, 1}, {kMic, 0}},
+            /*device_expectations=*/{kCamera, kMic},
+            /*notificatoin_expectations=*/{kCameraAndMicNotification},
         }));
 
 class VmCameraMicManagerNotificationTest
@@ -343,7 +358,7 @@
             /*expected_notifications=*/
             {
                 {kCrostiniVm, kCameraNotification},
-                {kPluginVm, kCameraWithMicNotification},
+                {kPluginVm, kCameraAndMicNotification},
             },
         },
     };
diff --git a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc
index 83fc0f2..9bdadfc2 100644
--- a/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc
+++ b/chrome/browser/chromeos/crosapi/ash_chrome_service_impl.cc
@@ -44,17 +44,12 @@
 AshChromeServiceImpl::AshChromeServiceImpl(
     mojo::PendingReceiver<mojom::AshChromeService> pending_receiver)
     : receiver_(this, std::move(pending_receiver)),
-      file_manager_ash_(std::make_unique<FileManagerAsh>()),
-      keystore_service_ash_(std::make_unique<KeystoreServiceAsh>()),
-      message_center_ash_(std::make_unique<MessageCenterAsh>()),
       metrics_reporting_ash_(std::make_unique<MetricsReportingAsh>(
           g_browser_process->local_state())),
       prefs_ash_(std::make_unique<PrefsAsh>(
           g_browser_process->local_state(),
           ProfileManager::GetPrimaryUserProfile()->GetPrefs())),
       screen_manager_ash_(std::make_unique<ScreenManagerAsh>()),
-      select_file_ash_(std::make_unique<SelectFileAsh>()),
-      feedback_ash_(std::make_unique<FeedbackAsh>()),
       cert_database_ash_(std::make_unique<CertDatabaseAsh>()),
       test_controller_ash_(std::make_unique<TestControllerAsh>()),
       clipboard_ash_(std::make_unique<ClipboardAsh>()) {
@@ -103,17 +98,25 @@
 
 void AshChromeServiceImpl::BindFileManager(
     mojo::PendingReceiver<crosapi::mojom::FileManager> receiver) {
-  file_manager_ash_->BindReceiver(std::move(receiver));
+  // TODO(https://crbug.com/1148448): Convert this to allow multiple,
+  // simultaneous crosapi clients. See BindScreenManager for an example.
+  file_manager_ash_ =
+      std::make_unique<crosapi::FileManagerAsh>(std::move(receiver));
 }
 
 void AshChromeServiceImpl::BindKeystoreService(
     mojo::PendingReceiver<crosapi::mojom::KeystoreService> receiver) {
-  keystore_service_ash_->BindReceiver(std::move(receiver));
+  // TODO(https://crbug.com/1148448): Convert this to allow multiple,
+  // simultaneous crosapi clients. See BindScreenManager for an example.
+  keystore_service_ash_ =
+      std::make_unique<crosapi::KeystoreServiceAsh>(std::move(receiver));
 }
 
 void AshChromeServiceImpl::BindMessageCenter(
     mojo::PendingReceiver<mojom::MessageCenter> receiver) {
-  message_center_ash_->BindReceiver(std::move(receiver));
+  // TODO(https://crbug.com/1148448): Convert this to allow multiple,
+  // simultaneous crosapi clients. See BindScreenManager for an example.
+  message_center_ash_ = std::make_unique<MessageCenterAsh>(std::move(receiver));
 }
 
 void AshChromeServiceImpl::BindMetricsReporting(
@@ -123,7 +126,9 @@
 
 void AshChromeServiceImpl::BindSelectFile(
     mojo::PendingReceiver<mojom::SelectFile> receiver) {
-  select_file_ash_->BindReceiver(std::move(receiver));
+  // TODO(https://crbug.com/1148448): Convert this to allow multiple,
+  // simultaneous crosapi clients. See BindScreenManager for an example.
+  select_file_ash_ = std::make_unique<SelectFileAsh>(std::move(receiver));
 }
 
 void AshChromeServiceImpl::BindScreenManager(
@@ -138,7 +143,9 @@
 
 void AshChromeServiceImpl::BindFeedback(
     mojo::PendingReceiver<mojom::Feedback> receiver) {
-  feedback_ash_->BindReceiver(std::move(receiver));
+  // TODO(https://crbug.com/1148448): Convert this to allow multiple,
+  // simultaneous crosapi clients. See BindScreenManager for an example.
+  feedback_ash_ = std::make_unique<FeedbackAsh>(std::move(receiver));
 }
 
 void AshChromeServiceImpl::BindMediaSessionController(
diff --git a/chrome/browser/chromeos/crosapi/feedback_ash.cc b/chrome/browser/chromeos/crosapi/feedback_ash.cc
index c558a86..5db2962 100644
--- a/chrome/browser/chromeos/crosapi/feedback_ash.cc
+++ b/chrome/browser/chromeos/crosapi/feedback_ash.cc
@@ -23,15 +23,11 @@
 
 }  // namespace
 
-FeedbackAsh::FeedbackAsh() = default;
+FeedbackAsh::FeedbackAsh(mojo::PendingReceiver<mojom::Feedback> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 FeedbackAsh::~FeedbackAsh() = default;
 
-void FeedbackAsh::BindReceiver(
-    mojo::PendingReceiver<mojom::Feedback> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void FeedbackAsh::ShowFeedbackPage(mojom::FeedbackInfoPtr feedback_info) {
   const user_manager::User* user =
       user_manager::UserManager::Get()->GetPrimaryUser();
diff --git a/chrome/browser/chromeos/crosapi/feedback_ash.h b/chrome/browser/chromeos/crosapi/feedback_ash.h
index 5695813..10e1cef 100644
--- a/chrome/browser/chromeos/crosapi/feedback_ash.h
+++ b/chrome/browser/chromeos/crosapi/feedback_ash.h
@@ -7,7 +7,7 @@
 
 #include "chromeos/crosapi/mojom/feedback.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace crosapi {
 
@@ -15,18 +15,16 @@
 // UI thread. Shows feedback page in response to mojo IPCs from lacros-chrome.
 class FeedbackAsh : public mojom::Feedback {
  public:
-  FeedbackAsh();
+  explicit FeedbackAsh(mojo::PendingReceiver<mojom::Feedback> receiver);
   FeedbackAsh(const FeedbackAsh&) = delete;
   FeedbackAsh& operator=(const FeedbackAsh&) = delete;
   ~FeedbackAsh() override;
 
-  void BindReceiver(mojo::PendingReceiver<mojom::Feedback> receiver);
-
   // crosapi::mojom::Feedback:
   void ShowFeedbackPage(mojom::FeedbackInfoPtr feedback_info) override;
 
  private:
-  mojo::ReceiverSet<mojom::Feedback> receivers_;
+  mojo::Receiver<mojom::Feedback> receiver_;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/file_manager_ash.cc b/chrome/browser/chromeos/crosapi/file_manager_ash.cc
index 5154446..7312bfb 100644
--- a/chrome/browser/chromeos/crosapi/file_manager_ash.cc
+++ b/chrome/browser/chromeos/crosapi/file_manager_ash.cc
@@ -67,15 +67,12 @@
 
 }  // namespace
 
-FileManagerAsh::FileManagerAsh() = default;
+FileManagerAsh::FileManagerAsh(
+    mojo::PendingReceiver<mojom::FileManager> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 FileManagerAsh::~FileManagerAsh() = default;
 
-void FileManagerAsh::BindReceiver(
-    mojo::PendingReceiver<mojom::FileManager> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void FileManagerAsh::DeprecatedShowItemInFolder(const base::FilePath& path) {
   Profile* primary_profile = ProfileManager::GetPrimaryUserProfile();
   base::FilePath final_path = ExpandPath(primary_profile, path);
diff --git a/chrome/browser/chromeos/crosapi/file_manager_ash.h b/chrome/browser/chromeos/crosapi/file_manager_ash.h
index 61e1c41..cf5e325 100644
--- a/chrome/browser/chromeos/crosapi/file_manager_ash.h
+++ b/chrome/browser/chromeos/crosapi/file_manager_ash.h
@@ -7,7 +7,7 @@
 
 #include "chromeos/crosapi/mojom/file_manager.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace crosapi {
 
@@ -16,13 +16,11 @@
 // manager, for example to open a folder or highlight a file.
 class FileManagerAsh : public mojom::FileManager {
  public:
-  FileManagerAsh();
+  explicit FileManagerAsh(mojo::PendingReceiver<mojom::FileManager> receiver);
   FileManagerAsh(const FileManagerAsh&) = delete;
   FileManagerAsh& operator=(const FileManagerAsh&) = delete;
   ~FileManagerAsh() override;
 
-  void BindReceiver(mojo::PendingReceiver<mojom::FileManager> receiver);
-
   // crosapi::mojom::FileManager:
   void DeprecatedShowItemInFolder(const base::FilePath& path) override;
   void ShowItemInFolder(const base::FilePath& path,
@@ -32,7 +30,7 @@
   void OpenFile(const base::FilePath& path, OpenFileCallback callback) override;
 
  private:
-  mojo::ReceiverSet<mojom::FileManager> receivers_;
+  mojo::Receiver<mojom::FileManager> receiver_;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/keystore_service_ash.cc b/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
index 2c07ac9..d6289bce 100644
--- a/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
+++ b/chrome/browser/chromeos/crosapi/keystore_service_ash.cc
@@ -62,7 +62,9 @@
 
 }  // namespace
 
-KeystoreServiceAsh::KeystoreServiceAsh() {
+KeystoreServiceAsh::KeystoreServiceAsh(
+    mojo::PendingReceiver<mojom::KeystoreService> receiver)
+    : receiver_(this, std::move(receiver)) {
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
@@ -70,11 +72,6 @@
   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
 }
 
-void KeystoreServiceAsh::BindReceiver(
-    mojo::PendingReceiver<mojom::KeystoreService> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void KeystoreServiceAsh::ChallengeAttestationOnlyKeystore(
     const std::string& challenge,
     mojom::KeystoreType type,
diff --git a/chrome/browser/chromeos/crosapi/keystore_service_ash.h b/chrome/browser/chromeos/crosapi/keystore_service_ash.h
index df5b729..e9f56fc 100644
--- a/chrome/browser/chromeos/crosapi/keystore_service_ash.h
+++ b/chrome/browser/chromeos/crosapi/keystore_service_ash.h
@@ -12,7 +12,7 @@
 #include "chrome/browser/chromeos/platform_keys/platform_keys.h"
 #include "chromeos/crosapi/mojom/keystore_service.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace chromeos {
 namespace attestation {
@@ -28,13 +28,12 @@
 // system keystores. This class is affine to the UI thread.
 class KeystoreServiceAsh : public mojom::KeystoreService {
  public:
-  KeystoreServiceAsh();
+  explicit KeystoreServiceAsh(
+      mojo::PendingReceiver<mojom::KeystoreService> receiver);
   KeystoreServiceAsh(const KeystoreServiceAsh&) = delete;
   KeystoreServiceAsh& operator=(const KeystoreServiceAsh&) = delete;
   ~KeystoreServiceAsh() override;
 
-  void BindReceiver(mojo::PendingReceiver<mojom::KeystoreService> receiver);
-
   // mojom::KeystoreService:
   using KeystoreType = mojom::KeystoreType;
   void ChallengeAttestationOnlyKeystore(
@@ -82,7 +81,7 @@
   // Container to keep outstanding challenges alive.
   std::vector<std::unique_ptr<chromeos::attestation::TpmChallengeKey>>
       outstanding_challenges_;
-  mojo::ReceiverSet<mojom::KeystoreService> receivers_;
+  mojo::Receiver<mojom::KeystoreService> receiver_;
 
   base::WeakPtrFactory<KeystoreServiceAsh> weak_factory_{this};
 };
diff --git a/chrome/browser/chromeos/crosapi/message_center_ash.cc b/chrome/browser/chromeos/crosapi/message_center_ash.cc
index 2127758..e9dbf421 100644
--- a/chrome/browser/chromeos/crosapi/message_center_ash.cc
+++ b/chrome/browser/chromeos/crosapi/message_center_ash.cc
@@ -156,15 +156,12 @@
 
 }  // namespace
 
-MessageCenterAsh::MessageCenterAsh() = default;
+MessageCenterAsh::MessageCenterAsh(
+    mojo::PendingReceiver<mojom::MessageCenter> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 MessageCenterAsh::~MessageCenterAsh() = default;
 
-void MessageCenterAsh::BindReceiver(
-    mojo::PendingReceiver<mojom::MessageCenter> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void MessageCenterAsh::DisplayNotification(
     mojom::NotificationPtr notification,
     mojo::PendingRemote<mojom::NotificationDelegate> delegate) {
diff --git a/chrome/browser/chromeos/crosapi/message_center_ash.h b/chrome/browser/chromeos/crosapi/message_center_ash.h
index 2464166..7379e53 100644
--- a/chrome/browser/chromeos/crosapi/message_center_ash.h
+++ b/chrome/browser/chromeos/crosapi/message_center_ash.h
@@ -7,7 +7,7 @@
 
 #include "chromeos/crosapi/mojom/message_center.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace crosapi {
 
@@ -16,13 +16,12 @@
 // Sends reply IPCs when the user interacts with the notifications.
 class MessageCenterAsh : public mojom::MessageCenter {
  public:
-  MessageCenterAsh();
+  explicit MessageCenterAsh(
+      mojo::PendingReceiver<mojom::MessageCenter> receiver);
   MessageCenterAsh(const MessageCenterAsh&) = delete;
   MessageCenterAsh& operator=(const MessageCenterAsh&) = delete;
   ~MessageCenterAsh() override;
 
-  void BindReceiver(mojo::PendingReceiver<mojom::MessageCenter> receiver);
-
   // crosapi::mojom::MessageCenter:
   void DisplayNotification(
       mojom::NotificationPtr notification,
@@ -32,7 +31,7 @@
       GetDisplayedNotificationsCallback callback) override;
 
  private:
-  mojo::ReceiverSet<mojom::MessageCenter> receivers_;
+  mojo::Receiver<mojom::MessageCenter> receiver_;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/crosapi/message_center_ash_unittest.cc b/chrome/browser/chromeos/crosapi/message_center_ash_unittest.cc
index a9c98bf..27a5b43 100644
--- a/chrome/browser/chromeos/crosapi/message_center_ash_unittest.cc
+++ b/chrome/browser/chromeos/crosapi/message_center_ash_unittest.cc
@@ -84,8 +84,7 @@
   // testing::Test:
   void SetUp() override {
     message_center::MessageCenter::Initialize();
-    message_center_ash_ = std::make_unique<MessageCenterAsh>();
-    message_center_ash_->BindReceiver(
+    message_center_ash_ = std::make_unique<MessageCenterAsh>(
         message_center_remote_.BindNewPipeAndPassReceiver());
   }
 
diff --git a/chrome/browser/chromeos/crosapi/select_file_ash.cc b/chrome/browser/chromeos/crosapi/select_file_ash.cc
index 77e36eee8..d109e02 100644
--- a/chrome/browser/chromeos/crosapi/select_file_ash.cc
+++ b/chrome/browser/chromeos/crosapi/select_file_ash.cc
@@ -167,15 +167,12 @@
 
 }  // namespace
 
-SelectFileAsh::SelectFileAsh() = default;
+// TODO(https://crbug.com/1090587): Connection error handling.
+SelectFileAsh::SelectFileAsh(mojo::PendingReceiver<mojom::SelectFile> receiver)
+    : receiver_(this, std::move(receiver)) {}
 
 SelectFileAsh::~SelectFileAsh() = default;
 
-void SelectFileAsh::BindReceiver(
-    mojo::PendingReceiver<mojom::SelectFile> receiver) {
-  receivers_.Add(this, std::move(receiver));
-}
-
 void SelectFileAsh::Select(mojom::SelectFileOptionsPtr options,
                            SelectCallback callback) {
   aura::Window* owner_window = nullptr;
diff --git a/chrome/browser/chromeos/crosapi/select_file_ash.h b/chrome/browser/chromeos/crosapi/select_file_ash.h
index 58c78ce2..28509dc 100644
--- a/chrome/browser/chromeos/crosapi/select_file_ash.h
+++ b/chrome/browser/chromeos/crosapi/select_file_ash.h
@@ -7,7 +7,7 @@
 
 #include "chromeos/crosapi/mojom/select_file.mojom.h"
 #include "mojo/public/cpp/bindings/pending_receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
+#include "mojo/public/cpp/bindings/receiver.h"
 
 namespace crosapi {
 
@@ -16,19 +16,17 @@
 // file manager to provide the dialogs. Lives on the UI thread.
 class SelectFileAsh : public mojom::SelectFile {
  public:
-  SelectFileAsh();
+  explicit SelectFileAsh(mojo::PendingReceiver<mojom::SelectFile> receiver);
   SelectFileAsh(const SelectFileAsh&) = delete;
   SelectFileAsh& operator=(const SelectFileAsh&) = delete;
   ~SelectFileAsh() override;
 
-  void BindReceiver(mojo::PendingReceiver<mojom::SelectFile> receiver);
-
   // crosapi::mojom::SelectFile:
   void Select(mojom::SelectFileOptionsPtr options,
               SelectCallback callback) override;
 
  private:
-  mojo::ReceiverSet<mojom::SelectFile> receivers_;
+  mojo::Receiver<mojom::SelectFile> receiver_;
 };
 
 }  // namespace crosapi
diff --git a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
index 138eab9..8ecebe1 100644
--- a/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
+++ b/chrome/browser/chromeos/file_manager/file_manager_jstest.cc
@@ -25,11 +25,11 @@
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ActionsSubmenuTest) {
-  RunTestURL("foreground/js/ui/actions_submenu_unittest_gen.html");
+  RunTestURL("foreground/js/ui/actions_submenu_unittest.m_gen.html");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, Breadcrumb) {
-  RunTestURL("foreground/js/ui/breadcrumb_unittest_gen.html");
+  RunTestURL("foreground/js/ui/breadcrumb_unittest.m_gen.html");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ContentMetadataProvider) {
@@ -169,7 +169,8 @@
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, InstallLinuxPackageDialogTest) {
-  RunTestURL("foreground/js/ui/install_linux_package_dialog_unittest_gen.html");
+  RunTestURL(
+      "foreground/js/ui/install_linux_package_dialog_unittest.m_gen.html");
 }
 
 IN_PROC_BROWSER_TEST_F(FileManagerJsTest, ListThumbnailLoader) {
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
index 1e469df7..04f2a7e 100644
--- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
+++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.cc
@@ -17,11 +17,84 @@
 
 namespace {
 
-bool IsFilesApp(const GURL& url) {
+bool IsFilesApp(const ui::DataTransferEndpoint* const data_dst) {
+  if (!data_dst || !data_dst->IsUrlType())
+    return false;
+
+  GURL url = data_dst->origin()->GetURL();
   return url.has_scheme() && url.SchemeIs(extensions::kExtensionScheme) &&
          url.has_host() && url.host() == extension_misc::kFilesManagerAppId;
 }
 
+bool IsClipboardHistory(const ui::DataTransferEndpoint* const data_dst) {
+  return data_dst && data_dst->type() == ui::EndpointType::kClipboardHistory;
+}
+
+DlpRulesManager::Level IsDataTransferAllowed(
+    const DlpRulesManager& dlp_rules_manager,
+    const ui::DataTransferEndpoint* const data_src,
+    const ui::DataTransferEndpoint* const data_dst) {
+  if (!data_src || !data_src->IsUrlType()) {  // Currently we only handle URLs.
+    return DlpRulesManager::Level::kAllow;
+  }
+
+  const GURL src_url = data_src->origin()->GetURL();
+  ui::EndpointType dst_type =
+      data_dst ? data_dst->type() : ui::EndpointType::kDefault;
+
+  DlpRulesManager::Level level = DlpRulesManager::Level::kAllow;
+
+  switch (dst_type) {
+    case ui::EndpointType::kDefault:
+    case ui::EndpointType::kUnknownVm:
+    case ui::EndpointType::kBorealis: {
+      // Passing empty URL will return restricted if there's a rule restricting
+      // the src against any dst (*), otherwise it will return ALLOW.
+      level = dlp_rules_manager.IsRestrictedDestination(
+          src_url, GURL(), DlpRulesManager::Restriction::kClipboard);
+      break;
+    }
+
+    case ui::EndpointType::kUrl: {
+      GURL dst_url = data_dst->origin()->GetURL();
+      level = dlp_rules_manager.IsRestrictedDestination(
+          src_url, dst_url, DlpRulesManager::Restriction::kClipboard);
+      break;
+    }
+
+    case ui::EndpointType::kCrostini: {
+      level = dlp_rules_manager.IsRestrictedComponent(
+          src_url, DlpRulesManager::Component::kCrostini,
+          DlpRulesManager::Restriction::kClipboard);
+      break;
+    }
+
+    case ui::EndpointType::kPluginVm: {
+      level = dlp_rules_manager.IsRestrictedComponent(
+          src_url, DlpRulesManager::Component::kPluginVm,
+          DlpRulesManager::Restriction::kClipboard);
+      break;
+    }
+
+    case ui::EndpointType::kArc: {
+      level = dlp_rules_manager.IsRestrictedComponent(
+          src_url, DlpRulesManager::Component::kArc,
+          DlpRulesManager::Restriction::kClipboard);
+      break;
+    }
+
+    case ui::EndpointType::kClipboardHistory: {
+      level = DlpRulesManager::Level::kAllow;
+      break;
+    }
+
+    default:
+      NOTREACHED();
+  }
+
+  return level;
+}
+
 }  // namespace
 
 // static
@@ -33,70 +106,17 @@
 bool DataTransferDlpController::IsClipboardReadAllowed(
     const ui::DataTransferEndpoint* const data_src,
     const ui::DataTransferEndpoint* const data_dst) {
-  if (!data_src || !data_src->IsUrlType()) {  // Currently we only handle URLs.
-    return true;
-  }
+  DlpRulesManager::Level level =
+      IsDataTransferAllowed(dlp_rules_manager_, data_src, data_dst);
 
-  const GURL src_url = data_src->origin()->GetURL();
-  DlpRulesManager::Level level = DlpRulesManager::Level::kAllow;
   bool notify_on_paste = !data_dst || data_dst->notify_if_restricted();
-  ui::EndpointType dst_type =
-      data_dst ? data_dst->type() : ui::EndpointType::kDefault;
-
-  switch (dst_type) {
-    case ui::EndpointType::kDefault:
-    case ui::EndpointType::kUnknownVm:
-    case ui::EndpointType::kBorealis: {
-      // Passing empty URL will return restricted if there's a rule restricting
-      // the src against any dst (*), otherwise it will return ALLOW.
-      level = dlp_rules_manager_.IsRestrictedDestination(
-          src_url, GURL(), DlpRulesManager::Restriction::kClipboard);
-      break;
-    }
-
-    case ui::EndpointType::kUrl: {
-      GURL dst_url = data_dst->origin()->GetURL();
-      level = dlp_rules_manager_.IsRestrictedDestination(
-          src_url, dst_url, DlpRulesManager::Restriction::kClipboard);
-      // Files Apps continously reads the clipboard data which triggers a lot of
-      // notifications while the user isn't actually initiating any copy/paste.
-      // TODO(crbug.com/1152475): Find a better way to handle File app.
-      if (IsFilesApp(dst_url))
-        notify_on_paste = false;
-      break;
-    }
-
-    case ui::EndpointType::kCrostini: {
-      level = dlp_rules_manager_.IsRestrictedComponent(
-          src_url, DlpRulesManager::Component::kCrostini,
-          DlpRulesManager::Restriction::kClipboard);
-      break;
-    }
-
-    case ui::EndpointType::kPluginVm: {
-      level = dlp_rules_manager_.IsRestrictedComponent(
-          src_url, DlpRulesManager::Component::kPluginVm,
-          DlpRulesManager::Restriction::kClipboard);
-      break;
-    }
-
-    case ui::EndpointType::kArc: {
-      level = dlp_rules_manager_.IsRestrictedComponent(
-          src_url, DlpRulesManager::Component::kArc,
-          DlpRulesManager::Restriction::kClipboard);
-      break;
-    }
-
-    case ui::EndpointType::kClipboardHistory: {
-      // When ClipboardHistory tries to read the clipboard we should allow it
-      // silently.
-      notify_on_paste = false;
-      break;
-    }
-
-    default:
-      NOTREACHED();
-  }
+  // Files Apps continuously reads the clipboard data which triggers a lot of
+  // notifications while the user isn't actually initiating any copy/paste.
+  // TODO(crbug.com/1152475): Find a better way to handle File app.
+  // When ClipboardHistory tries to read the clipboard we should allow it
+  // silently.
+  if (IsFilesApp(data_dst) || IsClipboardHistory(data_dst))
+    notify_on_paste = false;
 
   if (level == DlpRulesManager::Level::kBlock && notify_on_paste) {
     DoNotifyBlockedPaste(data_src, data_dst);
@@ -107,9 +127,16 @@
 
 bool DataTransferDlpController::IsDragDropAllowed(
     const ui::DataTransferEndpoint* const data_src,
-    const ui::DataTransferEndpoint* const data_dst) {
-  // TODO(crbug.com/1160656): Migrate off using `IsClipboardReadAllowed`.
-  return IsClipboardReadAllowed(data_src, data_dst);
+    const ui::DataTransferEndpoint* const data_dst,
+    const bool is_drop) {
+  DlpRulesManager::Level level =
+      IsDataTransferAllowed(dlp_rules_manager_, data_src, data_dst);
+
+  if (level == DlpRulesManager::Level::kBlock && is_drop) {
+    DoNotifyBlockedPaste(data_src, data_dst);
+  }
+
+  return level == DlpRulesManager::Level::kAllow;
 }
 
 DataTransferDlpController::DataTransferDlpController(
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h
index 7e132ba..19d8f91 100644
--- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h
+++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller.h
@@ -36,9 +36,9 @@
   bool IsClipboardReadAllowed(
       const ui::DataTransferEndpoint* const data_src,
       const ui::DataTransferEndpoint* const data_dst) override;
-  bool IsDragDropAllowed(
-      const ui::DataTransferEndpoint* const data_src,
-      const ui::DataTransferEndpoint* const data_dst) override;
+  bool IsDragDropAllowed(const ui::DataTransferEndpoint* const data_src,
+                         const ui::DataTransferEndpoint* const data_dst,
+                         const bool is_drop) override;
 
  protected:
   explicit DataTransferDlpController(const DlpRulesManager& dlp_rules_manager);
diff --git a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc
index 7d93a88..eee3b22 100644
--- a/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc
+++ b/chrome/browser/chromeos/policy/dlp/data_transfer_dlp_controller_unittest.cc
@@ -82,34 +82,53 @@
 
 TEST_F(DataTransferDlpControllerTest, NullSrc) {
   EXPECT_EQ(true, dlp_controller_.IsClipboardReadAllowed(nullptr, nullptr));
+  EXPECT_EQ(true, dlp_controller_.IsDragDropAllowed(nullptr, nullptr,
+                                                    /*is_drop=*/false));
 }
 
 TEST_F(DataTransferDlpControllerTest, NullDst) {
   ui::DataTransferEndpoint data_src(url::Origin::Create(GURL(kGoogleUrl)));
-  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
-  EXPECT_EQ(false, dlp_controller_.IsClipboardReadAllowed(&data_src, nullptr));
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, nullptr));
+  }
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_EQ(false, dlp_controller_.IsDragDropAllowed(&data_src, nullptr,
+                                                       /*is_drop=*/false));
+  }
 }
 
 TEST_F(DataTransferDlpControllerTest, DefaultDst) {
   ui::DataTransferEndpoint data_src(url::Origin::Create(GURL(kGoogleUrl)));
-  ui::DataTransferEndpoint data_dst_1(ui::EndpointType::kDefault);
-  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_1));
-  testing::Mock::VerifyAndClearExpectations(&rules_manager_);
-  testing::Mock::VerifyAndClearExpectations(&dlp_controller_);
-
-  // Turn off notifications
-  ui::DataTransferEndpoint data_dst_2(ui::EndpointType::kDefault,
-                                      /*notify_if_restricted=*/false);
-  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_2));
+  ui::DataTransferEndpoint data_dst(ui::EndpointType::kDefault);
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  }
+  {
+    // Turn off notifications
+    ui::DataTransferEndpoint data_dst_2(ui::EndpointType::kDefault,
+                                        /*notify_if_restricted=*/false);
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_2));
+  }
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false, dlp_controller_.IsDragDropAllowed(&data_src, &data_dst,
+                                                       /*is_drop=*/true));
+  }
 }
 
 TEST_F(DataTransferDlpControllerTest, ClipboardHistoryDst) {
@@ -120,42 +139,67 @@
 
 TEST_F(DataTransferDlpControllerTest, UrlSrcDst) {
   ui::DataTransferEndpoint data_src(url::Origin::Create(GURL(kGoogleUrl)));
-  ui::DataTransferEndpoint data_dst_1(url::Origin::Create(GURL(kYoutubeUrl)));
-  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_1));
-  testing::Mock::VerifyAndClearExpectations(&rules_manager_);
-  testing::Mock::VerifyAndClearExpectations(&dlp_controller_);
-
-  // Turn off notifications
-  ui::DataTransferEndpoint data_dst_2(url::Origin::Create(GURL(kYoutubeUrl)),
-                                      /*notify_if_restricted=*/false);
-  EXPECT_CALL(rules_manager_, IsRestrictedDestination)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_2));
+  ui::DataTransferEndpoint data_dst(url::Origin::Create(GURL(kYoutubeUrl)));
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  }
+  {
+    // Turn off notifications
+    ui::DataTransferEndpoint data_dst_2(url::Origin::Create(GURL(kYoutubeUrl)),
+                                        /*notify_if_restricted=*/false);
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst_2));
+  }
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedDestination)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_EQ(false, dlp_controller_.IsDragDropAllowed(&data_src, &data_dst,
+                                                       /*is_drop=*/false));
+  }
 }
 
 TEST_F(DataTransferDlpControllerTest, ArcDst) {
   ui::DataTransferEndpoint data_src(url::Origin::Create(GURL(kGoogleUrl)));
   ui::DataTransferEndpoint data_dst(ui::EndpointType::kArc);
-  EXPECT_CALL(rules_manager_, IsRestrictedComponent)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedComponent)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  }
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedComponent)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false, dlp_controller_.IsDragDropAllowed(&data_src, &data_dst,
+                                                       /*is_drop=*/true));
+  }
 }
 
 TEST_F(DataTransferDlpControllerTest, CrostiniDst) {
   ui::DataTransferEndpoint data_src(url::Origin::Create(GURL(kGoogleUrl)));
   ui::DataTransferEndpoint data_dst(ui::EndpointType::kCrostini);
-  EXPECT_CALL(rules_manager_, IsRestrictedComponent)
-      .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
-  EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
-  EXPECT_EQ(false,
-            dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedComponent)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false,
+              dlp_controller_.IsClipboardReadAllowed(&data_src, &data_dst));
+  }
+  {
+    EXPECT_CALL(rules_manager_, IsRestrictedComponent)
+        .WillOnce(testing::Return(DlpRulesManager::Level::kBlock));
+    EXPECT_CALL(dlp_controller_, DoNotifyBlockedPaste);
+    EXPECT_EQ(false, dlp_controller_.IsDragDropAllowed(&data_src, &data_dst,
+                                                       /*is_drop=*/true));
+  }
 }
 
 }  // namespace policy
diff --git a/chrome/browser/devtools/devtools_ui_bindings.cc b/chrome/browser/devtools/devtools_ui_bindings.cc
index dbb6472c..d1f684b 100644
--- a/chrome/browser/devtools/devtools_ui_bindings.cc
+++ b/chrome/browser/devtools/devtools_ui_bindings.cc
@@ -140,6 +140,8 @@
 static const char kDevToolsCssEditorOpenedHistogram[] =
     "DevTools.CssEditorOpened";
 static const char kDevToolsIssueCreatedHistogram[] = "DevTools.IssueCreated";
+static const char kDevToolsDeveloperResourceLoadedHistogram[] =
+    "DevTools.DeveloperResourceLoaded";
 
 static const char kRemotePageActionInspect[] = "inspect";
 static const char kRemotePageActionReload[] = "reload";
@@ -1315,7 +1317,8 @@
       name == kDevtoolsIssuesPanelResourceOpenedHistogram ||
       name == kDevToolsGridOverlayOpenedFromHistogram ||
       name == kDevToolsCssEditorOpenedHistogram ||
-      name == kDevToolsIssueCreatedHistogram)
+      name == kDevToolsIssueCreatedHistogram ||
+      name == kDevToolsDeveloperResourceLoadedHistogram)
     base::UmaHistogramExactLinear(name, sample, boundary_value);
   else
     frontend_host_->BadMessageReceived();
diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc
index a072dac..8c8f6d9 100644
--- a/chrome/browser/flags/android/chrome_feature_list.cc
+++ b/chrome/browser/flags/android/chrome_feature_list.cc
@@ -25,6 +25,7 @@
 #include "components/autofill/core/common/autofill_payments_features.h"
 #include "components/autofill_assistant/browser/features.h"
 #include "components/browser_sync/browser_sync_switches.h"
+#include "components/browser_ui/photo_picker/android/features.h"
 #include "components/data_reduction_proxy/core/common/data_reduction_proxy_features.h"
 #include "components/download/public/common/download_features.h"
 #include "components/embedder_support/android/util/cdn_utils.h"
@@ -191,12 +192,9 @@
     &kInlineUpdateFlow,
     &kInstantStart,
     &kKitKatSupported,
-    &kNewPhotoPicker,
     &kNotificationSuspender,
     &kOfflineIndicatorV2,
     &kOmniboxSpareRenderer,
-    &kPhotoPickerVideoSupport,
-    &kPhotoPickerZoom,
     &kProbabilisticCryptidRenderer,
     &kReachedCodeProfiler,
     &kReaderModeInCCT,
@@ -283,6 +281,7 @@
     &password_manager::features::kRecoverFromNeverSaveAndroid,
     &performance_hints::features::kContextMenuPerformanceInfo,
     &performance_hints::features::kPageInfoPerformanceHints,
+    &photo_picker::features::kPhotoPickerVideoSupport,
     &query_tiles::features::kQueryTilesGeoFilter,
     &query_tiles::features::kQueryTiles,
     &query_tiles::features::kQueryTilesInNTP,
@@ -542,9 +541,6 @@
 const base::Feature kSearchEnginePromoNewDevice{
     "SearchEnginePromo.NewDevice", base::FEATURE_ENABLED_BY_DEFAULT};
 
-const base::Feature kNewPhotoPicker{"NewPhotoPicker",
-                                    base::FEATURE_ENABLED_BY_DEFAULT};
-
 // TODO(knollr): This is a temporary kill switch, it can be removed once we feel
 // okay about leaving it on.
 const base::Feature kNotificationSuspender{"NotificationSuspender",
@@ -556,12 +552,6 @@
 const base::Feature kOmniboxSpareRenderer{"OmniboxSpareRenderer",
                                           base::FEATURE_DISABLED_BY_DEFAULT};
 
-const base::Feature kPhotoPickerVideoSupport{"PhotoPickerVideoSupport",
-                                             base::FEATURE_DISABLED_BY_DEFAULT};
-
-const base::Feature kPhotoPickerZoom{"PhotoPickerZoom",
-                                     base::FEATURE_ENABLED_BY_DEFAULT};
-
 const base::Feature kProbabilisticCryptidRenderer{
     "ProbabilisticCryptidRenderer", base::FEATURE_DISABLED_BY_DEFAULT};
 
diff --git a/chrome/browser/flags/android/chrome_feature_list.h b/chrome/browser/flags/android/chrome_feature_list.h
index 740781d9..458f9e14 100644
--- a/chrome/browser/flags/android/chrome_feature_list.h
+++ b/chrome/browser/flags/android/chrome_feature_list.h
@@ -90,12 +90,9 @@
 extern const base::Feature kInstantStart;
 extern const base::Feature kKitKatSupported;
 extern const base::Feature kLanguagesPreference;
-extern const base::Feature kNewPhotoPicker;
 extern const base::Feature kNotificationSuspender;
 extern const base::Feature kOfflineIndicatorV2;
 extern const base::Feature kOmniboxSpareRenderer;
-extern const base::Feature kPhotoPickerVideoSupport;
-extern const base::Feature kPhotoPickerZoom;
 extern const base::Feature kProbabilisticCryptidRenderer;
 extern const base::Feature kReachedCodeProfiler;
 extern const base::Feature kReengagementNotification;
diff --git a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
index 42fbe65..5c09279 100644
--- a/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
+++ b/chrome/browser/flags/android/java/src/org/chromium/chrome/browser/flags/ChromeFeatureList.java
@@ -345,7 +345,6 @@
     public static final String MOBILE_IDENTITY_CONSISTENCY_VAR = "MobileIdentityConsistencyVar";
     public static final String MODAL_PERMISSION_DIALOG_VIEW = "ModalPermissionDialogView";
     public static final String METRICS_SETTINGS_ANDROID = "MetricsSettingsAndroid";
-    public static final String NEW_PHOTO_PICKER = "NewPhotoPicker";
     public static final String NOTIFICATION_SUSPENDER = "NotificationSuspender";
     public static final String OFFLINE_INDICATOR = "OfflineIndicator";
     public static final String OFFLINE_INDICATOR_ALWAYS_HTTP_PROBE =
@@ -377,7 +376,6 @@
     public static final String PASSWORD_SCRIPTS_FETCHING = "PasswordScriptsFetching";
     public static final String PERMISSION_DELEGATION = "PermissionDelegation";
     public static final String PHOTO_PICKER_VIDEO_SUPPORT = "PhotoPickerVideoSupport";
-    public static final String PHOTO_PICKER_ZOOM = "PhotoPickerZoom";
     public static final String PORTALS = "Portals";
     public static final String PORTALS_CROSS_ORIGIN = "PortalsCrossOrigin";
     public static final String PREDICTIVE_PREFETCHING_ALLOWED_ON_ALL_CONNECTION_TYPES =
diff --git a/chrome/browser/privacy_sandbox/android/BUILD.gn b/chrome/browser/privacy_sandbox/android/BUILD.gn
index 34e0cfc..c2393f1 100644
--- a/chrome/browser/privacy_sandbox/android/BUILD.gn
+++ b/chrome/browser/privacy_sandbox/android/BUILD.gn
@@ -10,9 +10,14 @@
     "//chrome/android:chrome_all_java",
     "//chrome/android:chrome_java",
   ]
-  sources = [ "java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java" ]
+  sources = [
+    "java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSettingsFragment.java",
+    "java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSnackbarController.java",
+  ]
   deps = [
     ":java_resources",
+    "//base:base_java",
+    "//chrome/browser/ui/messages/android:java",
     "//components/browser_ui/settings/android:java",
     "//third_party/android_deps:androidx_fragment_fragment_java",
     "//third_party/android_deps:androidx_preference_preference_java",
diff --git a/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSnackbarController.java b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSnackbarController.java
new file mode 100644
index 0000000..813ef55
--- /dev/null
+++ b/chrome/browser/privacy_sandbox/android/java/src/org/chromium/chrome/browser/privacy_sandbox/PrivacySandboxSnackbarController.java
@@ -0,0 +1,60 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.chrome.browser.privacy_sandbox;
+
+import android.content.Context;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar;
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
+import org.chromium.components.browser_ui.settings.SettingsLauncher;
+
+/**
+ * Shows the snackbar for Privacy Sandbox settings, allowing the user to quickly navigate there.
+ */
+public class PrivacySandboxSnackbarController implements SnackbarManager.SnackbarController {
+    private Context mContext;
+    private SettingsLauncher mSettingsLauncher;
+    private SnackbarManager mSnackbarManager;
+
+    /**
+     * Creates an instance of the controller given a SnackbarManager and a SettingsLauncher.
+     */
+    public PrivacySandboxSnackbarController(
+            Context context, SnackbarManager manager, SettingsLauncher launcher) {
+        ThreadUtils.assertOnUiThread();
+        assert manager != null;
+        mContext = context;
+        mSnackbarManager = manager;
+        mSettingsLauncher = launcher;
+    }
+
+    /**
+     * Displays a snackbar, showing the user an option to go to Privacy Sandbox settings.
+     */
+    public void showSnackbar() {
+        mSnackbarManager.dismissSnackbars(this);
+        mSnackbarManager.showSnackbar(
+                Snackbar.make(mContext.getString(R.string.privacy_sandbox_snackbar_message), this,
+                                Snackbar.TYPE_ACTION, Snackbar.UMA_PRIVACY_SANDBOX_PAGE_OPEN)
+                        .setAction(mContext.getString(R.string.more), null));
+    }
+
+    /**
+     * Dismisses the snackbar, if it is active.
+     */
+    public void dismissSnackbar() {
+        mSnackbarManager.dismissSnackbars(this);
+    }
+
+    // Implement SnackbarController.
+    @Override
+    public void onAction(Object actionData) {
+        mSettingsLauncher.launchSettingsActivity(mContext, PrivacySandboxSettingsFragment.class);
+    }
+
+    @Override
+    public void onDismissNoAction(Object actionData) {}
+}
diff --git a/chrome/browser/resources/chromeos/login/fingerprint_setup.html b/chrome/browser/resources/chromeos/login/fingerprint_setup.html
index c4ed9ad..8198dd4 100644
--- a/chrome/browser/resources/chromeos/login/fingerprint_setup.html
+++ b/chrome/browser/resources/chromeos/login/fingerprint_setup.html
@@ -37,9 +37,6 @@
             <div id="sensorLocation"></div>
           </template>
         </div>
-        <div id="footer-text" class="content self-stretch" >
-          [[i18nDynamic(locale, 'setupFingerprintScreenFooter')]]
-        </div>
       </div>
       <div slot="bottom-buttons" class="layout horizontal end-justified">
         <oobe-text-button id="skipStart"
diff --git a/chrome/browser/resources/extensions/BUILD.gn b/chrome/browser/resources/extensions/BUILD.gn
index db0b18a..83764adf 100644
--- a/chrome/browser/resources/extensions/BUILD.gn
+++ b/chrome/browser/resources/extensions/BUILD.gn
@@ -4,6 +4,7 @@
 
 import("//build/config/chromeos/ui_mode.gni")
 import("//chrome/common/features.gni")
+import("//extensions/buildflags/buildflags.gni")
 import("//third_party/closure_compiler/compile_js.gni")
 import("//tools/grit/grit_rule.gni")
 import("//tools/grit/preprocess_if_expr.gni")
@@ -11,6 +12,8 @@
 import("//ui/webui/resources/tools/generate_grd.gni")
 import("../tools/optimize_webui.gni")
 
+assert(enable_extensions, "enable extensions check failed")
+
 preprocess_folder = "preprocessed"
 preprocess_manifest = "preprocessed_manifest.json"
 preprocess_gen_manifest = "preprocessed_gen_manifest.json"
diff --git a/chrome/browser/resources/new_tab_page/modules/module_descriptor.js b/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
index 8032f59..8ebce26a 100644
--- a/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
+++ b/chrome/browser/resources/new_tab_page/modules/module_descriptor.js
@@ -3,6 +3,7 @@
 // found in the LICENSE file.
 
 import {BrowserProxy} from '../browser_proxy.js';
+import {mojoTimeDelta} from '../utils.js';
 
 /**
  * @fileoverview Provides the module descriptor. Each module must create a
@@ -47,11 +48,13 @@
   }
 
   async initialize() {
+    const loadStartTime = BrowserProxy.getInstance().now();
     this.element_ = await this.initializeCallback_();
     if (!this.element_) {
       return;
     }
+    const loadEndTime = BrowserProxy.getInstance().now();
     BrowserProxy.getInstance().handler.onModuleLoaded(
-        this.id_, BrowserProxy.getInstance().now());
+        this.id_, loadEndTime, mojoTimeDelta(loadEndTime - loadStartTime));
   }
 }
diff --git a/chrome/browser/resources/settings/lazy_load.js b/chrome/browser/resources/settings/lazy_load.js
index 1c0bdd6..86f910e 100644
--- a/chrome/browser/resources/settings/lazy_load.js
+++ b/chrome/browser/resources/settings/lazy_load.js
@@ -94,7 +94,7 @@
 export {ContentSettingProvider, DefaultContentSetting, RawChooserException, RawSiteException, RecentSitePermissions, SiteException, SiteGroup, SiteSettingsPrefsBrowserProxy, SiteSettingsPrefsBrowserProxyImpl, ZoomLevelEntry} from './site_settings/site_settings_prefs_browser_proxy.js';
 export {WebsiteUsageBrowserProxyImpl} from './site_settings/website_usage_browser_proxy.js';
 export {defaultSettingLabel} from './site_settings_page/site_settings_list.js';
-// <if expr="not chromeos">
+// <if expr="not chromeos and not lacros">
 export {SystemPageBrowserProxyImpl} from './system_page/system_page_browser_proxy.js';
 
 // </if>
diff --git a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js
index c953358..d2e4df8 100644
--- a/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js
+++ b/chrome/browser/resources/signin/profile_picker/manage_profiles_browser_proxy.js
@@ -2,6 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
 import {addSingletonGetter, sendWithPromise} from 'chrome://resources/js/cr.m.js';
 
 /**
@@ -113,15 +114,19 @@
   loadSignInProfileCreationFlow(profileColor) {}
 
   /**
+   * Retrieves custom avatar list for the select avatar dialog.
+   * * @return {!Promise<!Array<!AvatarIcon>>}
+   */
+  getAvailableIcons() {}
+
+  /**
    * Creates local profile
    * @param {string} profileName
    * @param {number} profileColor
-   * @param {string} avatarUrl
-   * @param {boolean} isGeneric
+   * @param {number} avatarIndex
    * @param {boolean} createShortcut
    */
-  createProfile(
-      profileName, profileColor, avatarUrl, isGeneric, createShortcut) {}
+  createProfile(profileName, profileColor, avatarIndex, createShortcut) {}
 
   /**
    * Sets the local profile name.
@@ -187,11 +192,15 @@
   }
 
   /** @override */
-  createProfile(
-      profileName, profileColor, avatarUrl, isGeneric, createShortcut) {
+  getAvailableIcons() {
+    return sendWithPromise('getAvailableIcons');
+  }
+
+  /** @override */
+  createProfile(profileName, profileColor, avatarIndex, createShortcut) {
     chrome.send(
         'createProfile',
-        [profileName, profileColor, avatarUrl, isGeneric, createShortcut]);
+        [profileName, profileColor, avatarIndex, createShortcut]);
   }
 
   /** @override */
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
index b4b3748..2b189f2 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/BUILD.gn
@@ -34,8 +34,10 @@
     "//ui/webui/resources/cr_components/customize_themes",
     "//ui/webui/resources/cr_elements/cr_button:cr_button.m",
     "//ui/webui/resources/cr_elements/cr_checkbox:cr_checkbox.m",
+    "//ui/webui/resources/cr_elements/cr_dialog:cr_dialog.m",
     "//ui/webui/resources/cr_elements/cr_icon_button:cr_icon_button.m",
     "//ui/webui/resources/cr_elements/cr_input:cr_input.m",
+    "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector.m",
     "//ui/webui/resources/js:load_time_data.m",
     "//ui/webui/resources/js:web_ui_listener_behavior.m",
   ]
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html
index 24defbe..dbf5ea796 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.html
@@ -1,4 +1,4 @@
-<style include="profile-creation-shared">
+<style include="profile-creation-shared profile-picker-shared">
   :host {
     --vertical-gap: 24px;
   }
@@ -65,21 +65,6 @@
     overflow: auto;
   }
 
-  #wrapperContainer::-webkit-scrollbar {
-    width: var(--scrollbar-width);
-  }
-
-  /* Track */
-  #wrapperContainer::-webkit-scrollbar-track {
-    border-radius: var(--scrollbar-width);
-  }
-
-  /* Handle */
-  #wrapperContainer::-webkit-scrollbar-thumb {
-    background: var(--scrollbar-background);
-    border-radius: var(--scrollbar-width);
-  }
-
   #wrapper > * {
     flex-grow: 0;
     flex-shrink: 0;
@@ -143,6 +128,32 @@
     width: 111px;
   }
 
+  cr-profile-avatar-selector {
+    --avatar-size: 72px;
+    --avatar-spacing: 18px;
+    --avatar-grid-columns: 5;
+    height: fit-content;
+    padding-bottom: 15px;
+    padding-inline-start: 15px;
+    padding-top: 15px;
+    width: fit-content;
+  }
+
+  #selectAvatarWrapper {
+    height: 394px;
+    overflow-x: hidden;
+    overflow-y: auto;
+  }
+
+  #buttonContainer {
+    display: flex;
+    justify-content: flex-end;
+  }
+
+  #doneButton {
+    width : 32px;
+  }
+
   @media (prefers-color-scheme: dark) {
     #nameInput {
       --cr-input-placeholder-color: rgba(var(--google-grey-200-rgb), .5);
@@ -164,11 +175,11 @@
             --theme-shape-color:[[profileThemeInfo.themeShapeColor]]">
   <iron-icon class="banner" icon="profiles:customize-banner"></iron-icon>
   <cr-icon-button id="backButton" class="icon-arrow-back"
-        on-click="onClickBack_" aria-label="$i18n{backButtonLabel}">
+      on-click="onClickBack_" aria-label="$i18n{backButtonLabel}">
   </cr-icon-button>
   <h2 id="title">$i18n{localProfileCreationTitle}</h2>
   <div id="avatarContainer">
-    <img class="avatar" alt="" src$="[[profileThemeInfo.themeGenericAvatar]]">
+    <img class="avatar" alt="" src$="[[selectedAvatar_.url]]">
     <div id="customizeAvatarEllipse"></div>
     <cr-icon-button id="customizeAvatarIcon"
         iron-icon="profiles:create" on-click="onCustomizeAvatarClick_"
@@ -177,7 +188,7 @@
   </div>
 </div>
 
-<div id="wrapperContainer">
+<div id="wrapperContainer" class="custom-scrollbar">
   <div id="wrapper">
     <cr-input id="nameInput" value="{{profileName_}}" pattern="[[pattern_]]"
         placeholder="$i18n{createProfileNamePlaceholder}"
@@ -198,11 +209,28 @@
 <div class="footer">
   <cr-checkbox checked="{{createShortcut_}}"
       hidden="[[!isProfileShortcutsEnabled_]]">
-      $i18n{createDesktopShortcutLabel}
+    $i18n{createDesktopShortcutLabel}
   </cr-checkbox>
 
   <cr-button id="save" class="action-button" on-click="onSaveClick_"
-            disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]">
+      disabled="[[isSaveDisabled_(createInProgress_, profileName_)]]">
     $i18n{createProfileConfirm}
   </cr-button>
 </div>
+
+<cr-dialog id="selectAvatarDialog">
+  <div slot="title">$i18n{selectAnAvatarDialogTitle}</div>
+  <div slot="body">
+    <div id="selectAvatarWrapper" class="custom-scrollbar">
+      <cr-profile-avatar-selector avatars="[[availableIcons_]]"
+          selected-avatar="{{selectedAvatar_}}">
+      </cr-profile-avatar-selector>
+    </div>
+  </div>
+  <div id="buttonContainer" slot="button-container">
+    <cr-button id="doneButton" class="action-button"
+        on-click="onDoneSelectAvatarClick_">
+      $i18n{selectAvatarDoneButtonLabel}
+    </cr-button>
+  </div>
+</cr-dialog>
diff --git a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js
index 57751048..41de377d 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js
+++ b/chrome/browser/resources/signin/profile_picker/profile_creation_flow/local_profile_customization.js
@@ -3,15 +3,20 @@
 // found in the LICENSE file.
 
 import 'chrome://resources/cr_elements/cr_icon_button/cr_icon_button.m.js';
+import 'chrome://resources/cr_elements/cr_dialog/cr_dialog.m.js';
 import 'chrome://resources/cr_elements/cr_button/cr_button.m.js';
 import 'chrome://resources/cr_elements/cr_input/cr_input.m.js';
 import 'chrome://resources/cr_elements/cr_checkbox/cr_checkbox.m.js';
 import 'chrome://resources/cr_elements/shared_vars_css.m.js';
 import 'chrome://resources/cr_components/customize_themes/customize_themes.js';
+import 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
 import './shared_css.js';
 import '../icons.js';
+import '../profile_picker_shared_css.js';
 
 import {Theme, ThemeType} from 'chrome://resources/cr_components/customize_themes/customize_themes.mojom-webui.js';
+import {AvatarIcon} from 'chrome://resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.m.js';
+import {I18nBehavior} from 'chrome://resources/js/i18n_behavior.m.js';
 import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
 import {WebUIListenerBehavior} from 'chrome://resources/js/web_ui_listener_behavior.m.js';
 import {html, Polymer} from 'chrome://resources/polymer/v3_0/polymer/polymer_bundled.min.js';
@@ -25,7 +30,7 @@
 
   _template: html`{__html_template__}`,
 
-  behaviors: [WebUIListenerBehavior],
+  behaviors: [I18nBehavior, WebUIListenerBehavior],
 
   properties: {
     /**
@@ -58,6 +63,34 @@
     },
 
     /**
+     * Colored default generic avatar in the format expected by
+     * 'cr-profile-avatar-selector'
+     * @private {AvatarIcon}
+     */
+    genericDefaultAvatar_: {
+      type: Object,
+      computed: 'getGenericDefaultAvatar_(profileThemeInfo.themeGenericAvatar)',
+      observer: 'onGenericDefaultAvatarChange_',
+    },
+
+    /**
+     * List of available profile icon Urls and labels.
+     * @private {!Array<!AvatarIcon>}
+     */
+    availableIcons_: {
+      type: Array,
+      value() {
+        return [];
+      },
+    },
+
+    /**
+     * The currently selected profile avatar, if any.
+     * @private {?AvatarIcon}
+     */
+    selectedAvatar_: Object,
+
+    /**
      * The current profile name.
      * @private {string}
      */
@@ -98,6 +131,12 @@
       type: String,
       value: '.*\\S.*',
     },
+
+    /** @private */
+    defaultAvatarIndex_: {
+      type: Number,
+      value: () => loadTimeData.getInteger('placeholderAvatarIndex'),
+    },
   },
 
   listeners: {
@@ -118,6 +157,8 @@
     this.sanityCheck_();
     this.addWebUIListener(
         'create-profile-finished', () => this.handleCreateProfileFinished_());
+    this.manageProfilesBrowserProxy_.getAvailableIcons().then(
+        icons => this.setAvailableIcons_(icons));
   },
 
   /** @private */
@@ -172,10 +213,9 @@
     this.createInProgress_ = true;
     const createShortcut =
         this.isProfileShortcutsEnabled_ && this.createShortcut_;
-    // TODO(crbug.com/1115056): Support avatar selection.
     this.manageProfilesBrowserProxy_.createProfile(
-        this.profileName_, this.profileThemeInfo.color, '', true,
-        createShortcut);
+        this.profileName_, this.profileThemeInfo.color,
+        this.selectedAvatar_.index, createShortcut);
   },
 
   /** @private */
@@ -185,7 +225,49 @@
 
   /** @private */
   onCustomizeAvatarClick_() {
-    // TODO(msalama): Open select avatar dialog.
+    this.$.selectAvatarDialog.showModal();
+  },
+
+  /** @private */
+  onDoneSelectAvatarClick_() {
+    this.$.selectAvatarDialog.close();
+  },
+
+  /**
+   * @return {AvatarIcon}
+   * @private
+   */
+  getGenericDefaultAvatar_() {
+    return /** @type {!AvatarIcon} */ ({
+      url: this.profileThemeInfo.themeGenericAvatar,
+      label: this.i18n('defaultAvatarLabel'),
+      index: this.defaultAvatarIndex_,
+      isGaiaAvatar: false,
+      selected: false,
+    });
+  },
+
+  /** @private */
+  onGenericDefaultAvatarChange_() {
+    this.setAvailableIcons_([...this.availableIcons_]);
+    if (!this.selectedAvatar_ ||
+        this.selectedAvatar_.index === this.defaultAvatarIndex_) {
+      this.selectedAvatar_ = this.genericDefaultAvatar_;
+    }
+  },
+
+  /**
+   * @param {!Array<!AvatarIcon>} icons
+   * @private
+   */
+  setAvailableIcons_(icons) {
+    if (!this.genericDefaultAvatar_) {
+      this.availableIcons_ = icons;
+      return;
+    }
+    const offset =
+        icons.length > 0 && icons[0].index === this.defaultAvatarIndex_ ? 1 : 0;
+    this.availableIcons_ = [this.genericDefaultAvatar_, ...icons.slice(offset)];
   },
 
   /** @private */
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html
index b7de3118..fa4d01d 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_picker_main_view.html
@@ -72,21 +72,6 @@
     width: 100%;
   }
 
-  .profiles-container::-webkit-scrollbar {
-    width: var(--scrollbar-width);
-  }
-
-  /* Track */
-  .profiles-container::-webkit-scrollbar-track {
-    border-radius: var(--scrollbar-width);
-  }
-
-  /* Handle */
-  .profiles-container::-webkit-scrollbar-thumb {
-    background: var(--scrollbar-background);
-    border-radius: var(--scrollbar-width);
-  }
-
   .profile-item {
     align-items: center;
     border-radius: 12px;
@@ -168,7 +153,7 @@
   <h3>$i18n{mainViewSubtitle}</h3>
 </div>
 <div id="wrapper" hidden$="[[!profilesListLoaded_]]">
-  <div class="profiles-container">
+  <div class="profiles-container custom-scrollbar">
     <template is="dom-repeat" items="[[profilesList_]]">
       <profile-card
           class="profile-item" profile-state="[[item]]">
diff --git a/chrome/browser/resources/signin/profile_picker/profile_picker_shared_css.html b/chrome/browser/resources/signin/profile_picker/profile_picker_shared_css.html
index 80be3353..f6a222e 100644
--- a/chrome/browser/resources/signin/profile_picker/profile_picker_shared_css.html
+++ b/chrome/browser/resources/signin/profile_picker/profile_picker_shared_css.html
@@ -51,5 +51,20 @@
       position: absolute;
       width: 100%;
     }
+
+    .custom-scrollbar::-webkit-scrollbar {
+      width: var(--scrollbar-width);
+    }
+
+    /* Track */
+    .custom-scrollbar::-webkit-scrollbar-track {
+      border-radius: var(--scrollbar-width);
+    }
+
+    /* Handle */
+    .custom-scrollbar::-webkit-scrollbar-thumb {
+      background: var(--scrollbar-background);
+      border-radius: var(--scrollbar-width);
+    }
   </style>
 </template>
diff --git a/chrome/browser/sharing/sharing_message_sender.cc b/chrome/browser/sharing/sharing_message_sender.cc
index 630a1d0..b990c01 100644
--- a/chrome/browser/sharing/sharing_message_sender.cc
+++ b/chrome/browser/sharing/sharing_message_sender.cc
@@ -42,15 +42,13 @@
   chrome_browser_sharing::MessageType message_type =
       SharingPayloadCaseToMessageType(message.payload_case());
   SharingDevicePlatform receiver_device_platform = GetDevicePlatform(device);
-  base::TimeDelta last_updated_age =
-      base::Time::Now() - device.last_updated_timestamp();
 
   auto inserted = base::InsertOrAssign(
       message_metadata_, message_guid,
-      SentMessageMetadata(
-          std::move(callback), base::TimeTicks::Now(), message_type,
-          receiver_device_platform, last_updated_age, trace_id,
-          SharingChannelType::kUnknown, device.pulse_interval()));
+      SentMessageMetadata(std::move(callback), base::TimeTicks::Now(),
+                          message_type, receiver_device_platform, trace_id,
+                          SharingChannelType::kUnknown,
+                          device.pulse_interval()));
   DCHECK(inserted.second);
 
   auto delegate_iter = send_delegates_.find(delegate_type);
@@ -84,9 +82,6 @@
                          /*response=*/nullptr),
           response_timeout);
 
-  LogSharingDeviceLastUpdatedAge(message_type, last_updated_age);
-  LogSharingVersionComparison(message_type, device.chrome_version());
-
   message.set_sender_guid(local_device_info->guid());
   message.set_sender_device_name(
       send_tab_to_self::GetSharingDeviceNames(local_device_info).full_name);
@@ -184,7 +179,6 @@
   LogSendSharingMessageResult(metadata.type, metadata.receiver_device_platform,
                               metadata.channel_type,
                               metadata.receiver_pulse_interval, result);
-  LogSharingDeviceLastUpdatedAgeWithResult(result, metadata.last_updated_age);
   TRACE_EVENT_NESTABLE_ASYNC_END1("sharing", "SharingMessageSender.SendMessage",
                                   TRACE_ID_LOCAL(metadata.trace_id), "result",
                                   SharingSendMessageResultToString(result));
@@ -195,7 +189,6 @@
     base::TimeTicks timestamp,
     chrome_browser_sharing::MessageType type,
     SharingDevicePlatform receiver_device_platform,
-    base::TimeDelta last_updated_age,
     int trace_id,
     SharingChannelType channel_type,
     base::TimeDelta receiver_pulse_interval)
@@ -203,7 +196,6 @@
       timestamp(timestamp),
       type(type),
       receiver_device_platform(receiver_device_platform),
-      last_updated_age(last_updated_age),
       trace_id(trace_id),
       channel_type(channel_type),
       receiver_pulse_interval(receiver_pulse_interval) {}
diff --git a/chrome/browser/sharing/sharing_message_sender.h b/chrome/browser/sharing/sharing_message_sender.h
index 652b347..82ce0311 100644
--- a/chrome/browser/sharing/sharing_message_sender.h
+++ b/chrome/browser/sharing/sharing_message_sender.h
@@ -89,7 +89,6 @@
                         base::TimeTicks timestamp,
                         chrome_browser_sharing::MessageType type,
                         SharingDevicePlatform receiver_device_platform,
-                        base::TimeDelta last_updated_age,
                         int trace_id,
                         SharingChannelType channel_type,
                         base::TimeDelta receiver_pulse_interval);
@@ -101,7 +100,6 @@
     base::TimeTicks timestamp;
     chrome_browser_sharing::MessageType type;
     SharingDevicePlatform receiver_device_platform;
-    base::TimeDelta last_updated_age;
     int trace_id;
     SharingChannelType channel_type;
     base::TimeDelta receiver_pulse_interval;
diff --git a/chrome/browser/sharing/sharing_metrics.cc b/chrome/browser/sharing/sharing_metrics.cc
index 76912f1..dfbca18 100644
--- a/chrome/browser/sharing/sharing_metrics.cc
+++ b/chrome/browser/sharing/sharing_metrics.cc
@@ -287,55 +287,6 @@
       time_taken);
 }
 
-void LogSharingDeviceLastUpdatedAge(
-    chrome_browser_sharing::MessageType message_type,
-    base::TimeDelta age) {
-  constexpr char kBase[] = "Sharing.DeviceLastUpdatedAge";
-  int hours = age.InHours();
-  base::UmaHistogramCounts1000(kBase, hours);
-  base::UmaHistogramCounts1000(
-      base::StrCat({kBase, ".", SharingMessageTypeToString(message_type)}),
-      hours);
-}
-
-void LogSharingDeviceLastUpdatedAgeWithResult(SharingSendMessageResult result,
-                                              base::TimeDelta age) {
-  base::UmaHistogramCounts1000(
-      base::StrCat({"Sharing.DeviceLastUpdatedAgeWithResult.",
-                    SharingSendMessageResultToString(result)}),
-      age.InHours());
-}
-
-void LogSharingVersionComparison(
-    chrome_browser_sharing::MessageType message_type,
-    const std::string& receiver_version) {
-  int sender_major = 0;
-  base::StringToInt(version_info::GetMajorVersionNumber(), &sender_major);
-
-  // The |receiver_version| has optional modifiers e.g. "1.2.3.4 canary" so we
-  // do not parse it with base::Version.
-  int receiver_major = 0;
-  base::StringToInt(receiver_version, &receiver_major);
-
-  SharingMajorVersionComparison result;
-  if (sender_major == 0 || sender_major == INT_MIN || sender_major == INT_MAX ||
-      receiver_major == 0 || receiver_major == INT_MIN ||
-      receiver_major == INT_MAX) {
-    result = SharingMajorVersionComparison::kUnknown;
-  } else if (sender_major < receiver_major) {
-    result = SharingMajorVersionComparison::kSenderIsLower;
-  } else if (sender_major == receiver_major) {
-    result = SharingMajorVersionComparison::kSame;
-  } else {
-    result = SharingMajorVersionComparison::kSenderIsHigher;
-  }
-  constexpr char kBase[] = "Sharing.MajorVersionComparison";
-  base::UmaHistogramEnumeration(kBase, result);
-  base::UmaHistogramEnumeration(
-      base::StrCat({kBase, ".", SharingMessageTypeToString(message_type)}),
-      result);
-}
-
 void LogSharingDialogShown(SharingFeatureName feature, SharingDialogType type) {
   base::UmaHistogramEnumeration(
       base::StrCat({"Sharing.", GetEnumStringValue(feature), "DialogShown"}),
@@ -423,15 +374,6 @@
                                  size);
 }
 
-void LogSharedClipboardRetries(int retries, SharingSendMessageResult result) {
-  constexpr char kBase[] = "Sharing.SharedClipboardRetries";
-  base::UmaHistogramExactLinear(kBase, retries, /*value_max=*/20);
-  base::UmaHistogramExactLinear(
-      base::StrCat({kBase, ".", SharingSendMessageResultToString(result)}),
-      retries,
-      /*value_max=*/20);
-}
-
 void LogRemoteCopyHandleMessageResult(RemoteCopyHandleMessageResult result) {
   base::UmaHistogramEnumeration("Sharing.RemoteCopyHandleMessageResult",
                                 result);
@@ -480,7 +422,3 @@
   else
     base::UmaHistogramTimes("Sharing.RemoteCopyWriteTextDetectionTime", time);
 }
-
-void LogSharingDeviceInfoAvailable(bool available) {
-  base::UmaHistogramBoolean("Sharing.DeviceInfoAvailable", available);
-}
diff --git a/chrome/browser/sharing/sharing_metrics.h b/chrome/browser/sharing/sharing_metrics.h
index 2c6135e..f8724291 100644
--- a/chrome/browser/sharing/sharing_metrics.h
+++ b/chrome/browser/sharing/sharing_metrics.h
@@ -107,26 +107,6 @@
     chrome_browser_sharing::MessageType message_type,
     base::TimeDelta time_taken);
 
-// Logs to UMA the number of hours since the target device timestamp was last
-// updated. Logged when a message is sent to the device.
-void LogSharingDeviceLastUpdatedAge(
-    chrome_browser_sharing::MessageType message_type,
-    base::TimeDelta age);
-
-// Logs to UMA the number of hours since the target device timestamp was last
-// updated. Logged when a message is sent to the device and the result is known.
-void LogSharingDeviceLastUpdatedAgeWithResult(SharingSendMessageResult result,
-                                              base::TimeDelta age);
-
-// Logs to UMA the comparison of the major version of Chrome on this
-// (the sender) device and the receiver device. Logged when a message is sent.
-// The |receiver_version| should be a dotted version number with optional
-// modifiers e.g. "1.2.3.4 canary" as generated by
-// version_info::GetVersionStringWithModifier.
-void LogSharingVersionComparison(
-    chrome_browser_sharing::MessageType message_type,
-    const std::string& receiver_version);
-
 // Logs to UMA the |type| of dialog shown for sharing feature.
 void LogSharingDialogShown(SharingFeatureName feature, SharingDialogType type);
 
@@ -149,9 +129,6 @@
 // Logs to UMA the size of the selected text for Shared Clipboard.
 void LogSharedClipboardSelectedTextSize(size_t text_size);
 
-// Logs to UMA the number of retries for sending a Shared Clipboard message.
-void LogSharedClipboardRetries(int retries, SharingSendMessageResult result);
-
 // Logs to UMA the result of handling a Remote Copy message.
 void LogRemoteCopyHandleMessageResult(RemoteCopyHandleMessageResult result);
 
@@ -182,7 +159,4 @@
 // Logs to UMA the time to detect a clipboard write for Remote Copy.
 void LogRemoteCopyWriteDetectionTime(base::TimeDelta time, bool is_image);
 
-// Logs to UMA if the DeviceInfo for a guid was available locally.
-void LogSharingDeviceInfoAvailable(bool available);
-
 #endif  // CHROME_BROWSER_SHARING_SHARING_METRICS_H_
diff --git a/chrome/browser/sharing/sharing_service_proxy_android.cc b/chrome/browser/sharing/sharing_service_proxy_android.cc
index 310cf1d3..a6b2fcf 100644
--- a/chrome/browser/sharing/sharing_service_proxy_android.cc
+++ b/chrome/browser/sharing/sharing_service_proxy_android.cc
@@ -44,7 +44,6 @@
     JNIEnv* env,
     const base::android::JavaParamRef<jstring>& j_guid,
     const base::android::JavaParamRef<jstring>& j_text,
-    const jint j_retries,
     const base::android::JavaParamRef<jobject>& j_runnable) {
   auto callback =
       base::BindOnce(base::android::RunIntCallbackAndroid,
@@ -55,7 +54,6 @@
 
   std::unique_ptr<syncer::DeviceInfo> device =
       sharing_service_->GetDeviceByGuid(guid);
-  LogSharingDeviceInfoAvailable(device != nullptr);
 
   if (!device) {
     std::move(callback).Run(
@@ -71,14 +69,13 @@
       *device, base::TimeDelta::FromSeconds(kSharingMessageTTLSeconds.Get()),
       std::move(sharing_message),
       base::BindOnce(
-          [](int retries, base::OnceCallback<void(int)> callback,
+          [](base::OnceCallback<void(int)> callback,
              SharingSendMessageResult result,
              std::unique_ptr<chrome_browser_sharing::ResponseMessage>
                  response) {
-            LogSharedClipboardRetries(retries, result);
             std::move(callback).Run(static_cast<int>(result));
           },
-          j_retries, std::move(callback)));
+          std::move(callback)));
 }
 
 void SharingServiceProxyAndroid::GetDeviceCandidates(
diff --git a/chrome/browser/sharing/sharing_service_proxy_android.h b/chrome/browser/sharing/sharing_service_proxy_android.h
index 2c86753..81af31b 100644
--- a/chrome/browser/sharing/sharing_service_proxy_android.h
+++ b/chrome/browser/sharing/sharing_service_proxy_android.h
@@ -20,7 +20,6 @@
       JNIEnv* env,
       const base::android::JavaParamRef<jstring>& j_guid,
       const base::android::JavaParamRef<jstring>& j_text,
-      const jint j_retries,
       const base::android::JavaParamRef<jobject>& j_runnable);
 
   void GetDeviceCandidates(
diff --git a/chrome/browser/sharing/web_push/web_push_sender_unittest.cc b/chrome/browser/sharing/web_push/web_push_sender_unittest.cc
index af931c7..6f04570 100644
--- a/chrome/browser/sharing/web_push/web_push_sender_unittest.cc
+++ b/chrome/browser/sharing/web_push/web_push_sender_unittest.cc
@@ -141,7 +141,8 @@
       pendingRequest->request.request_body->elements();
   ASSERT_EQ(1UL, body_elements->size());
   const network::DataElement& body = body_elements->back();
-  EXPECT_EQ("payload", std::string(body.bytes(), body.length()));
+  ASSERT_EQ(network::DataElement::Tag::kBytes, body.type());
+  EXPECT_EQ("payload", body.As<network::DataElementBytes>().AsStringPiece());
 
   auto response_head = network::CreateURLResponseHead(net::HTTP_OK);
   response_head->headers->AddHeader("location",
diff --git a/chrome/browser/signin/dice_web_signin_interceptor.cc b/chrome/browser/signin/dice_web_signin_interceptor.cc
index a6e1c1dc..ce9d9bc7f 100644
--- a/chrome/browser/signin/dice_web_signin_interceptor.cc
+++ b/chrome/browser/signin/dice_web_signin_interceptor.cc
@@ -88,11 +88,35 @@
   return chrome::FindBrowserWithWebContents(web_contents) == nullptr;
 }
 
-bool GuestOptionAvailable() {
-  return Profile::IsEphemeralGuestProfileEnabled() &&
-         !ProfileManager::GuestProfileExists() &&
-         g_browser_process->local_state()->GetBoolean(
-             prefs::kBrowserGuestModeEnabled);
+// Different conditions which make Guest option available or not.
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class SigninInterceptGuestAvailability {
+  kAvailable = 0,
+  kGuestAlreadyOpen = 1,
+  kGuestBlocked = 2,
+  kEphemeralGuestDisabled = 3,
+  kMaxValue = kEphemeralGuestDisabled
+};
+
+SigninInterceptGuestAvailability GetGuestOptionAvailablity() {
+  if (!Profile::IsEphemeralGuestProfileEnabled())
+    return SigninInterceptGuestAvailability::kEphemeralGuestDisabled;
+
+  if (ProfileManager::GuestProfileExists())
+    return SigninInterceptGuestAvailability::kGuestAlreadyOpen;
+
+  if (!g_browser_process->local_state()->GetBoolean(
+          prefs::kBrowserGuestModeEnabled)) {
+    return SigninInterceptGuestAvailability::kGuestBlocked;
+  }
+  return SigninInterceptGuestAvailability::kAvailable;
+}
+
+void RecordGuestOptionAvailablity(
+    SigninInterceptGuestAvailability availability) {
+  base::UmaHistogramEnumeration("Signin.Intercept.Guest.Availability",
+                                availability);
 }
 
 }  // namespace
@@ -407,10 +431,12 @@
       ->GetProfileAttributesStorage()
       .GetProfileAttributesWithPath(profile_->GetPath(), &entry);
   SkColor profile_color = GenerateNewProfileColor(entry).color;
+  auto guest_option_availability = GetGuestOptionAvailablity();
   Delegate::BubbleParameters bubble_parameters{
       *interception_type, info, GetPrimaryAccountInfo(identity_manager_),
       GetAutogeneratedThemeColors(profile_color).frame_color,
-      GuestOptionAvailable()};
+      guest_option_availability ==
+          SigninInterceptGuestAvailability::kAvailable};
   interception_bubble_handle_ = delegate_->ShowSigninInterceptionBubble(
       web_contents(), bubble_parameters,
       base::BindOnce(&DiceWebSigninInterceptor::OnProfileCreationChoice,
@@ -420,6 +446,7 @@
       *interception_type == SigninInterceptionType::kEnterprise
           ? SigninInterceptionHeuristicOutcome::kInterceptEnterprise
           : SigninInterceptionHeuristicOutcome::kInterceptMultiUser);
+  RecordGuestOptionAvailablity(guest_option_availability);
 }
 
 void DiceWebSigninInterceptor::OnExtendedAccountInfoFetchTimeout() {
diff --git a/chrome/browser/signin/ui/android/BUILD.gn b/chrome/browser/signin/ui/android/BUILD.gn
index 787e962d..638b7ef 100644
--- a/chrome/browser/signin/ui/android/BUILD.gn
+++ b/chrome/browser/signin/ui/android/BUILD.gn
@@ -9,10 +9,14 @@
     ":java_resources",
     "//base:base_java",
     "//chrome/browser/consent_auditor/android:java",
+    "//chrome/browser/feedback/android:java",
     "//chrome/browser/flags:java",
+    "//chrome/browser/incognito/interstitial/android:java",
     "//chrome/browser/preferences:java",
     "//chrome/browser/profiles/android:java",
     "//chrome/browser/signin/services/android:java",
+    "//chrome/browser/tabmodel:java",
+    "//components/browser_ui/android/bottomsheet:java",
     "//components/browser_ui/settings/android:java",
     "//components/browser_ui/widget/android:java",
     "//components/embedder_support/android:util_java",
@@ -42,6 +46,11 @@
     "java/src/org/chromium/chrome/browser/signin/ui/SigninPromoController.java",
     "java/src/org/chromium/chrome/browser/signin/ui/SigninScrollView.java",
     "java/src/org/chromium/chrome/browser/signin/ui/SigninView.java",
+    "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetCoordinator.java",
+    "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetMediator.java",
+    "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetProperties.java",
+    "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetView.java",
+    "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetViewBinder.java",
     "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerCoordinator.java",
     "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDelegate.java",
     "java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerDialogFragment.java",
@@ -61,12 +70,22 @@
     "java/res/drawable-xhdpi/chrome_sync_logo.png",
     "java/res/drawable-xxhdpi/chrome_sync_logo.png",
     "java/res/drawable-xxxhdpi/chrome_sync_logo.png",
+    "java/res/drawable/ic_expand_more_in_circle_24dp.xml",
+    "java/res/layout/account_picker_bottom_sheet_continue_button.xml",
+    "java/res/layout/account_picker_bottom_sheet_header.xml",
+    "java/res/layout/account_picker_bottom_sheet_view.xml",
     "java/res/layout/account_picker_dialog_body.xml",
     "java/res/layout/account_picker_incognito_row.xml",
     "java/res/layout/account_picker_new_account_row.xml",
     "java/res/layout/account_picker_new_account_row_legacy.xml",
     "java/res/layout/account_picker_row.xml",
     "java/res/layout/account_picker_row_legacy.xml",
+    "java/res/layout/account_picker_state_auth_error.xml",
+    "java/res/layout/account_picker_state_collapsed.xml",
+    "java/res/layout/account_picker_state_expanded.xml",
+    "java/res/layout/account_picker_state_general_error.xml",
+    "java/res/layout/account_picker_state_no_account.xml",
+    "java/res/layout/account_picker_state_signin_in_progress.xml",
     "java/res/layout/confirm_import_sync_data.xml",
     "java/res/layout/personalized_signin_promo_view_body.xml",
     "java/res/layout/personalized_signin_promo_view_bookmarks.xml",
@@ -80,6 +99,7 @@
     "java/res/values/dimens.xml",
   ]
   deps = [
+    "//chrome/browser/incognito/interstitial/android:java_resources",
     "//chrome/browser/signin/services/android:java_resources",
     "//chrome/browser/ui/android/strings:ui_strings_grd",
     "//components/browser_ui/strings/android:browser_ui_strings_grd",
diff --git a/chrome/browser/signin/ui/android/DEPS b/chrome/browser/signin/ui/android/DEPS
new file mode 100644
index 0000000..7295e24
--- /dev/null
+++ b/chrome/browser/signin/ui/android/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+  "+components/browser_ui/android/bottomsheet",
+]
diff --git a/chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml b/chrome/browser/signin/ui/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml
similarity index 100%
rename from chrome/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml
rename to chrome/browser/signin/ui/android/java/res/drawable/ic_expand_more_in_circle_24dp.xml
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_continue_button.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_continue_button.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_bottom_sheet_continue_button.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_continue_button.xml
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_header.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_header.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_bottom_sheet_header.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_header.xml
diff --git a/chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_view.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_bottom_sheet_view.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_bottom_sheet_view.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_auth_error.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_auth_error.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_auth_error.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_auth_error.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_collapsed.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_collapsed.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_collapsed.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_collapsed.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_expanded.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_expanded.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_expanded.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_expanded.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_general_error.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_general_error.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_general_error.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_general_error.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_no_account.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_no_account.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_no_account.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_no_account.xml
diff --git a/chrome/android/java/res/layout/account_picker_state_signin_in_progress.xml b/chrome/browser/signin/ui/android/java/res/layout/account_picker_state_signin_in_progress.xml
similarity index 100%
rename from chrome/android/java/res/layout/account_picker_state_signin_in_progress.xml
rename to chrome/browser/signin/ui/android/java/res/layout/account_picker_state_signin_in_progress.xml
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetCoordinator.java
similarity index 95%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
rename to chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetCoordinator.java
index 63e0ad0..04446a7 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetCoordinator.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetCoordinator.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.signin.account_picker;
+package org.chromium.chrome.browser.signin.ui.account_picker;
 
 import android.app.Activity;
 import android.view.View;
@@ -15,8 +15,6 @@
 import org.chromium.chrome.browser.incognito.interstitial.IncognitoInterstitialDelegate;
 import org.chromium.chrome.browser.signin.services.SigninMetricsUtils;
 import org.chromium.chrome.browser.signin.services.SigninPreferencesManager;
-import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerCoordinator;
-import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate;
 import org.chromium.chrome.browser.tabmodel.TabCreator;
 import org.chromium.chrome.browser.tabmodel.TabModel;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetMediator.java
similarity index 97%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
rename to chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetMediator.java
index 90811afd..0d62dd6 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetMediator.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetMediator.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.signin.account_picker;
+package org.chromium.chrome.browser.signin.ui.account_picker;
 
 import android.accounts.Account;
 import android.content.Context;
@@ -12,12 +12,10 @@
 import androidx.annotation.Nullable;
 
 import org.chromium.base.task.AsyncTask;
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.chrome.browser.signin.services.ProfileDataCache;
 import org.chromium.chrome.browser.signin.services.SigninMetricsUtils;
-import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerCoordinator;
-import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerDelegate;
+import org.chromium.chrome.browser.signin.ui.R;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.components.signin.AccountManagerFacade;
 import org.chromium.components.signin.AccountManagerFacadeProvider;
 import org.chromium.components.signin.AccountUtils;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetProperties.java
similarity index 98%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java
rename to chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetProperties.java
index 3b050c0..6ab9eba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetProperties.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetProperties.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.signin.account_picker;
+package org.chromium.chrome.browser.signin.ui.account_picker;
 
 import android.view.View.OnClickListener;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetView.java
similarity index 96%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
rename to chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetView.java
index 12d4f873d..94d31da 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetView.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetView.java
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.signin.account_picker;
+package org.chromium.chrome.browser.signin.ui.account_picker;
 
 import android.app.Activity;
 import android.view.LayoutInflater;
@@ -18,11 +18,9 @@
 import androidx.recyclerview.widget.LinearLayoutManager;
 import androidx.recyclerview.widget.RecyclerView;
 
-import org.chromium.chrome.R;
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.chrome.browser.signin.services.DisplayableProfileData;
-import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerFeatureUtils;
-import org.chromium.chrome.browser.signin.ui.account_picker.ExistingAccountRowViewBinder;
+import org.chromium.chrome.browser.signin.ui.R;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.components.browser_ui.bottomsheet.BottomSheetContent;
 import org.chromium.ui.widget.ButtonCompat;
 
@@ -170,7 +168,6 @@
         continueButton.setText(continueAsButtonText);
     }
 
-
     @Override
     public View getContentView() {
         return mContentView;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetViewBinder.java
similarity index 91%
rename from chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
rename to chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetViewBinder.java
index 63fd12f..be36425 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerBottomSheetViewBinder.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerBottomSheetViewBinder.java
@@ -2,10 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-package org.chromium.chrome.browser.signin.account_picker;
+package org.chromium.chrome.browser.signin.ui.account_picker;
 
-import org.chromium.chrome.browser.signin.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.chrome.browser.signin.services.DisplayableProfileData;
+import org.chromium.chrome.browser.signin.ui.account_picker.AccountPickerBottomSheetProperties.ViewState;
 import org.chromium.ui.modelutil.PropertyKey;
 import org.chromium.ui.modelutil.PropertyModel;
 
diff --git a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerCoordinator.java b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerCoordinator.java
index 794c45e6..730b258 100644
--- a/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerCoordinator.java
+++ b/chrome/browser/signin/ui/android/java/src/org/chromium/chrome/browser/signin/ui/account_picker/AccountPickerCoordinator.java
@@ -57,9 +57,8 @@
      *                 account.
      * @param selectedAccountName The name of the account that should be marked as selected.
      * @param showIncognitoRow whether to show the incognito row in the account picker.
-     * TODO(crbug/1155123): Change this method to package private after modularization.
      */
-    public AccountPickerCoordinator(RecyclerView view, Listener listener,
+    AccountPickerCoordinator(RecyclerView view, Listener listener,
             @Nullable String selectedAccountName, boolean showIncognitoRow) {
         assert listener != null : "The argument AccountPickerCoordinator.Listener cannot be null!";
 
@@ -90,9 +89,8 @@
 
     /**
      * Destroys the resources used by the coordinator.
-     * TODO(crbug/1155123): Change this method to package private after modularization.
      */
-    public void destroy() {
+    void destroy() {
         mMediator.destroy();
     }
 
diff --git a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
index 41a8607b..ea4de6c2 100644
--- a/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
+++ b/chrome/browser/subresource_filter/subresource_filter_browsertest.cc
@@ -370,7 +370,7 @@
   proto::UrlRule rule = testing::CreateSuffixRule("included_script.html");
   proto::UrlRule allowlist_rule = testing::CreateSuffixRule(kAllowlistedDomain);
   allowlist_rule.set_anchor_right(proto::ANCHOR_TYPE_NONE);
-  allowlist_rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+  allowlist_rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
   ASSERT_NO_FATAL_FAILURE(SetRulesetWithRules({rule, allowlist_rule}));
 
   ui_test_utils::NavigateToURL(browser(), url);
diff --git a/chrome/browser/sync/test/integration/single_client_sync_invalidations_test.cc b/chrome/browser/sync/test/integration/single_client_sync_invalidations_test.cc
index f048331..fbc3aa8 100644
--- a/chrome/browser/sync/test/integration/single_client_sync_invalidations_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_sync_invalidations_test.cc
@@ -11,17 +11,23 @@
 #include "chrome/browser/sync/test/integration/sync_test.h"
 #include "components/bookmarks/browser/bookmark_model.h"
 #include "components/sync/base/model_type.h"
+#include "components/sync/base/time.h"
 #include "components/sync/invalidations/switches.h"
 #include "components/sync/invalidations/sync_invalidations_service.h"
 #include "components/sync/protocol/sync.pb.h"
 #include "components/sync/test/fake_server/bookmark_entity_builder.h"
 #include "components/sync/test/fake_server/entity_builder_factory.h"
+#include "components/sync_device_info/device_info_util.h"
 #include "content/public/test/browser_test.h"
 #include "testing/gmock/include/gmock/gmock.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 namespace {
 
+using bookmarks::BookmarkNode;
+using bookmarks_helper::AddFolder;
+using bookmarks_helper::GetBookmarkBarNode;
+using bookmarks_helper::ServerBookmarksEqualityChecker;
 using testing::AllOf;
 using testing::ElementsAre;
 using testing::Not;
@@ -76,6 +82,23 @@
              .instance_id_token() == expected_token;
 }
 
+sync_pb::DeviceInfoSpecifics CreateDeviceInfoSpecifics(
+    const std::string& cache_guid,
+    const std::string& fcm_registration_token) {
+  sync_pb::DeviceInfoSpecifics specifics;
+  specifics.set_cache_guid(cache_guid);
+  specifics.set_client_name("client name");
+  specifics.set_device_type(sync_pb::SyncEnums_DeviceType_TYPE_LINUX);
+  specifics.set_sync_user_agent("user agent");
+  specifics.set_chrome_version("chrome version");
+  specifics.set_signin_scoped_device_id("scoped device id");
+  specifics.set_last_updated_timestamp(
+      syncer::TimeToProtoTime(base::Time::Now()));
+  specifics.mutable_invalidation_fields()->set_instance_id_token(
+      fcm_registration_token);
+  return specifics;
+}
+
 class SingleClientWithSyncSendInterestedDataTypesTest : public SyncTest {
  public:
   SingleClientWithSyncSendInterestedDataTypesTest() : SyncTest(SINGLE_CLIENT) {
@@ -134,6 +157,24 @@
   }
   ~SingleClientWithUseSyncInvalidationsTest() override = default;
 
+  // Injects a test DeviceInfo entity to the fake server.
+  void InjectDeviceInfoEntityToServer(
+      const std::string& cache_guid,
+      const std::string& fcm_registration_token) {
+    sync_pb::EntitySpecifics specifics;
+    *specifics.mutable_device_info() =
+        CreateDeviceInfoSpecifics(cache_guid, fcm_registration_token);
+    GetFakeServer()->InjectEntity(
+        syncer::PersistentUniqueClientEntity::CreateFromSpecificsForTesting(
+            /*non_unique_name=*/"",
+            /*client_tag=*/
+            syncer::DeviceInfoUtil::SpecificsToTag(specifics.device_info()),
+            specifics,
+            /*creation_time=*/specifics.device_info().last_updated_timestamp(),
+            /*last_modified_time=*/
+            specifics.device_info().last_updated_timestamp()));
+  }
+
  private:
   base::test::ScopedFeatureList override_features_;
 
@@ -172,6 +213,33 @@
           .Wait());
 }
 
+IN_PROC_BROWSER_TEST_F(SingleClientWithUseSyncInvalidationsTest,
+                       ShouldPopulateFCMRegistrationTokens) {
+  const std::string kTitle = "title";
+  const std::string kRemoteDeviceCacheGuid = "other_cache_guid";
+  const std::string kRemoteFCMRegistrationToken = "other_fcm_token";
+
+  // Simulate the case when the server already knows one other device.
+  InjectDeviceInfoEntityToServer(kRemoteDeviceCacheGuid,
+                                 kRemoteFCMRegistrationToken);
+  ASSERT_TRUE(SetupSync());
+
+  // Commit a new bookmark to check if the next commit message has FCM
+  // registration tokens.
+  AddFolder(0, GetBookmarkBarNode(0), 0, kTitle);
+  ASSERT_TRUE(ServerBookmarksEqualityChecker(GetSyncService(0), GetFakeServer(),
+                                             {{kTitle, GURL()}},
+                                             /*cryptographer=*/nullptr)
+                  .Wait());
+
+  sync_pb::ClientToServerMessage message;
+  GetFakeServer()->GetLastCommitMessage(&message);
+
+  EXPECT_THAT(
+      message.commit().config_params().devices_fcm_registration_tokens(),
+      ElementsAre(kRemoteFCMRegistrationToken));
+}
+
 class SingleClientWithUseSyncInvalidationsForWalletAndOfferTest
     : public SyncTest {
  public:
diff --git a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
index e5ee3d89..0f26dd3 100644
--- a/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
+++ b/chrome/browser/sync/test/integration/single_client_wallet_sync_test.cc
@@ -665,11 +665,11 @@
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   std::vector<CreditCard*> cards = pdm->GetCreditCards();
   ASSERT_EQ(1uL, cards.size());
-  pdm->RecordUseOf(*cards[0]);
+  pdm->RecordUseOf(cards[0]);
   std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
   ASSERT_EQ(1uL, profiles.size());
   // TODO(crbug.com/941498): Server profiles are not recorded.
-  pdm->RecordUseOf(*profiles[0]);
+  pdm->RecordUseOf(profiles[0]);
 
   // Keep the same data (only change the customer data and the cloud token to
   // force the FakeServer to send the full update).
@@ -723,11 +723,11 @@
   autofill::PersonalDataManager* pdm = GetPersonalDataManager(0);
   std::vector<CreditCard*> cards = pdm->GetCreditCards();
   ASSERT_EQ(1uL, cards.size());
-  pdm->RecordUseOf(*cards[0]);
+  pdm->RecordUseOf(cards[0]);
   std::vector<AutofillProfile*> profiles = pdm->GetServerProfiles();
   ASSERT_EQ(1uL, profiles.size());
   // TODO(crbug.com/941498): Server profiles are not recorded.
-  pdm->RecordUseOf(*profiles[0]);
+  pdm->RecordUseOf(profiles[0]);
 
   // Update the data (also change the customer data to force the full update as
   // FakeServer computes the hash for progress markers only based on ids). For
diff --git a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc
index 919bfe0..a7dc2cd 100644
--- a/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc
+++ b/chrome/browser/sync/test/integration/two_client_send_tab_to_self_sync_test.cc
@@ -298,9 +298,16 @@
 
 // Non-primary accounts don't exist on ChromeOS.
 #if !BUILDFLAG(IS_CHROMEOS_ASH)
+// TODO(crbug.com/1166032): Test times out in component builds.
+#if defined(COMPONENT_BUILD)
+#define MAYBE_SignedInClientCanReceive DISABLED_SignedInClientCanReceive
+#else
+#define MAYBE_SignedInClientCanReceive SignedInClientCanReceive
+#endif
+
 IN_PROC_BROWSER_TEST_F(
     TwoClientSendTabToSelfSyncTestWithSendTabToSelfWhenSignedIn,
-    SignedInClientCanReceive) {
+    MAYBE_SignedInClientCanReceive) {
   ASSERT_TRUE(SetupClients()) << "SetupClients() failed.";
 
   // Set up one client syncing and the other signed-in but not syncing.
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
index 8e22eac..0492b39b 100644
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -794,6 +794,9 @@
       <message name="IDS_PRIVACY_SANDBOX_BULLET_TWO" desc="Second bullet point of the Privacy Sandbox description">
         Allow advertisers to study ad campaigns using non-identifiable information.
       </message>
+      <message name="IDS_PRIVACY_SANDBOX_SNACKBAR_MESSAGE" desc="The text displayed in the snackbar, which gives the user an option to navigate to the Privacy Sandbox settings page. 'Privacy sandbox' has TC ID 5753235213964358658.">
+        Explore the Privacy Sandbox
+      </message>
 
       <!-- Secure DNS Settings.  Used by //chrome/browser/privacy. -->
       <message name="IDS_SETTINGS_CUSTOM" desc="Label for a custom option in a dropdown menu.">
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_SNACKBAR_MESSAGE.png.sha1 b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_SNACKBAR_MESSAGE.png.sha1
new file mode 100644
index 0000000..c29b854
--- /dev/null
+++ b/chrome/browser/ui/android/strings/android_chrome_strings_grd/IDS_PRIVACY_SANDBOX_SNACKBAR_MESSAGE.png.sha1
@@ -0,0 +1 @@
+24e8a92900ea2105ed92dc6e33104e7c45401f64
\ No newline at end of file
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
index 9e3ab1d..f64124d 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.cc
@@ -32,33 +32,6 @@
 
 }  // namespace
 
-// static
-bool AppServiceAppIconLoader::CanLoadImage(Profile* profile,
-                                           const std::string& id) {
-  const std::string app_id = GetAppId(profile, id);
-
-  // Skip the ARC intent helper, the system Android app that proxies links to
-  // Chrome, which should be hidden.
-  if (app_id == kArcIntentHelperAppId) {
-    return false;
-  }
-
-  if (!apps::AppServiceProxyFactory::IsAppServiceAvailableForProfile(profile)) {
-    return false;
-  }
-
-  // Support icon loading for apps registered in AppService or Crostini apps
-  // with the prefix "crostini:".
-  if (apps::AppServiceProxyFactory::GetForProfile(profile)
-              ->AppRegistryCache()
-              .GetAppType(app_id) != apps::mojom::AppType::kUnknown ||
-      crostini::IsUnmatchedCrostiniShelfAppId(app_id)) {
-    return true;
-  }
-
-  return false;
-}
-
 AppServiceAppIconLoader::AppServiceAppIconLoader(
     Profile* profile,
     int resource_size_in_dip,
@@ -72,7 +45,26 @@
 AppServiceAppIconLoader::~AppServiceAppIconLoader() = default;
 
 bool AppServiceAppIconLoader::CanLoadImageForApp(const std::string& id) {
-  return AppServiceAppIconLoader::CanLoadImage(profile(), id);
+  const std::string app_id = GetAppId(profile(), id);
+
+  // Skip the ARC intent helper, the system Android app that proxies links to
+  // Chrome, which should be hidden.
+  if (app_id == kArcIntentHelperAppId) {
+    return false;
+  }
+
+  apps::AppServiceProxy* proxy =
+      apps::AppServiceProxyFactory::GetForProfile(profile());
+
+  // Support icon loading for apps registered in AppService or Crostini apps
+  // with the prefix "crostini:".
+  if (proxy->AppRegistryCache().GetAppType(app_id) !=
+          apps::mojom::AppType::kUnknown ||
+      crostini::IsUnmatchedCrostiniShelfAppId(app_id)) {
+    return true;
+  }
+
+  return false;
 }
 
 void AppServiceAppIconLoader::FetchImage(const std::string& id) {
diff --git a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h
index 9d8f75a..7996b07 100644
--- a/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h
+++ b/chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h
@@ -22,8 +22,6 @@
 class AppServiceAppIconLoader : public AppIconLoader,
                                 private apps::AppRegistryCache::Observer {
  public:
-  static bool CanLoadImage(Profile* profile, const std::string& id);
-
   AppServiceAppIconLoader(Profile* profile,
                           int resource_size_in_dip,
                           AppIconLoaderDelegate* delegate);
diff --git a/chrome/browser/ui/ash/clipboard_history_browsertest.cc b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
index a19005a..a613cd2 100644
--- a/chrome/browser/ui/ash/clipboard_history_browsertest.cc
+++ b/chrome/browser/ui/ash/clipboard_history_browsertest.cc
@@ -806,9 +806,9 @@
            (*data_src->origin() == allowed_origin_);
   }
 
-  bool IsDragDropAllowed(
-      const ui::DataTransferEndpoint* const data_src,
-      const ui::DataTransferEndpoint* const data_dst) override {
+  bool IsDragDropAllowed(const ui::DataTransferEndpoint* const data_src,
+                         const ui::DataTransferEndpoint* const data_dst,
+                         const bool is_drop) override {
     return false;
   }
 
diff --git a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
index 76e39e6..91dd75d 100644
--- a/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
+++ b/chrome/browser/ui/ash/launcher/chrome_launcher_controller.cc
@@ -39,7 +39,6 @@
 #include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h"
 #include "chrome/browser/ui/app_list/app_service/app_service_app_icon_loader.h"
 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
-#include "chrome/browser/ui/app_list/icon_standardizer.h"
 #include "chrome/browser/ui/app_list/md_icon_normalizer.h"
 #include "chrome/browser/ui/apps/app_info_dialog.h"
 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
@@ -929,10 +928,6 @@
 
 void ChromeLauncherController::OnAppImageUpdated(const std::string& app_id,
                                                  const gfx::ImageSkia& image) {
-  bool is_standard_icon = true;
-  if (!AppServiceAppIconLoader::CanLoadImage(latest_active_profile_, app_id))
-    is_standard_icon = false;
-
   // TODO: need to get this working for shortcuts.
   for (int index = 0; index < model_->item_count(); ++index) {
     ash::ShelfItem item = model_->items()[index];
@@ -941,8 +936,7 @@
         item.id.app_id != app_id) {
       continue;
     }
-    item.image =
-        is_standard_icon ? image : app_list::CreateStandardIconImage(image);
+    item.image = image;
     shelf_spinner_controller_->MaybeApplySpinningEffect(app_id, &item.image);
     model_->Set(index, item);
     // It's possible we're waiting on more than one item, so don't break.
diff --git a/chrome/browser/ui/ash/media_client_impl.cc b/chrome/browser/ui/ash/media_client_impl.cc
index 4386052..d172202a 100644
--- a/chrome/browser/ui/ash/media_client_impl.cc
+++ b/chrome/browser/ui/ash/media_client_impl.cc
@@ -313,8 +313,12 @@
     vm_media_capture_state_ |= MediaCaptureState::kAudio;
 
   media_controller_->NotifyVmMediaNotificationState(
-      manager->IsNotificationActive(DeviceType::kCamera),
-      manager->IsNotificationActive(DeviceType::kMic));
+      manager->IsNotificationActive(
+          chromeos::VmCameraMicManager::kCameraNotification),
+      manager->IsNotificationActive(
+          chromeos::VmCameraMicManager::kMicNotification),
+      manager->IsNotificationActive(
+          chromeos::VmCameraMicManager::kCameraAndMicNotification));
 }
 
 void MediaClientImpl::OnCameraPrivacySwitchStatusChanged(
diff --git a/chrome/browser/ui/ash/media_client_impl_unittest.cc b/chrome/browser/ui/ash/media_client_impl_unittest.cc
index 771dc06..dc86acb 100644
--- a/chrome/browser/ui/ash/media_client_impl_unittest.cc
+++ b/chrome/browser/ui/ash/media_client_impl_unittest.cc
@@ -30,7 +30,9 @@
       const base::flat_map<AccountId, ash::MediaCaptureState>& capture_states)
       override {}
 
-  void NotifyVmMediaNotificationState(bool camera, bool mic) override {}
+  void NotifyVmMediaNotificationState(bool camera,
+                                      bool mic,
+                                      bool camera_and_mic) override {}
 
   bool force_media_client_key_handling() const {
     return force_media_client_key_handling_;
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
index 6349c3bc..9e1a86e 100644
--- a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java
@@ -90,6 +90,7 @@
     public static final int UMA_CONDITIONAL_TAB_STRIP_DISMISS_UNDO = 35;
     public static final int UMA_PAINT_PREVIEW_UPGRADE_NOTIFICATION = 36;
     public static final int UMA_READING_LIST_BOOKMARK_ADDED = 37;
+    public static final int UMA_PRIVACY_SANDBOX_PAGE_OPEN = 38;
 
     private SnackbarController mController;
     private CharSequence mText;
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.cc b/chrome/browser/ui/search/ntp_user_data_logger.cc
index 4fec69b..10e963f 100644
--- a/chrome/browser/ui/search/ntp_user_data_logger.cc
+++ b/chrome/browser/ui/search/ntp_user_data_logger.cc
@@ -578,11 +578,17 @@
 }
 
 void NTPUserDataLogger::LogModuleLoaded(const std::string& id,
-                                        base::TimeDelta time) {
-  UMA_HISTOGRAM_LOAD_TIME("NewTabPage.Modules.Loaded", time);
-  base::UmaHistogramCustomTimes("NewTabPage.Modules.Loaded." + id, time,
+                                        base::TimeDelta duration,
+                                        base::TimeDelta time_since_navigation) {
+  UMA_HISTOGRAM_LOAD_TIME("NewTabPage.Modules.Loaded", time_since_navigation);
+  base::UmaHistogramCustomTimes("NewTabPage.Modules.Loaded." + id,
+                                time_since_navigation,
                                 base::TimeDelta::FromMilliseconds(1),
                                 base::TimeDelta::FromSeconds(60), 100);
+  UMA_HISTOGRAM_LOAD_TIME("NewTabPage.Modules.LoadDuration", duration);
+  base::UmaHistogramCustomTimes("NewTabPage.Modules.LoadDuration." + id,
+                                duration, base::TimeDelta::FromMilliseconds(1),
+                                base::TimeDelta::FromSeconds(60), 100);
 }
 
 void NTPUserDataLogger::LogModuleUsage(const std::string& id) {
diff --git a/chrome/browser/ui/search/ntp_user_data_logger.h b/chrome/browser/ui/search/ntp_user_data_logger.h
index b98fd5f6..db352a6 100644
--- a/chrome/browser/ui/search/ntp_user_data_logger.h
+++ b/chrome/browser/ui/search/ntp_user_data_logger.h
@@ -45,7 +45,9 @@
   void LogModuleImpression(const std::string& id, base::TimeDelta time);
 
   // Logs a module is loaded on the NTP.
-  void LogModuleLoaded(const std::string& id, base::TimeDelta time);
+  void LogModuleLoaded(const std::string& id,
+                       base::TimeDelta duration,
+                       base::TimeDelta time_since_navigation);
 
   // Logs when a user interacts with a module which will result in a navigation.
   void LogModuleUsage(const std::string& id);
diff --git a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
index f109afb..af800f70 100644
--- a/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
+++ b/chrome/browser/ui/views/extensions/extension_install_dialog_view_browsertest.cc
@@ -400,6 +400,12 @@
   ShowAndVerifyUi();
 }
 
+// crbug.com/1166152
+#if defined(OS_WIN)
+#define MAYBE_InvokeUi_ManyPermissions DISABLED_InvokeUi_ManyPermissions
+#else
+#define MAYBE_InvokeUi_ManyPermissions InvokeUi_ManyPermissions
+#endif
 IN_PROC_BROWSER_TEST_F(ExtensionInstallDialogViewInteractiveBrowserTest,
                        InvokeUi_ManyPermissions) {
   for (int i = 0; i < 20; i++)
diff --git a/chrome/browser/ui/views/hung_renderer_view.cc b/chrome/browser/ui/views/hung_renderer_view.cc
index febf843..4ce7d12 100644
--- a/chrome/browser/ui/views/hung_renderer_view.cc
+++ b/chrome/browser/ui/views/hung_renderer_view.cc
@@ -80,8 +80,8 @@
   DCHECK(!hang_monitor_restarter.is_null());
 
   DCHECK(!render_widget_host_);
-  DCHECK(!process_observation_.IsObserving());
-  DCHECK(!widget_observation_.IsObserving());
+  DCHECK(!process_observer_.IsObservingSources());
+  DCHECK(!widget_observer_.IsObservingSources());
   DCHECK(tab_observers_.empty());
 
   render_widget_host_ = render_widget_host;
@@ -93,8 +93,8 @@
         std::make_unique<WebContentsObserverImpl>(this, hung_contents));
   }
 
-  process_observation_.Observe(render_widget_host_->GetProcess());
-  widget_observation_.Observe(render_widget_host_);
+  process_observer_.Add(render_widget_host_->GetProcess());
+  widget_observer_.Add(render_widget_host_);
 
   // The world is different.
   if (observer_)
@@ -102,8 +102,8 @@
 }
 
 void HungPagesTableModel::Reset() {
-  process_observation_.Reset();
-  widget_observation_.Reset();
+  process_observer_.RemoveAll();
+  widget_observer_.RemoveAll();
   tab_observers_.clear();
   render_widget_host_ = nullptr;
 
@@ -158,8 +158,8 @@
 
 void HungPagesTableModel::RenderWidgetHostDestroyed(
     content::RenderWidgetHost* widget_host) {
-  DCHECK(widget_observation_.IsObservingSource(render_widget_host_));
-  widget_observation_.Reset();
+  DCHECK(widget_observer_.IsObserving(render_widget_host_));
+  widget_observer_.Remove(widget_host);
   render_widget_host_ = nullptr;
 
   // Notify the delegate.
diff --git a/chrome/browser/ui/views/hung_renderer_view.h b/chrome/browser/ui/views/hung_renderer_view.h
index 3665588..1d487ae 100644
--- a/chrome/browser/ui/views/hung_renderer_view.h
+++ b/chrome/browser/ui/views/hung_renderer_view.h
@@ -10,7 +10,7 @@
 
 #include "base/callback.h"
 #include "base/macros.h"
-#include "base/scoped_observation.h"
+#include "base/scoped_observer.h"
 #include "components/favicon/content/content_favicon_driver.h"
 #include "content/public/browser/render_process_host.h"
 #include "content/public/browser/render_process_host_observer.h"
@@ -124,13 +124,11 @@
   // some more until the renderer process responds).
   base::RepeatingClosure hang_monitor_restarter_;
 
-  base::ScopedObservation<content::RenderProcessHost,
-                          content::RenderProcessHostObserver>
-      process_observation_{this};
+  ScopedObserver<content::RenderProcessHost, content::RenderProcessHostObserver>
+      process_observer_{this};
 
-  base::ScopedObservation<content::RenderWidgetHost,
-                          content::RenderWidgetHostObserver>
-      widget_observation_{this};
+  ScopedObserver<content::RenderWidgetHost, content::RenderWidgetHostObserver>
+      widget_observer_{this};
 
   DISALLOW_COPY_AND_ASSIGN(HungPagesTableModel);
 };
diff --git a/chrome/browser/ui/views/task_manager_view.cc b/chrome/browser/ui/views/task_manager_view.cc
index 47d7153..84f9e5c 100644
--- a/chrome/browser/ui/views/task_manager_view.cc
+++ b/chrome/browser/ui/views/task_manager_view.cc
@@ -38,7 +38,6 @@
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 #include "ash/public/cpp/shelf_item.h"
 #include "ash/public/cpp/window_properties.h"
-#include "chrome/browser/ui/app_list/icon_standardizer.h"
 #include "chrome/grit/theme_resources.h"
 #include "ui/aura/window.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -172,11 +171,8 @@
 
 gfx::ImageSkia TaskManagerView::GetWindowIcon() {
 #if BUILDFLAG(IS_CHROMEOS_ASH)
-  // TODO(crbug.com/1162514): Move app_list::CreateStandardIconImage to some
-  // where lower in the stack.
-  return app_list::CreateStandardIconImage(
-      *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
-          IDR_ASH_SHELF_ICON_TASK_MANAGER));
+  return *ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(
+      IDR_ASH_SHELF_ICON_TASK_MANAGER);
 #else
   return views::DialogDelegateView::GetWindowIcon();
 #endif
diff --git a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
index 4b26fd4e..806cb06 100644
--- a/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
+++ b/chrome/browser/ui/webui/chromeos/login/fingerprint_setup_screen_handler.cc
@@ -25,12 +25,8 @@
 
 void FingerprintSetupScreenHandler::DeclareLocalizedValues(
     ::login::LocalizedValuesBuilder* builder) {
-  builder->AddF("setupFingerprintScreenTitle",
-                IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE,
-                ui::GetChromeOSDeviceName());
-  builder->AddF("setupFingerprintScreenFooter",
-                IDS_OOBE_FINGERPINT_SETUP_SCREEN_ENROLLMENT_FOOTER,
-                ui::GetChromeOSDeviceName());
+  builder->Add("setupFingerprintScreenTitle",
+               IDS_OOBE_FINGERPINT_SETUP_SCREEN_TITLE);
   builder->Add("skipFingerprintSetup",
                IDS_OOBE_FINGERPINT_SETUP_SCREEN_BUTTON_SKIP);
   builder->Add("fingerprintSetupDone",
@@ -75,7 +71,8 @@
           IDS_SETTINGS_ADD_FINGERPRINT_DIALOG_INSTRUCTION_LOCATE_SCANNER_KEYBOARD_TOP_RIGHT_ARIA_LABEL;
       break;
   }
-  builder->Add("setupFingerprintScreenDescription", description_id);
+  builder->AddF("setupFingerprintScreenDescription", description_id,
+                ui::GetChromeOSDeviceName());
   builder->Add("setupFingerprintScreenAriaLabel", aria_label_id);
 }
 
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
index 83178b9..5ba2b97 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page.mojom
@@ -397,8 +397,10 @@
   // Logs a module impression. Called when a module is loaded and can be seen by
   // the user (scrolled into view).
   OnModuleImpression(string module_id, double time);
-  // Logs when a module is loaded with data.
-  OnModuleLoaded(string module_id, double time);
+  // Logs that a module loaded data for |duration| and finished successfully at
+  // |time|.
+  OnModuleLoaded(string module_id, mojo_base.mojom.TimeDelta duration,
+                 double time);
   // Logs when a user interacts with a module which will result in a navigation.
   OnModuleUsage(string module_id);
   // Logs that the modules have been shown at |time|.
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
index b0196e9..2e19ae50 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.cc
@@ -999,9 +999,11 @@
 }
 
 void NewTabPageHandler::OnModuleLoaded(const std::string& module_id,
+                                       base::TimeDelta duration,
                                        double time) {
   logger_.LogModuleLoaded(
-      module_id, base::Time::FromJsTime(time) - ntp_navigation_start_time_);
+      module_id, base::Time::FromJsTime(time) - ntp_navigation_start_time_,
+      duration);
 }
 
 void NewTabPageHandler::OnModuleUsage(const std::string& module_id) {
diff --git a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
index f57a202..f18b85a 100644
--- a/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
+++ b/chrome/browser/ui/webui/new_tab_page/new_tab_page_handler.h
@@ -139,7 +139,9 @@
       new_tab_page::mojom::VoiceSearchAction action) override;
   void OnVoiceSearchError(new_tab_page::mojom::VoiceSearchError error) override;
   void OnModuleImpression(const std::string& module_id, double time) override;
-  void OnModuleLoaded(const std::string& module_id, double time) override;
+  void OnModuleLoaded(const std::string& module_id,
+                      base::TimeDelta duration,
+                      double time) override;
   void OnModuleUsage(const std::string& module_id) override;
   void OnModulesRendered(double time) override;
   void QueryAutocomplete(const base::string16& input,
diff --git a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
index 0f67bfa..1f98e4ab 100644
--- a/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
+++ b/chrome/browser/ui/webui/reset_password/reset_password_ui.cc
@@ -89,10 +89,13 @@
   if (!nav_entry || !nav_entry->GetHasPostData())
     return PasswordType::PASSWORD_TYPE_UNKNOWN;
   auto& post_data = nav_entry->GetPostData()->elements()->at(0);
-  int post_data_int = -1;
-  if (base::StringToInt(std::string(post_data.bytes(), post_data.length()),
-                        &post_data_int)) {
-    return static_cast<PasswordType>(post_data_int);
+  if (post_data.type() == network::DataElement::Tag::kBytes) {
+    int post_data_int = -1;
+    if (base::StringToInt(
+            post_data.As<network::DataElementBytes>().AsStringPiece(),
+            &post_data_int)) {
+      return static_cast<PasswordType>(post_data_int);
+    }
   }
 
   return PasswordType::PASSWORD_TYPE_UNKNOWN;
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.cc b/chrome/browser/ui/webui/signin/profile_picker_handler.cc
index 3f345d0..7a176d5 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_handler.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_handler.cc
@@ -209,6 +209,10 @@
   // TODO(crbug.com/1115056): Consider renaming this message to
   // 'createLocalProfile' as this is only used for local profiles.
   web_ui()->RegisterMessageCallback(
+      "getAvailableIcons",
+      base::BindRepeating(&ProfilePickerHandler::HandleGetAvailableIcons,
+                          base::Unretained(this)));
+  web_ui()->RegisterMessageCallback(
       "createProfile",
       base::BindRepeating(&ProfilePickerHandler::HandleCreateProfile,
                           base::Unretained(this)));
@@ -356,31 +360,33 @@
   ResolveJavascriptCallback(callback_id, std::move(dict));
 }
 
+void ProfilePickerHandler::HandleGetAvailableIcons(
+    const base::ListValue* args) {
+  AllowJavascript();
+  CHECK_EQ(1U, args->GetSize());
+  const base::Value& callback_id = args->GetList()[0];
+  ResolveJavascriptCallback(callback_id,
+                            *profiles::GetCustomProfileAvatarIconsAndLabels());
+}
+
 void ProfilePickerHandler::HandleCreateProfile(const base::ListValue* args) {
-  // profileName, profileColor, avatarUrl, isGeneric, createShortcut
-  CHECK_EQ(5U, args->GetList().size());
+  CHECK_EQ(4U, args->GetList().size());
   base::string16 profile_name =
       base::UTF8ToUTF16(args->GetList()[0].GetString());
   // profileColor is undefined for the default theme.
   base::Optional<SkColor> profile_color;
   if (args->GetList()[1].is_int())
     profile_color = args->GetList()[1].GetInt();
-  std::string avatar_url = args->GetList()[2].GetString();
-  bool is_generic = args->GetList()[3].GetBool();
-  bool create_shortcut = args->GetList()[4].GetBool();
-  DCHECK(base::IsStringASCII(avatar_url));
+  size_t avatar_index = args->GetList()[2].GetInt();
+  bool create_shortcut = args->GetList()[3].GetBool();
   base::TrimWhitespace(profile_name, base::TRIM_ALL, &profile_name);
   CHECK(!profile_name.empty());
-  if (is_generic) {
-    avatar_url = profiles::GetDefaultAvatarIconUrl(
-        profiles::GetPlaceholderAvatarIndex());
-  }
 
 #ifndef NDEBUG
-  size_t icon_index;
-  DCHECK(profiles::IsDefaultAvatarIconUrl(avatar_url, &icon_index));
+  DCHECK(profiles::IsDefaultAvatarIconIndex(avatar_index));
 #endif
 
+  std::string avatar_url = profiles::GetDefaultAvatarIconUrl(avatar_index);
   ProfileMetrics::LogProfileAddNewUser(
       ProfileMetrics::ADD_NEW_PROFILE_PICKER_LOCAL);
   ProfileManager::CreateMultiProfileAsync(
@@ -683,6 +689,8 @@
 }
 
 void ProfilePickerHandler::OnProfileAdded(const base::FilePath& profile_path) {
+  if (profile_path == ProfileManager::GetGuestProfilePath())
+    return;
   size_t number_of_profiles = profiles_order_.size();
   profiles_order_[profile_path] = number_of_profiles;
   PushProfilesList();
@@ -692,6 +700,8 @@
     const base::FilePath& profile_path,
     const base::string16& profile_name) {
   DCHECK(IsJavascriptAllowed());
+  if (profile_path == ProfileManager::GetGuestProfilePath())
+    return;
   size_t index = profiles_order_[profile_path];
   profiles_order_.erase(profile_path);
   for (auto it : profiles_order_) {
diff --git a/chrome/browser/ui/webui/signin/profile_picker_handler.h b/chrome/browser/ui/webui/signin/profile_picker_handler.h
index 1966cb08..b855b86 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_handler.h
+++ b/chrome/browser/ui/webui/signin/profile_picker_handler.h
@@ -47,6 +47,7 @@
   void HandleLoadSignInProfileCreationFlow(const base::ListValue* args);
   void HandleGetNewProfileSuggestedThemeInfo(const base::ListValue* args);
   void HandleGetProfileThemeInfo(const base::ListValue* args);
+  void HandleGetAvailableIcons(const base::ListValue* args);
   void HandleCreateProfile(const base::ListValue* args);
 
   // |args| is unused.
diff --git a/chrome/browser/ui/webui/signin/profile_picker_ui.cc b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
index 16da9bb..10fd195 100644
--- a/chrome/browser/ui/webui/signin/profile_picker_ui.cc
+++ b/chrome/browser/ui/webui/signin/profile_picker_ui.cc
@@ -9,6 +9,7 @@
 #include "chrome/browser/browser_process.h"
 #include "chrome/browser/policy/browser_signin_policy_handler.h"
 #include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_avatar_icon_util.h"
 #include "chrome/browser/profiles/profile_shortcut_manager.h"
 #include "chrome/browser/signin/signin_util.h"
 #include "chrome/browser/ui/profile_picker.h"
@@ -117,6 +118,11 @@
        IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_SHORTCUT_TEXT},
       {"createProfileConfirm",
        IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_DONE},
+      {"defaultAvatarLabel", IDS_DEFAULT_AVATAR_LABEL_26},
+      {"selectAnAvatarDialogTitle",
+       IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_TEXT},
+      {"selectAvatarDoneButtonLabel",
+       IDS_PROFILE_PICKER_PROFILE_CREATION_FLOW_LOCAL_PROFILE_CREATION_AVATAR_DONE},
 
       // Color picker.
       {"colorPickerLabel", IDS_NTP_CUSTOMIZE_COLOR_PICKER_LABEL},
@@ -144,6 +150,9 @@
   html_source->AddString("minimumPickerSize",
                          base::StringPrintf("%ipx", kMinimumPickerSizePx));
 
+  html_source->AddInteger("placeholderAvatarIndex",
+                          profiles::GetPlaceholderAvatarIndex());
+
   // Add policies.
   html_source->AddBoolean("isBrowserSigninAllowed", IsBrowserSigninAllowed());
   html_source->AddBoolean("isForceSigninEnabled",
@@ -153,7 +162,6 @@
                           IsProfileCreationAllowed());
   html_source->AddBoolean("profileShortcutsEnabled",
                           ProfileShortcutManager::IsFeatureEnabled());
-  // TODO(crbug.com/1063856): Check if |BrowserSignin| device policy exists.
 }
 
 }  // namespace
diff --git a/chrome/browser/web_share_target/target_util_unittest.cc b/chrome/browser/web_share_target/target_util_unittest.cc
index 69431ee..aa7b8ac 100644
--- a/chrome/browser/web_share_target/target_util_unittest.cc
+++ b/chrome/browser/web_share_target/target_util_unittest.cc
@@ -11,18 +11,19 @@
 namespace web_share_target {
 
 std::string convertDataElementToString(const network::DataElement& element) {
-  if (element.type() == network::mojom::DataElementType::kBytes) {
-    return std::string(element.bytes(), element.length());
+  if (element.type() == network::DataElement::Tag::kBytes) {
+    return std::string(element.As<network::DataElementBytes>().AsStringPiece());
   }
-  if (element.type() == network::mojom::DataElementType::kFile) {
-    return std::string(element.path().AsUTF8Unsafe());
+  if (element.type() == network::DataElement::Tag::kFile) {
+    return std::string(
+        element.As<network::DataElementFile>().path().AsUTF8Unsafe());
   }
   return "";
 }
 
 void CheckDataElements(
     const scoped_refptr<network::ResourceRequestBody>& body,
-    const std::vector<network::mojom::DataElementType>& expected_element_types,
+    const std::vector<network::DataElement::Tag>& expected_element_types,
     const std::vector<std::string>& expected_element_values) {
   EXPECT_NE(nullptr, body->elements());
   const std::vector<network::DataElement>& data_elements = *body->elements();
@@ -67,12 +68,10 @@
       ComputeMultipartBody(names, values, is_value_file_uris, filenames, types,
                            boundary);
 
-  std::vector<network::mojom::DataElementType> expected_types = {
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kFile,
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kBytes};
+  std::vector<network::DataElement::Tag> expected_types = {
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kFile,
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kBytes,
+      network::DataElement::Tag::kBytes};
   std::vector<std::string> expected = {
       "--boundary\r\nContent-Disposition: form-data; name=\"share-file%22\"; "
       "filename=\"filename%0D%0A\"\r\nContent-Type: type\r\n\r\n",
@@ -97,9 +96,8 @@
       ComputeMultipartBody(names, values, is_value_file_uris, filenames, types,
                            boundary);
 
-  std::vector<network::mojom::DataElementType> expected_types = {
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kBytes};
+  std::vector<network::DataElement::Tag> expected_types = {
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kBytes};
   std::vector<std::string> expected = {
       "--boundary\r\nContent-Disposition: form-data; "
       "name=\"name%22\"\r\nContent-Type: type\r\n\r\nvalue\r\n",
@@ -126,27 +124,24 @@
   scoped_refptr<network::ResourceRequestBody> body = ComputeMultipartBody(
       names, values, is_value_file_uris, filenames, types, boundary);
 
-  std::vector<network::mojom::DataElementType> expected_types = {
+  std::vector<network::DataElement::Tag> expected_types = {
       // item 1
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes,
       // item 2
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kFile,
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kFile,
+      network::DataElement::Tag::kBytes,
       // item 3
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kFile,
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kFile,
+      network::DataElement::Tag::kBytes,
       // item 4
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes,
       // item 5
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kFile,
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kFile,
+      network::DataElement::Tag::kBytes,
       // item 6
-      network::mojom::DataElementType::kBytes,
+      network::DataElement::Tag::kBytes,
       // ending
-      network::mojom::DataElementType::kBytes};
+      network::DataElement::Tag::kBytes};
   std::vector<std::string> expected = {
       // item 1
       "--boundary\r\nContent-Disposition: form-data; "
@@ -185,9 +180,8 @@
       names, values, is_value_file_uris, filenames, types, boundary);
   EXPECT_NE(nullptr, body->elements());
 
-  std::vector<network::mojom::DataElementType> expected_types = {
-      network::mojom::DataElementType::kBytes,
-      network::mojom::DataElementType::kBytes};
+  std::vector<network::DataElement::Tag> expected_types = {
+      network::DataElement::Tag::kBytes, network::DataElement::Tag::kBytes};
   std::vector<std::string> expected = {
       "--boundary\r\nContent-Disposition: form-data;"
       " name=\"name\"; filename=\"filename\"\r\nContent-Type: type"
diff --git a/chrome/build/linux.pgo.txt b/chrome/build/linux.pgo.txt
index 54b287e24..8fdc131 100644
--- a/chrome/build/linux.pgo.txt
+++ b/chrome/build/linux.pgo.txt
@@ -1 +1 @@
-chrome-linux-master-1610495996-ac73e18e1b2efb1cd1bfbf2a2aaf90e9e3476b5a.profdata
+chrome-linux-master-1610538373-541aee2d8154a147aea334eed2074efc5a2f470f.profdata
diff --git a/chrome/build/mac.pgo.txt b/chrome/build/mac.pgo.txt
index b392018b..5edb548 100644
--- a/chrome/build/mac.pgo.txt
+++ b/chrome/build/mac.pgo.txt
@@ -1 +1 @@
-chrome-mac-master-1610495996-38f3d5c57ab4be3d52eaefe38d45ce16ec0addd8.profdata
+chrome-mac-master-1610538373-c4c83fd08459537f19e890c14c2288baf23d3675.profdata
diff --git a/chrome/build/win32.pgo.txt b/chrome/build/win32.pgo.txt
index 4f696ae..7bafa3dc 100644
--- a/chrome/build/win32.pgo.txt
+++ b/chrome/build/win32.pgo.txt
@@ -1 +1 @@
-chrome-win32-master-1610495996-5598384ad8a00037e18a56fd00981ea765e31cd1.profdata
+chrome-win32-master-1610528340-b101588b91e5587ca53d6a4d812cdea4439c3876.profdata
diff --git a/chrome/build/win64.pgo.txt b/chrome/build/win64.pgo.txt
index 435afb8..d5eb974 100644
--- a/chrome/build/win64.pgo.txt
+++ b/chrome/build/win64.pgo.txt
@@ -1 +1 @@
-chrome-win64-master-1610495996-7189a1d14c9908600535ebce9352fe55a59722e6.profdata
+chrome-win64-master-1610528340-1fc68c0c17222e2254fe428312433be61c378c49.profdata
diff --git a/chrome/services/speech/cloud_speech_recognition_client_unittest.cc b/chrome/services/speech/cloud_speech_recognition_client_unittest.cc
index 1264cad..d014aa59 100644
--- a/chrome/services/speech/cloud_speech_recognition_client_unittest.cc
+++ b/chrome/services/speech/cloud_speech_recognition_client_unittest.cc
@@ -184,16 +184,15 @@
           GetUpstreamRequest();
       EXPECT_TRUE(upstream_request);
       EXPECT_TRUE(upstream_request->request.request_body);
-      EXPECT_EQ(1u, upstream_request->request.request_body->elements()->size());
-      EXPECT_EQ(
-          network::mojom::DataElementType::kChunkedDataPipe,
-          (*upstream_request->request.request_body->elements())[0].type());
-      network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
-          const_cast<network::TestURLLoaderFactory::PendingRequest*>(
-              upstream_request);
-      chunked_data_pipe_getter_.Bind((*mutable_upstream_request->request
-                                           .request_body->elements_mutable())[0]
-                                         .ReleaseChunkedDataPipeGetter());
+      auto& mutable_elements =
+          *upstream_request->request.request_body->elements_mutable();
+      ASSERT_EQ(1u, mutable_elements.size());
+      ASSERT_EQ(network::DataElement::Tag::kChunkedDataPipe,
+                mutable_elements[0].type());
+      chunked_data_pipe_getter_.Bind(
+          mutable_elements[0]
+              .As<network::DataElementChunkedDataPipe>()
+              .ReleaseChunkedDataPipeGetter());
     }
 
     constexpr size_t kDataPipeCapacity = 256;
diff --git a/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js b/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js
index 5fe38fb..c75587aa 100644
--- a/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js
+++ b/chrome/test/data/webui/cr_elements/cr_profile_avatar_selector_tests.js
@@ -20,9 +20,9 @@
     const avatarSelector = /** @type {!CrProfileAvatarSelectorElement} */ (
         document.createElement('cr-profile-avatar-selector'));
     avatarSelector.avatars = [
-      {url: 'chrome://avatar1.png', label: 'avatar1'},
-      {url: 'chrome://avatar2.png', label: 'avatar2'},
-      {url: 'chrome://avatar3.png', label: 'avatar3'}
+      {url: 'chrome://avatar1.png', label: 'avatar1', index: '1'},
+      {url: 'chrome://avatar2.png', label: 'avatar2', index: '2'},
+      {url: 'chrome://avatar3.png', label: 'avatar3', index: '3'}
     ];
     return avatarSelector;
   }
diff --git a/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js b/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
index 522288f..c04b871 100644
--- a/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
+++ b/chrome/test/data/webui/new_tab_page/modules/module_descriptor_test.js
@@ -21,8 +21,11 @@
   test('instantiate module with data', async () => {
     // Arrange.
     const element = document.createElement('div');
-    const moduleDescriptor =
-        new ModuleDescriptor('foo', 100, () => Promise.resolve(element));
+    const moduleDescriptor = new ModuleDescriptor('foo', 100, () => {
+      // Move time forward to simulate delay instantiating module.
+      testProxy.setResultFor('now', 128);
+      return Promise.resolve(element);
+    });
     testProxy.setResultFor('now', 123);
 
     // Act.
@@ -30,10 +33,12 @@
 
     // Assert.
     assertEquals(element, moduleDescriptor.element);
-    const [id, now] = await testProxy.handler.whenCalled('onModuleLoaded');
+    const [id, now, delta] =
+        await testProxy.handler.whenCalled('onModuleLoaded');
     assertEquals(1, testProxy.handler.getCallCount('onModuleLoaded'));
     assertEquals('foo', id);
-    assertEquals(123, now);
+    assertEquals(128, now);
+    assertEquals(5000n, delta.microseconds);  // 128ms - 123ms === 5000µs.
   });
 
   test('instantiate module without data', async () => {
diff --git a/chrome/test/data/webui/signin/local_profile_customization_test.js b/chrome/test/data/webui/signin/local_profile_customization_test.js
index e4d34ac..c9bdc2b37 100644
--- a/chrome/test/data/webui/signin/local_profile_customization_test.js
+++ b/chrome/test/data/webui/signin/local_profile_customization_test.js
@@ -21,6 +21,8 @@
   /** @type {!TestManageProfilesBrowserProxy} */
   let browserProxy;
 
+  const defaultAvatarIndex = 26;
+
   async function resetCustomizeProfileElement() {
     document.body.innerHTML = '';
     customizeProfileElement = /** @type {!LocalProfileCustomizationElement} */ (
@@ -52,18 +54,16 @@
   /**
    * @param {string} profileName
    * @param {number} profileColor
-   * @param {string} avatarUrl
-   * @param {boolean} isGeneric
+   * @param {number} avatarIndex
    * @param {boolean} createShortcut
    */
   async function verifyCreateProfileCalledWithParams(
-      profileName, profileColor, avatarUrl, isGeneric, createShortcut) {
+      profileName, profileColor, avatarIndex, createShortcut) {
     const args = await browserProxy.whenCalled('createProfile');
     assertEquals(args[0], profileName);
     assertEquals(args[1], profileColor);
-    assertEquals(args[2], avatarUrl);
-    assertEquals(args[3], isGeneric);
-    assertEquals(args[4], createShortcut);
+    assertEquals(args[2], avatarIndex);
+    assertEquals(args[3], createShortcut);
     browserProxy.resetResolver('createProfile');
   }
 
@@ -86,7 +86,7 @@
     assertFalse(customizeProfileElement.$$('#save').disabled);
     customizeProfileElement.$$('#save').click();
     await verifyCreateProfileCalledWithParams(
-        'Work', browserProxy.profileThemeInfo.color, '', true, false);
+        'Work', browserProxy.profileThemeInfo.color, defaultAvatarIndex, false);
   });
 
   test('ThemeSelectionChanges', async function() {
@@ -122,7 +122,8 @@
     customizeProfileElement.$$('#nameInput').value = 'Personal';
     customizeProfileElement.$$('#save').click();
     await verifyCreateProfileCalledWithParams(
-        'Personal', browserProxy.profileThemeInfo.color, '', true, false);
+        'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
+        false);
   });
 
   test('createShortcut', async function() {
@@ -142,7 +143,8 @@
     customizeProfileElement.$$('#nameInput').value = 'Personal';
     customizeProfileElement.$$('#save').click();
     await verifyCreateProfileCalledWithParams(
-        'Personal', browserProxy.profileThemeInfo.color, '', true, false);
+        'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
+        false);
     // Profile creation in progress should disable the save button.
     assertTrue(customizeProfileElement.$$('#save').disabled);
     // Fire profile creation finished.
@@ -153,6 +155,7 @@
     assertTrue(createShortcut.checked);
     customizeProfileElement.$$('#save').click();
     await verifyCreateProfileCalledWithParams(
-        'Personal', browserProxy.profileThemeInfo.color, '', true, true);
+        'Personal', browserProxy.profileThemeInfo.color, defaultAvatarIndex,
+        true);
   });
 });
diff --git a/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js b/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js
index 95e4e6f6..2896af2 100644
--- a/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js
+++ b/chrome/test/data/webui/signin/test_manage_profiles_browser_proxy.js
@@ -23,6 +23,7 @@
       'createProfile',
       'setProfileName',
       'recordSignInPromoImpression',
+      'getAvailableIcons',
     ]);
 
     /** @type {!AutogeneratedThemeColorInfo} */
@@ -106,11 +107,10 @@
   }
 
   /** @override */
-  createProfile(
-      profileName, profileColor, avatarUrl, isGeneric, createShortcut) {
+  createProfile(profileName, profileColor, avatarIndex, createShortcut) {
     this.methodCalled(
         'createProfile',
-        [profileName, profileColor, avatarUrl, isGeneric, createShortcut]);
+        [profileName, profileColor, avatarIndex, createShortcut]);
   }
 
   /** @override */
@@ -122,4 +122,14 @@
   recordSignInPromoImpression() {
     this.methodCalled('recordSignInPromoImpression');
   }
+
+  /** @override */
+  getAvailableIcons() {
+    this.methodCalled('getAvailableIcons');
+    return Promise.resolve([
+      {url: 'fake-icon-1.png', label: 'fake-icon-1', index: 1, selected: false},
+      {url: 'fake-icon-2.png', label: 'fake-icon-2', index: 2, selected: false},
+      {url: 'fake-icon-3.png', label: 'fake-icon-3', index: 3, selected: false},
+    ]);
+  }
 }
diff --git a/chrome/updater/test/integration_tests.cc b/chrome/updater/test/integration_tests.cc
index 7628a82..ed2aa21 100644
--- a/chrome/updater/test/integration_tests.cc
+++ b/chrome/updater/test/integration_tests.cc
@@ -312,7 +312,14 @@
   Clean();
 }
 
-TEST_F(IntegrationTest, UnregisterUnownedApp) {
+// TODO(https://crbug.com/1166196): Fix flaky timeouts. The timeout is in
+// RunWake(0).
+#if defined(OS_MAC)
+#define MAYBE_UnregisterUnownedApp DISABLED_UnregisterUnownedApp
+#else
+#define MAYBE_UnregisterUnownedApp UnregisterUnownedApp
+#endif
+TEST_F(IntegrationTest, MAYBE_UnregisterUnownedApp) {
   RegisterTestApp();
   ExpectInstalled();
   ExpectActiveVersion(UPDATER_VERSION_STRING);
diff --git a/chromeos/services/assistant/chromium_http_connection.cc b/chromeos/services/assistant/chromium_http_connection.cc
index 2f002fd5..7602bcc 100644
--- a/chromeos/services/assistant/chromium_http_connection.cc
+++ b/chromeos/services/assistant/chromium_http_connection.cc
@@ -163,7 +163,8 @@
     receiver_set_.Add(this, data_remote.InitWithNewPipeAndPassReceiver());
     resource_request->request_body = new network::ResourceRequestBody();
     resource_request->request_body->SetToChunkedDataPipe(
-        std::move(data_remote));
+        std::move(data_remote),
+        network::ResourceRequestBody::ReadOnlyOnce(false));
   }
 
   url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
diff --git a/components/autofill/core/browser/autofill_download_manager_unittest.cc b/components/autofill/core/browser/autofill_download_manager_unittest.cc
index f939418..47fde35 100644
--- a/components/autofill/core/browser/autofill_download_manager_unittest.cc
+++ b/components/autofill/core/browser/autofill_download_manager_unittest.cc
@@ -87,10 +87,11 @@
     const std::vector<network::DataElement>* data_elements) {
   std::string result;
   for (const network::DataElement& e : *data_elements) {
-    DCHECK_EQ(e.type(), network::mojom::DataElementType::kBytes);
+    DCHECK_EQ(e.type(), network::DataElement::Tag::kBytes);
     // Provide the length of the bytes explicitly, not to rely on the null
     // termination.
-    result.append(e.bytes(), base::checked_cast<size_t>(e.length()));
+    const auto piece = e.As<network::DataElementBytes>().AsStringPiece();
+    result.append(piece.data(), piece.size());
   }
   return result;
 }
diff --git a/components/autofill/core/browser/autofill_manager.cc b/components/autofill/core/browser/autofill_manager.cc
index 020107db..b240931 100644
--- a/components/autofill/core/browser/autofill_manager.cc
+++ b/components/autofill/core/browser/autofill_manager.cc
@@ -413,23 +413,25 @@
 
 AutofillManager::FillingContext::FillingContext(
     const AutofillField& field,
-    const AutofillProfile* optional_profile,
-    const CreditCard* optional_credit_card,
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card,
     const base::string16* optional_cvc)
-    : profile(optional_profile ? base::make_optional(*optional_profile)
-                               : base::nullopt),
-      credit_card(optional_credit_card
-                      ? base::make_optional(std::make_pair(
-                            *optional_credit_card,
-                            optional_cvc ? *optional_cvc : base::string16()))
-                      : base::nullopt),
-      filled_field_renderer_id(field.unique_renderer_id),
+    : filled_field_renderer_id(field.unique_renderer_id),
       filled_field_signature(field.GetFieldSignature()),
       filled_field_unique_name(field.unique_name()),
       original_fill_time(AutofillTickClock::NowTicks()) {
-  DCHECK(optional_profile || optional_credit_card);
-  DCHECK(optional_credit_card || !optional_cvc);
-  DCHECK(profile || credit_card);
+  DCHECK(absl::holds_alternative<const CreditCard*>(profile_or_credit_card) ||
+         !optional_cvc);
+
+  if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card)) {
+    profile_or_credit_card_with_cvc =
+        *absl::get<const AutofillProfile*>(profile_or_credit_card);
+  } else if (absl::holds_alternative<const CreditCard*>(
+                 profile_or_credit_card)) {
+    profile_or_credit_card_with_cvc =
+        std::make_pair(*absl::get<const CreditCard*>(profile_or_credit_card),
+                       optional_cvc ? *optional_cvc : base::string16());
+  }
 }
 
 AutofillManager::FillingContext::~FillingContext() = default;
@@ -1071,9 +1073,8 @@
         credit_card_, *form_structure, *autofill_field, sync_state_);
   }
 
-  FillOrPreviewDataModelForm(action, query_id, form, field, /*profile=*/nullptr,
-                             &credit_card_, /*cvc=*/nullptr, form_structure,
-                             autofill_field);
+  FillOrPreviewDataModelForm(action, query_id, form, field, &credit_card_,
+                             /*cvc=*/nullptr, form_structure, autofill_field);
 }
 
 void AutofillManager::FillOrPreviewProfileForm(
@@ -1092,7 +1093,6 @@
   }
 
   FillOrPreviewDataModelForm(action, query_id, form, field, &profile,
-                             /*credit_card=*/nullptr,
                              /*cvc=*/nullptr, form_structure, autofill_field);
 }
 
@@ -1135,8 +1135,8 @@
     return;
 
   FillOrPreviewDataModelForm(AutofillDriver::FORM_DATA_ACTION_FILL, query_id,
-                             form, field, /*profile=*/nullptr, &credit_card,
-                             &cvc, form_structure, autofill_field);
+                             form, field, &credit_card, &cvc, form_structure,
+                             autofill_field);
 }
 
 void AutofillManager::FillProfileForm(const autofill::AutofillProfile& profile,
@@ -1630,25 +1630,19 @@
     int query_id,
     const FormData& form,
     const FormFieldData& field,
-    const AutofillProfile* optional_profile,
-    const CreditCard* optional_credit_card,
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card,
     const base::string16* optional_cvc,
     FormStructure* form_structure,
     AutofillField* autofill_field,
     bool is_refill) {
-  DCHECK(optional_profile || optional_credit_card);
-  DCHECK(optional_credit_card || !optional_cvc);
+  bool is_credit_card =
+      absl::holds_alternative<const CreditCard*>(profile_or_credit_card);
+
+  DCHECK(is_credit_card || !optional_cvc);
   DCHECK(form_structure);
   DCHECK(autofill_field);
 
-  const AutofillDataModel& data_model = [&]() -> const AutofillDataModel& {
-    if (optional_profile)
-      return *optional_profile;
-    else
-      return *optional_credit_card;
-  }();
-  bool is_credit_card = !!optional_credit_card;
-
   LogBuffer buffer;
   buffer << "is credit card section: " << is_credit_card << Br{};
   buffer << "is refill: " << is_refill << Br{};
@@ -1661,9 +1655,10 @@
   DCHECK_EQ(form_structure->field_count(), form.fields.size());
 
   if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill) {
-    SetFillingContext(*form_structure, std::make_unique<FillingContext>(
-                                           *autofill_field, optional_profile,
-                                           optional_credit_card, optional_cvc));
+    SetFillingContext(
+        *form_structure,
+        std::make_unique<FillingContext>(*autofill_field,
+                                         profile_or_credit_card, optional_cvc));
   }
 
   // Only record the types that are filled for an eventual refill if all the
@@ -1761,8 +1756,8 @@
 
     // Don't fill expired cards expiration date.
     if (data_util::IsCreditCardExpirationType(field_type) &&
-        (!optional_credit_card ||
-         optional_credit_card->IsExpired(AutofillClock::Now()))) {
+        (is_credit_card && absl::get<const CreditCard*>(profile_or_credit_card)
+                               ->IsExpired(AutofillClock::Now()))) {
       buffer << Tr{} << field_number
              << "Skipped: don't fill expiration date of expired cards";
       continue;
@@ -1795,9 +1790,9 @@
     const base::string16 kEmptyCvc{};
     std::string failure_to_fill;  // Reason for failing to fill.
 
-    // Fill the non-empty value from |data_model| into the result vector, which
-    // will be sent to the renderer.
-    FillFieldWithValue(cached_field, data_model, &result.fields[i],
+    // Fill the non-empty value from |profile_or_credit_card| into the result
+    // vector, which will be sent to the renderer.
+    FillFieldWithValue(cached_field, profile_or_credit_card, &result.fields[i],
                        should_notify, optional_cvc ? *optional_cvc : kEmptyCvc,
                        data_util::DetermineGroups(*form_structure),
                        &failure_to_fill);
@@ -1822,9 +1817,9 @@
   if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
     autofilled_form_signatures_.pop_back();
 
-  // Note that this may invalidate |data_model|.
+  // Note that this may invalidate |profile_or_credit_card|.
   if (action == AutofillDriver::FORM_DATA_ACTION_FILL && !is_refill)
-    personal_data_->RecordUseOf(data_model);
+    personal_data_->RecordUseOf(profile_or_credit_card);
 
   if (log_manager_) {
     log_manager_->Log() << LoggingScope::kFilling
@@ -2309,15 +2304,17 @@
   }
 }
 
-void AutofillManager::FillFieldWithValue(AutofillField* autofill_field,
-                                         const AutofillDataModel& data_model,
-                                         FormFieldData* field_data,
-                                         bool should_notify,
-                                         const base::string16& cvc,
-                                         uint32_t profile_form_bitmask,
-                                         std::string* failure_to_fill) {
-  if (field_filler_.FillFormField(*autofill_field, data_model, field_data, cvc,
-                                  failure_to_fill)) {
+void AutofillManager::FillFieldWithValue(
+    AutofillField* autofill_field,
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card,
+    FormFieldData* field_data,
+    bool should_notify,
+    const base::string16& cvc,
+    uint32_t profile_form_bitmask,
+    std::string* failure_to_fill) {
+  if (field_filler_.FillFormField(*autofill_field, profile_or_credit_card,
+                                  field_data, cvc, failure_to_fill)) {
     if (failure_to_fill)
       *failure_to_fill = "Decided to fill";
     // Mark the cached field as autofilled, so that we can detect when a
@@ -2333,10 +2330,14 @@
         client_->GetSecurityLevelForUmaHistograms(), profile_form_bitmask);
 
     if (should_notify) {
+      DCHECK(absl::holds_alternative<const AutofillProfile*>(
+          profile_or_credit_card));
+      const AutofillProfile* profile =
+          absl::get<const AutofillProfile*>(profile_or_credit_card);
       client_->DidFillOrPreviewField(
-          /*value=*/data_model.GetInfo(autofill_field->Type(), app_locale_),
-          /*profile_full_name=*/data_model.GetInfo(AutofillType(NAME_FULL),
-                                                   app_locale_));
+          /*value=*/profile->GetInfo(autofill_field->Type(), app_locale_),
+          /*profile_full_name=*/profile->GetInfo(AutofillType(NAME_FULL),
+                                                 app_locale_));
     }
   }
 }
@@ -2463,22 +2464,28 @@
     return;
 
   FormFieldData field = *autofill_field;
-  if (filling_context->credit_card) {
+  if (absl::holds_alternative<std::pair<CreditCard, base::string16>>(
+          filling_context->profile_or_credit_card_with_cvc)) {
     FillOrPreviewDataModelForm(
         AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
         /*query_id=*/-1, form, field,
-        /*profile=*/nullptr, &filling_context->credit_card.value().first,
-        &filling_context->credit_card.value().second, form_structure,
-        autofill_field,
+        &absl::get<std::pair<CreditCard, base::string16>>(
+             filling_context->profile_or_credit_card_with_cvc)
+             .first,
+        &absl::get<std::pair<CreditCard, base::string16>>(
+             filling_context->profile_or_credit_card_with_cvc)
+             .second,
+        form_structure, autofill_field,
         /*is_refill=*/true);
   }
-  if (filling_context->profile) {
+  if (absl::holds_alternative<AutofillProfile>(
+          filling_context->profile_or_credit_card_with_cvc)) {
     FillOrPreviewDataModelForm(
         AutofillDriver::RendererFormDataAction::FORM_DATA_ACTION_FILL,
-        /*query_id=*/-1, form, field, &filling_context->profile.value(),
-        /*credic_card=*/nullptr, /*cvc=*/nullptr, form_structure,
-        autofill_field,
-        /*is_refill=*/true);
+        /*query_id=*/-1, form, field,
+        &absl::get<AutofillProfile>(
+            filling_context->profile_or_credit_card_with_cvc),
+        /*cvc=*/nullptr, form_structure, autofill_field, /*is_refill=*/true);
   }
 }
 
diff --git a/components/autofill/core/browser/autofill_manager.h b/components/autofill/core/browser/autofill_manager.h
index 9d6c4b1..5f9a358e 100644
--- a/components/autofill/core/browser/autofill_manager.h
+++ b/components/autofill/core/browser/autofill_manager.h
@@ -40,6 +40,7 @@
 #include "components/autofill/core/browser/ui/popup_types.h"
 #include "components/autofill/core/common/form_data.h"
 #include "components/autofill/core/common/signatures.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace gfx {
 class RectF;
@@ -47,7 +48,6 @@
 
 namespace autofill {
 
-class AutofillDataModel;
 class AutofillField;
 class AutofillClient;
 class AutofillManagerTestDelegate;
@@ -365,11 +365,13 @@
 
   // Keeps track of the filling context for a form, used to make refill attemps.
   struct FillingContext {
-    // |optional_profile| or |optional_credit_card| must be non-null.
-    // If |optional_credit_card| is non-null, |optional_cvc| may be non-null.
+    // |profile_or_credit_card| contains either AutofillProfile or CreditCard
+    // and must be non-null.
+    // If |profile_or_credit_card| contains a CreditCard, |optional_cvc| may be
+    // non-null.
     FillingContext(const AutofillField& field,
-                   const AutofillProfile* optional_profile,
-                   const CreditCard* optional_credit_card,
+                   absl::variant<const AutofillProfile*, const CreditCard*>
+                       profile_or_credit_card,
                    const base::string16* optional_cvc);
     ~FillingContext();
 
@@ -378,8 +380,8 @@
     // The profile or credit card that was used for the initial fill.
     // The std::string associated with the credit card is the CVC, which may be
     // empty.
-    const base::Optional<AutofillProfile> profile;
-    const base::Optional<std::pair<CreditCard, base::string16>> credit_card;
+    absl::variant<AutofillProfile, std::pair<CreditCard, base::string16>>
+        profile_or_credit_card_with_cvc;
     // Possible identifiers of the field that was focused when the form was
     // initially filled. A refill shall be triggered from the same field.
     // TODO(crbug/896689): Remove |filled_field_unique_name|.
@@ -463,16 +465,17 @@
                                 const AutofillProfile& profile);
 
   // Fills or previews |data_model| in the |form|.
-  void FillOrPreviewDataModelForm(AutofillDriver::RendererFormDataAction action,
-                                  int query_id,
-                                  const FormData& form,
-                                  const FormFieldData& field,
-                                  const AutofillProfile* optional_profile,
-                                  const CreditCard* optional_credit_card,
-                                  const base::string16* optional_cvc,
-                                  FormStructure* form_structure,
-                                  AutofillField* autofill_field,
-                                  bool is_refill = false);
+  void FillOrPreviewDataModelForm(
+      AutofillDriver::RendererFormDataAction action,
+      int query_id,
+      const FormData& form,
+      const FormFieldData& field,
+      absl::variant<const AutofillProfile*, const CreditCard*>
+          profile_or_credit_card,
+      const base::string16* optional_cvc,
+      FormStructure* form_structure,
+      AutofillField* autofill_field,
+      bool is_refill = false);
 
   // Creates a FormStructure using the FormData received from the renderer. Will
   // return an empty scoped_ptr if the data should not be processed for upload
@@ -547,13 +550,15 @@
       size_t current_index,
       const ServerFieldTypeSet& upload_types);
 
-  void FillFieldWithValue(AutofillField* autofill_field,
-                          const AutofillDataModel& data_model,
-                          FormFieldData* field_data,
-                          bool should_notify,
-                          const base::string16& cvc,
-                          uint32_t profile_form_bitmask,
-                          std::string* failure_to_fill);
+  void FillFieldWithValue(
+      AutofillField* autofill_field,
+      absl::variant<const AutofillProfile*, const CreditCard*>
+          profile_or_credit_card,
+      FormFieldData* field_data,
+      bool should_notify,
+      const base::string16& cvc,
+      uint32_t profile_form_bitmask,
+      std::string* failure_to_fill);
 
   // TODO(crbug/896689): Remove code duplication once experiment is finished.
   void SetFillingContext(const FormStructure& form,
diff --git a/components/autofill/core/browser/data_model/autofill_structured_address_component.h b/components/autofill/core/browser/data_model/autofill_structured_address_component.h
index 2284008..b4a4f81 100644
--- a/components/autofill/core/browser/data_model/autofill_structured_address_component.h
+++ b/components/autofill/core/browser/data_model/autofill_structured_address_component.h
@@ -67,8 +67,7 @@
   kUseNewerIfDifferent = 1 << 5,
   // If the newer component contains one token more, apply a recursive strategy
   // to merge the tokens.
-  kRecursivelyMergeSingleTokenSubset =
-      1 << 6 | kRecursivelyMergeTokenEquivalentValues,
+  kRecursivelyMergeSingleTokenSubset = 1 << 6,
   // If one is a substring use the most recent one.
   kUseMostRecentSubstring = 1 << 7,
   // Merge the child nodes and reformat the node from its children after merge.
diff --git a/components/autofill/core/browser/field_filler.cc b/components/autofill/core/browser/field_filler.cc
index 849661ab..add65ac 100644
--- a/components/autofill/core/browser/field_filler.cc
+++ b/components/autofill/core/browser/field_filler.cc
@@ -19,8 +19,6 @@
 #include "components/autofill/core/browser/autofill_field.h"
 #include "components/autofill/core/browser/autofill_type.h"
 #include "components/autofill/core/browser/data_model/autofill_data_model.h"
-#include "components/autofill/core/browser/data_model/autofill_profile.h"
-#include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/browser/data_model/data_model_utils.h"
 #include "components/autofill/core/browser/data_model/phone_number.h"
 #include "components/autofill/core/browser/field_types.h"
@@ -540,9 +538,10 @@
 // found, falls back to alternate filling strategies based on the |type|.
 bool FillSelectControl(const AutofillType& type,
                        const base::string16& value,
-                       FormFieldData* field,
-                       const AutofillDataModel& data_model,
+                       absl::variant<const AutofillProfile*, const CreditCard*>
+                           profile_or_credit_card,
                        const std::string& app_locale,
+                       FormFieldData* field,
                        AddressNormalizer* address_normalizer,
                        std::string* failure_to_fill) {
   DCHECK_EQ("select-one", field->form_control_type);
@@ -571,9 +570,10 @@
 
   // If that fails, try specific fallbacks based on the field type.
   if (storable_type == ADDRESS_HOME_STATE) {
-    // Safe to cast the data model to AutofillProfile here.
+    DCHECK(absl::holds_alternative<const AutofillProfile*>(
+        profile_or_credit_card));
     const std::string country_code = data_util::GetCountryCodeWithFallback(
-        static_cast<const AutofillProfile&>(data_model), app_locale);
+        *absl::get<const AutofillProfile*>(profile_or_credit_card), app_locale);
     return FillStateSelectControl(value, field, country_code,
                                   address_normalizer, failure_to_fill);
   }
@@ -813,12 +813,20 @@
 
 FieldFiller::~FieldFiller() {}
 
-bool FieldFiller::FillFormField(const AutofillField& field,
-                                const AutofillDataModel& data_model,
-                                FormFieldData* field_data,
-                                const base::string16& cvc,
-                                std::string* failure_to_fill) {
+bool FieldFiller::FillFormField(
+    const AutofillField& field,
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card,
+    FormFieldData* field_data,
+    const base::string16& cvc,
+    std::string* failure_to_fill) {
   const AutofillType type = field.Type();
+  const AutofillDataModel& data_model = [&]() -> const AutofillDataModel& {
+    if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card))
+      return *absl::get<const AutofillProfile*>(profile_or_credit_card);
+    else
+      return *absl::get<const CreditCard*>(profile_or_credit_card);
+  }();
 
   if (data_model.ShouldSkipFillingOrSuggesting(type.GetStorableType())) {
     if (failure_to_fill)
@@ -851,19 +859,21 @@
     return true;
   }
   if (field_data->form_control_type == "select-one") {
-    return FillSelectControl(type, value, field_data, data_model, app_locale_,
-                             address_normalizer_, failure_to_fill);
+    return FillSelectControl(type, value, profile_or_credit_card, app_locale_,
+                             field_data, address_normalizer_, failure_to_fill);
   }
   if (field_data->form_control_type == "month") {
-    // Safe to cast to CreditCard here because month control type only applying
-    // to credit card expirations.
-    FillMonthControl(static_cast<const CreditCard&>(data_model), field_data);
+    DCHECK(absl::holds_alternative<const CreditCard*>(profile_or_credit_card));
+    FillMonthControl(*absl::get<const CreditCard*>(profile_or_credit_card),
+                     field_data);
     return true;
   }
   if (type.GetStorableType() == ADDRESS_HOME_STREET_ADDRESS) {
-    // Safe to cast to AutofillProfile here because of the address |type|.
-    const std::string profile_language_code =
-        static_cast<const AutofillProfile&>(data_model).language_code();
+    DCHECK(absl::holds_alternative<const AutofillProfile*>(
+        profile_or_credit_card));
+    const std::string& profile_language_code =
+        absl::get<const AutofillProfile*>(profile_or_credit_card)
+            ->language_code();
     FillStreetAddress(value, profile_language_code, field_data);
     return true;
   }
@@ -872,9 +882,11 @@
     return true;
   }
   if (type.GetStorableType() == ADDRESS_HOME_STATE) {
-    // TODO(crbug.com/1147883): Static casts are unsafe
-    const std::string country_code = data_util::GetCountryCodeWithFallback(
-        static_cast<const AutofillProfile&>(data_model), app_locale_);
+    DCHECK(absl::holds_alternative<const AutofillProfile*>(
+        profile_or_credit_card));
+    const std::string& country_code = data_util::GetCountryCodeWithFallback(
+        *absl::get<const AutofillProfile*>(profile_or_credit_card),
+        app_locale_);
     return FillStateText(value, country_code, field_data, failure_to_fill);
   }
   if (field_data->form_control_type == "text" &&
diff --git a/components/autofill/core/browser/field_filler.h b/components/autofill/core/browser/field_filler.h
index 85ddb2b..d549587 100644
--- a/components/autofill/core/browser/field_filler.h
+++ b/components/autofill/core/browser/field_filler.h
@@ -9,12 +9,14 @@
 
 #include "base/macros.h"
 #include "base/strings/string16.h"
+#include "components/autofill/core/browser/data_model/autofill_profile.h"
+#include "components/autofill/core/browser/data_model/credit_card.h"
 #include "components/autofill/core/common/form_field_data.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace autofill {
 
 class AddressNormalizer;
-class AutofillDataModel;
 class AutofillField;
 
 // Helper class to put user content in fields, to eventually send to the
@@ -25,14 +27,14 @@
               AddressNormalizer* address_normalizer);
   ~FieldFiller();
 
-  // Set |field_data|'s value to the right value in |data_model|. Uses |field|
-  // to determine which field type should be filled, and |app_locale_| as hint
-  // when filling exceptional cases like phone number values. Returns |true| if
-  // the field has been filled, false otherwise. |cvc| is not stored in the
-  // data model and may be needed at fill time. If |failure_to_fill| is not
-  // null, errors are reported to that string.
+  // Set |field_data|'s value to the right value in |profile_or_credit_card|.
+  // Uses |field| to determine which field type should be filled, and
+  // |app_locale_| as hint when filling exceptional cases like phone number
+  // values. Returns |true| if the field has been filled, false otherwise. If
+  // |failure_to_fill| is not null, errors are reported to that string.
   bool FillFormField(const AutofillField& field,
-                     const AutofillDataModel& data_model,
+                     absl::variant<const AutofillProfile*, const CreditCard*>
+                         profile_or_credit_card,
                      FormFieldData* field_data,
                      const base::string16& cvc,
                      std::string* failure_to_fill = nullptr);
diff --git a/components/autofill/core/browser/field_filler_unittest.cc b/components/autofill/core/browser/field_filler_unittest.cc
index 3f3c16c..3959b74 100644
--- a/components/autofill/core/browser/field_filler_unittest.cc
+++ b/components/autofill/core/browser/field_filler_unittest.cc
@@ -101,13 +101,13 @@
   // Try a single-digit month.
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(3);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   GetIndexOfValue(field.option_values, field.value, &content_index);
   EXPECT_EQ(ASCIIToUTF16("Mar"), field.option_contents[content_index]);
 
   // Try a two-digit month.
   card.SetExpirationMonth(11);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   GetIndexOfValue(field.option_values, field.value, &content_index);
   EXPECT_EQ(ASCIIToUTF16("Nov"), field.option_contents[content_index]);
 }
@@ -126,11 +126,11 @@
   field_city.set_heuristic_type(ADDRESS_HOME_CITY);
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field_state, profile, &field_state,
+  filler.FillFormField(field_state, &profile, &field_state,
                        /*cvc=*/base::string16());
   EXPECT_EQ(state, field_state.value);
 
-  filler.FillFormField(field_city, profile, &field_city,
+  filler.FillFormField(field_city, &profile, &field_city,
                        /*cvc=*/base::string16());
   EXPECT_EQ(city, field_city.value);
 }
@@ -366,7 +366,7 @@
   // Non credit card related field.
   address()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Test"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled in all circumstances.
   EXPECT_EQ(ASCIIToUTF16("Test"), field.value);
@@ -382,7 +382,7 @@
   // Credit card related field.
   credit_card()->SetNumber(ASCIIToUTF16("4111111111111111"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *credit_card(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, credit_card(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled.
   EXPECT_EQ(ASCIIToUTF16("4111111111111111"), field.value);
@@ -400,7 +400,7 @@
   // Credit card related field.
   credit_card()->SetNumber(ASCIIToUTF16("0123456789999999"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *credit_card(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, credit_card(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled with the fourth digit of the credit card
   // number.
@@ -419,7 +419,7 @@
   // Credit card related field.
   credit_card()->SetNumber(ASCIIToUTF16("0123456789999999"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *credit_card(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, credit_card(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled with the full credit card number.
   EXPECT_EQ(ASCIIToUTF16("0123456789999999"), field.value);
@@ -437,7 +437,7 @@
   // Credit card related field.
   credit_card()->SetNumber(ASCIIToUTF16("0123456789999999"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *credit_card(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, credit_card(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled with the third digit of the credit card
   // number.
@@ -453,7 +453,7 @@
   // Credit card related field.
   credit_card()->SetNumber(ASCIIToUTF16("4111111111111111"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *credit_card(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, credit_card(), &field, /*cvc=*/base::string16());
 
   // Verify that the field is filled with only the first digit of the credit
   // card number.
@@ -525,13 +525,13 @@
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
   // State is filled, because it's an address field.
-  filler.FillFormField(field_state, profile, &field_state,
+  filler.FillFormField(field_state, &profile, &field_state,
                        /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("CA"), field_state.value);
 
   // Email is not filled, because it's not an address field, and it doesn't
   // depend on the country.
-  filler.FillFormField(field_email, profile, &field_email,
+  filler.FillFormField(field_email, &profile, &field_email,
                        /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16(""), field_email.value);
 }
@@ -557,7 +557,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+15145554578"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
 }
 
@@ -607,7 +607,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationDateFromString(ASCIIToUTF16("12/2023"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
 }
 
@@ -670,7 +670,7 @@
   card.SetExpirationDateFromString(ASCIIToUTF16("03/2022"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
   bool response =
-      filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+      filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
   EXPECT_EQ(response, test_case.expected_response);
 }
@@ -760,7 +760,7 @@
 
   address()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Meenie"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Meenie"), field.value);
 }
 
@@ -782,7 +782,7 @@
 
   address()->SetRawInfo(NAME_FIRST, ASCIIToUTF16("Miney"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("2"), field.value);  // Corresponds to "Miney".
 }
 
@@ -836,7 +836,7 @@
   AutofillProfile address = test::GetFullProfile();
   address.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16(test_case.input_value));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   // nullptr means we expect them not to match without normalization.
   if (test_case.expected_value_without_normalization != nullptr) {
     EXPECT_EQ(UTF8ToUTF16(test_case.expected_value_without_normalization),
@@ -849,7 +849,7 @@
                               UTF8ToUTF16(test_case.input_value));
   // Fill a first time without loading the rules for the region.
   FieldFiller canadian_filler(/*app_locale=*/"en-US", normalizer());
-  canadian_filler.FillFormField(field, canadian_address, &field,
+  canadian_filler.FillFormField(field, &canadian_address, &field,
                                 /*cvc=*/base::string16());
   // If the expectation with normalization is nullptr, this means that the same
   // result than without a normalizer is expected.
@@ -864,7 +864,7 @@
 
     // Load the rules and try again.
     normalizer()->LoadRulesForRegion("CA");
-    canadian_filler.FillFormField(field, canadian_address, &field,
+    canadian_filler.FillFormField(field, &canadian_address, &field,
                                   /*cvc=*/base::string16());
     EXPECT_EQ(UTF8ToUTF16(test_case.expected_value_with_normalization),
               field.value);
@@ -933,7 +933,7 @@
   AutofillProfile address = test::GetFullProfile();
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, UTF8ToUTF16("CA"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("Canada"), field.value);
 }
 
@@ -1059,7 +1059,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(4);
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Apr"), field.value);
 }
 
@@ -1075,7 +1075,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(4);
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("April"), field.value);
 }
 
@@ -1092,7 +1092,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(4);
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("April (04)"), field.value);
 }
 
@@ -1119,10 +1119,10 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(8);
   FieldFiller filler(/*app_locale=*/"fr-FR", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("08 - AOÛT"), field.value);
   card.SetExpirationMonth(12);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("12 - DECEMBRE"), field.value);
 }
 
@@ -1136,15 +1136,15 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(2);
   FieldFiller filler(/*app_locale=*/"fr-FR", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("FÉVR."), field.value);
 
   card.SetExpirationMonth(1);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("JANV"), field.value);
 
   card.SetExpirationMonth(12);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("décembre"), field.value);
 }
 
@@ -1160,7 +1160,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationMonth(4);
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("4"), field.value);
 }
 
@@ -1174,7 +1174,7 @@
   CreditCard card = test::GetCreditCard();
   card.SetExpirationYear(2017);
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("17"), field.value);
 }
 
@@ -1189,22 +1189,22 @@
 
   // Normal case:
   card.SetNumber(ASCIIToUTF16("4111111111111111"));  // Visa number.
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Visa"), field.value);
 
   // Filling should be able to handle intervening whitespace:
   card.SetNumber(ASCIIToUTF16("5555555555554444"));  // MC number.
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Mastercard"), field.value);
 
   // American Express is sometimes abbreviated as AmEx:
   card.SetNumber(ASCIIToUTF16("378282246310005"));  // Amex number.
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("AmEx"), field.value);
 
   // Case insensitivity:
   card.SetNumber(ASCIIToUTF16("6011111111111117"));  // Discover number.
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("discover"), field.value);
 }
 
@@ -1217,12 +1217,12 @@
   // Try a month with two digits.
   CreditCard card = test::GetCreditCard();
   card.SetExpirationDateFromString(ASCIIToUTF16("12/2017"));
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("2017-12"), field.value);
 
   // Try a month with a leading zero.
   card.SetExpirationDateFromString(ASCIIToUTF16("03/2019"));
-  filler.FillFormField(field, card, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &card, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("2019-03"), field.value);
 }
 
@@ -1236,7 +1236,7 @@
       "123 Fake St.\n"
       "Apt. 42");
   address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), value, "en-US");
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(value, field.value);
 
   base::string16 ja_value = UTF8ToUTF16(
@@ -1245,7 +1245,7 @@
   address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), ja_value,
                      "ja-JP");
   address()->set_language_code("ja-JP");
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(ja_value, field.value);
 }
 
@@ -1259,7 +1259,7 @@
       "123 Fake St.\n"
       "Apt. 42");
   address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), value, "en-US");
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("123 Fake St., Apt. 42"), field.value);
 
   base::string16 ja_value = UTF8ToUTF16(
@@ -1268,7 +1268,7 @@
   address()->SetInfo(AutofillType(ADDRESS_HOME_STREET_ADDRESS), ja_value,
                      "ja-JP");
   address()->set_language_code("ja-JP");
-  filler.FillFormField(field, *address(), &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, address(), &field, /*cvc=*/base::string16());
   EXPECT_EQ(UTF8ToUTF16("桜丘町26-1セルリアンタワー6階"), field.value);
 }
 
@@ -1279,7 +1279,7 @@
 
   credit_card()->SetNumber(ASCIIToUTF16("41111111111111111"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(cc_number_full, *credit_card(), &cc_number_full,
+  filler.FillFormField(cc_number_full, credit_card(), &cc_number_full,
                        /*cvc=*/base::string16());
 
   // Verify that full card-number shall get filled properly.
@@ -1307,7 +1307,7 @@
 
     // Fill with a card-number; should fill just the card_number_part.
     credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
-    filler.FillFormField(cc_number_part, *credit_card(), &cc_number_part,
+    filler.FillFormField(cc_number_part, credit_card(), &cc_number_part,
                          /*cvc=*/base::string16());
 
     // Verify for expected results.
@@ -1321,7 +1321,7 @@
   cc_number_full.set_heuristic_type(CREDIT_CARD_NUMBER);
 
   credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
-  filler.FillFormField(cc_number_full, *credit_card(), &cc_number_full,
+  filler.FillFormField(cc_number_full, credit_card(), &cc_number_full,
                        /*cvc=*/base::string16());
 
   // Verify for expected results.
@@ -1350,7 +1350,7 @@
 
     // Fill with a card-number; should fill just the card_number_part.
     credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
-    filler.FillFormField(cc_number_part, *credit_card(), &cc_number_part,
+    filler.FillFormField(cc_number_part, credit_card(), &cc_number_part,
                          /*cvc=*/base::string16());
 
     // Verify for expected results.
@@ -1364,7 +1364,7 @@
   AutofillField cc_number_full;
   cc_number_full.set_heuristic_type(CREDIT_CARD_NUMBER);
   credit_card()->SetNumber(ASCIIToUTF16(test.card_number_));
-  filler.FillFormField(cc_number_full, *credit_card(), &cc_number_full,
+  filler.FillFormField(cc_number_full, credit_card(), &cc_number_full,
                        /*cvc=*/base::string16());
 
   // Verify for expected results.
@@ -1439,7 +1439,7 @@
   AutofillProfile address = test::GetFullProfile();
   address.SetRawInfo(ADDRESS_HOME_STATE, UTF8ToUTF16(test_case.value_to_fill));
   bool has_filled =
-      filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+      filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
 
   EXPECT_EQ(test_case.should_fill, has_filled);
   EXPECT_EQ(ASCIIToUTF16(test_case.expected_value), field.value);
@@ -1493,7 +1493,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+15145554578"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("1"), field.value);
 }
 
@@ -1514,7 +1514,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+918890888888"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("+91"), field.value);
 }
 
@@ -1535,7 +1535,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+918890888888"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("0091"), field.value);
 }
 
@@ -1556,7 +1556,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("+49 (Germany)"), field.value);
 }
 
@@ -1578,7 +1578,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("(00 49) Germany"), field.value);
 }
 
@@ -1601,7 +1601,7 @@
   AutofillProfile address;
   address.SetRawInfo(PHONE_HOME_WHOLE_NUMBER, ASCIIToUTF16("+49151669087345"));
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("(0049) Germany"), field.value);
 }
 
@@ -1623,7 +1623,7 @@
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("BY"), field.value);
 }
 
@@ -1646,7 +1646,7 @@
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Bayern"), field.value);
 }
 
@@ -1669,7 +1669,7 @@
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Bavaria Has Munich"), field.value);
 }
 
@@ -1692,7 +1692,7 @@
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("BY"), field.value);
 }
 
@@ -1715,7 +1715,7 @@
   address.SetRawInfo(ADDRESS_HOME_COUNTRY, ASCIIToUTF16("DE"));
 
   FieldFiller filler(/*app_locale=*/"en-US", /*address_normalizer=*/nullptr);
-  filler.FillFormField(field, address, &field, /*cvc=*/base::string16());
+  filler.FillFormField(field, &address, &field, /*cvc=*/base::string16());
   EXPECT_EQ(ASCIIToUTF16("Bavari"), field.value);
 }
 
diff --git a/components/autofill/core/browser/personal_data_manager.cc b/components/autofill/core/browser/personal_data_manager.cc
index c95b0484..301ed1a4 100644
--- a/components/autofill/core/browser/personal_data_manager.cc
+++ b/components/autofill/core/browser/personal_data_manager.cc
@@ -601,46 +601,58 @@
     observer.OnInsufficientFormData();
 }
 
-void PersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
+void PersonalDataManager::RecordUseOf(
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card) {
   if (is_off_the_record_)
     return;
 
-  CreditCard* credit_card = GetCreditCardByGUID(data_model.guid());
-  if (credit_card) {
-    credit_card->RecordAndLogUse();
+  if (absl::holds_alternative<const CreditCard*>(profile_or_credit_card)) {
+    CreditCard* credit_card = GetCreditCardByGUID(
+        absl::get<const CreditCard*>(profile_or_credit_card)->guid());
 
-    if (credit_card->record_type() == CreditCard::LOCAL_CARD) {
-      // Fail silently if there's no local database, because we need to support
-      // this for tests.
-      if (database_helper_->GetLocalDatabase()) {
-        database_helper_->GetLocalDatabase()->UpdateCreditCard(*credit_card);
+    if (credit_card) {
+      credit_card->RecordAndLogUse();
+
+      if (credit_card->record_type() == CreditCard::LOCAL_CARD) {
+        // Fail silently if there's no local database, because we need to
+        // support this for tests.
+        if (database_helper_->GetLocalDatabase()) {
+          database_helper_->GetLocalDatabase()->UpdateCreditCard(*credit_card);
+        }
+      } else {
+        DCHECK(database_helper_->GetServerDatabase())
+            << "Recording use of server card without server storage.";
+        database_helper_->GetServerDatabase()->UpdateServerCardMetadata(
+            *credit_card);
       }
-    } else {
-      DCHECK(database_helper_->GetServerDatabase())
-          << "Recording use of server card without server storage.";
-      database_helper_->GetServerDatabase()->UpdateServerCardMetadata(
-          *credit_card);
-    }
 
-    Refresh();
-    return;
+      Refresh();
+      return;
+    }
   }
 
-  AutofillProfile* profile = GetProfileByGUID(data_model.guid());
-  if (profile) {
-    profile->RecordAndLogUse();
+  if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card)) {
+    // TODO(crbug.com/941498): Server profiles are not recorded therefore
+    // GetProfileByGUID returns null for them.
+    AutofillProfile* profile = GetProfileByGUID(
+        absl::get<const AutofillProfile*>(profile_or_credit_card)->guid());
 
-    switch (profile->record_type()) {
-      case AutofillProfile::LOCAL_PROFILE:
-        UpdateProfileInDB(*profile, /*enforced=*/true);
-        break;
-      case AutofillProfile::SERVER_PROFILE:
-        DCHECK(database_helper_->GetServerDatabase())
-            << "Recording use of server address without server storage.";
-        database_helper_->GetServerDatabase()->UpdateServerAddressMetadata(
-            *profile);
-        Refresh();
-        break;
+    if (profile) {
+      profile->RecordAndLogUse();
+
+      switch (profile->record_type()) {
+        case AutofillProfile::LOCAL_PROFILE:
+          UpdateProfileInDB(*profile, /*enforced=*/true);
+          break;
+        case AutofillProfile::SERVER_PROFILE:
+          DCHECK(database_helper_->GetServerDatabase())
+              << "Recording use of server address without server storage.";
+          database_helper_->GetServerDatabase()->UpdateServerAddressMetadata(
+              *profile);
+          Refresh();
+          break;
+      }
     }
   }
 }
diff --git a/components/autofill/core/browser/personal_data_manager.h b/components/autofill/core/browser/personal_data_manager.h
index 7f14296..e98c992 100644
--- a/components/autofill/core/browser/personal_data_manager.h
+++ b/components/autofill/core/browser/personal_data_manager.h
@@ -145,9 +145,11 @@
   // imported from a form.
   void MarkObserversInsufficientFormDataForImport();
 
-  // Called to indicate |data_model| was used (to fill in a form). Updates
-  // the database accordingly. Can invalidate |data_model|.
-  virtual void RecordUseOf(const AutofillDataModel& data_model);
+  // Called to indicate |profile_or_credit_card| was used (to fill in a form).
+  // Updates the database accordingly.
+  virtual void RecordUseOf(
+      absl::variant<const AutofillProfile*, const CreditCard*>
+          profile_or_credit_card);
 
   // Saves |imported_profile| to the WebDB if it exists. Returns the guid of
   // the new or updated profile, or the empty string if no profile was saved.
diff --git a/components/autofill/core/browser/personal_data_manager_unittest.cc b/components/autofill/core/browser/personal_data_manager_unittest.cc
index d19607c9..670736b 100644
--- a/components/autofill/core/browser/personal_data_manager_unittest.cc
+++ b/components/autofill/core/browser/personal_data_manager_unittest.cc
@@ -3970,7 +3970,7 @@
   EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
       .WillOnce(QuitMessageLoop(&profile_run_loop));
   EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
-  personal_data_->RecordUseOf(profile);
+  personal_data_->RecordUseOf(&profile);
   profile_run_loop.Run();
 
   added_profile = personal_data_->GetProfileByGUID(profile.guid());
@@ -3985,7 +3985,7 @@
   EXPECT_CALL(personal_data_observer_, OnPersonalDataFinishedProfileTasks())
       .WillOnce(QuitMessageLoop(&credit_card_run_loop));
   EXPECT_CALL(personal_data_observer_, OnPersonalDataChanged()).Times(1);
-  personal_data_->RecordUseOf(credit_card);
+  personal_data_->RecordUseOf(&credit_card);
   credit_card_run_loop.Run();
 
   added_profile = personal_data_->GetProfileByGUID(profile.guid());
diff --git a/components/autofill/core/browser/test_personal_data_manager.cc b/components/autofill/core/browser/test_personal_data_manager.cc
index 3380a826..d0ed404 100644
--- a/components/autofill/core/browser/test_personal_data_manager.cc
+++ b/components/autofill/core/browser/test_personal_data_manager.cc
@@ -23,14 +23,24 @@
   return sync_and_signin_state_;
 }
 
-void TestPersonalDataManager::RecordUseOf(const AutofillDataModel& data_model) {
-  CreditCard* credit_card = GetCreditCardWithGUID(data_model.guid().c_str());
-  if (credit_card)
-    credit_card->RecordAndLogUse();
+void TestPersonalDataManager::RecordUseOf(
+    absl::variant<const AutofillProfile*, const CreditCard*>
+        profile_or_credit_card) {
+  if (absl::holds_alternative<const CreditCard*>(profile_or_credit_card)) {
+    CreditCard* credit_card = GetCreditCardByGUID(
+        absl::get<const CreditCard*>(profile_or_credit_card)->guid());
 
-  AutofillProfile* profile = GetProfileWithGUID(data_model.guid().c_str());
-  if (profile)
-    profile->RecordAndLogUse();
+    if (credit_card)
+      credit_card->RecordAndLogUse();
+  }
+
+  if (absl::holds_alternative<const AutofillProfile*>(profile_or_credit_card)) {
+    AutofillProfile* profile = GetProfileByGUID(
+        absl::get<const AutofillProfile*>(profile_or_credit_card)->guid());
+
+    if (profile)
+      profile->RecordAndLogUse();
+  }
 }
 
 std::string TestPersonalDataManager::SaveImportedProfile(
diff --git a/components/autofill/core/browser/test_personal_data_manager.h b/components/autofill/core/browser/test_personal_data_manager.h
index 0f5d004..eaf5473 100644
--- a/components/autofill/core/browser/test_personal_data_manager.h
+++ b/components/autofill/core/browser/test_personal_data_manager.h
@@ -32,7 +32,8 @@
   // or to make things easier in general to toggle.
   void OnSyncServiceInitialized(syncer::SyncService* sync_service) override;
   AutofillSyncSigninState GetSyncSigninState() const override;
-  void RecordUseOf(const AutofillDataModel& data_model) override;
+  void RecordUseOf(absl::variant<const AutofillProfile*, const CreditCard*>
+                       profile_or_credit_card) override;
   std::string SaveImportedProfile(
       const AutofillProfile& imported_profile) override;
   std::string SaveImportedCreditCard(
diff --git a/components/autofill_assistant/browser/actions/action_delegate.h b/components/autofill_assistant/browser/actions/action_delegate.h
index a7bc8ddbf..acb25cc1 100644
--- a/components/autofill_assistant/browser/actions/action_delegate.h
+++ b/components/autofill_assistant/browser/actions/action_delegate.h
@@ -445,6 +445,14 @@
   virtual void SetOverlayBehavior(
       ConfigureUiStateProto::OverlayBehavior overlay_behavior) = 0;
 
+  // Maybe shows a warning letting the user know that the website is unusually
+  // slow, depending on the current settings.
+  virtual void MaybeShowSlowWebsiteWarning() = 0;
+
+  // Maybe shows a warning letting the user know that a slow connection was
+  // detected, depending on the current settings.
+  virtual void MaybeShowSlowConnectionWarning() = 0;
+
   virtual base::WeakPtr<ActionDelegate> GetWeakPtr() const = 0;
 
  protected:
diff --git a/components/autofill_assistant/browser/actions/mock_action_delegate.h b/components/autofill_assistant/browser/actions/mock_action_delegate.h
index c35b389..05990f9 100644
--- a/components/autofill_assistant/browser/actions/mock_action_delegate.h
+++ b/components/autofill_assistant/browser/actions/mock_action_delegate.h
@@ -323,6 +323,9 @@
   MOCK_METHOD1(SetOverlayBehavior,
                void(ConfigureUiStateProto::OverlayBehavior));
 
+  MOCK_METHOD0(MaybeShowSlowWebsiteWarning, void());
+  MOCK_METHOD0(MaybeShowSlowConnectionWarning, void());
+
   base::WeakPtr<ActionDelegate> GetWeakPtr() const override {
     return weak_ptr_factory_.GetWeakPtr();
   }
diff --git a/components/autofill_assistant/browser/client_settings.cc b/components/autofill_assistant/browser/client_settings.cc
index 620586a..812e8b2 100644
--- a/components/autofill_assistant/browser/client_settings.cc
+++ b/components/autofill_assistant/browser/client_settings.cc
@@ -105,7 +105,39 @@
       back_button_settings.reset();
     }
   }
-
+  if (proto.has_slow_warning_settings()) {
+    if (proto.slow_warning_settings().has_enable_slow_connection_warnings()) {
+      enable_slow_connection_warnings =
+          proto.slow_warning_settings().enable_slow_connection_warnings();
+    }
+    if (proto.slow_warning_settings().has_enable_slow_website_warnings()) {
+      enable_slow_website_warnings =
+          proto.slow_warning_settings().enable_slow_website_warnings();
+    }
+    if (proto.slow_warning_settings().has_show_only_once()) {
+      only_show_warning_once = proto.slow_warning_settings().show_only_once();
+    }
+    if (proto.slow_warning_settings().has_warning_delay_ms()) {
+      timeout_warning_delay = base::TimeDelta::FromMilliseconds(
+          proto.slow_warning_settings().warning_delay_ms());
+    }
+    if (proto.slow_warning_settings().has_slow_roundtrip_threshold_ms()) {
+      slow_roundtrip_threshold = base::TimeDelta::FromMilliseconds(
+          proto.slow_warning_settings().slow_roundtrip_threshold_ms());
+    }
+    if (proto.slow_warning_settings().has_max_consecutive_slow_roundtrips()) {
+      max_consecutive_slow_roundtrips =
+          proto.slow_warning_settings().max_consecutive_slow_roundtrips();
+    }
+    if (proto.slow_warning_settings().has_slow_connection_message()) {
+      slow_connection_message =
+          proto.slow_warning_settings().slow_connection_message();
+    }
+    if (proto.slow_warning_settings().has_slow_website_message()) {
+      slow_website_message =
+          proto.slow_warning_settings().slow_website_message();
+    }
+  }
   // Test only settings.
   if (proto.has_integration_test_settings()) {
     integration_test_settings = proto.integration_test_settings();
diff --git a/components/autofill_assistant/browser/client_settings.h b/components/autofill_assistant/browser/client_settings.h
index 25d50c9..f754ea0 100644
--- a/components/autofill_assistant/browser/client_settings.h
+++ b/components/autofill_assistant/browser/client_settings.h
@@ -9,6 +9,7 @@
 #include "base/optional.h"
 #include "base/time/time.h"
 #include "components/autofill_assistant/browser/service.pb.h"
+#include "components/strings/grit/components_strings.h"
 
 namespace autofill_assistant {
 
@@ -89,6 +90,17 @@
   // Snackbar.
   base::Optional<ClientSettingsProto::BackButtonSettings> back_button_settings;
 
+  bool enable_slow_connection_warnings = false;
+  bool enable_slow_website_warnings = false;
+  bool only_show_warning_once = false;
+  base::TimeDelta timeout_warning_delay =
+      base::TimeDelta::FromMilliseconds(1000);
+  int max_consecutive_slow_roundtrips = 3;
+  base::TimeDelta slow_roundtrip_threshold =
+      base::TimeDelta::FromMilliseconds(500);
+  std::string slow_connection_message = "";
+  std::string slow_website_message = "";
+
  private:
   DISALLOW_COPY_AND_ASSIGN(ClientSettings);
 };
diff --git a/components/autofill_assistant/browser/controller.cc b/components/autofill_assistant/browser/controller.cc
index d54e5c6..492ea9f 100644
--- a/components/autofill_assistant/browser/controller.cc
+++ b/components/autofill_assistant/browser/controller.cc
@@ -508,6 +508,11 @@
   browse_mode_invisible_ = invisible;
 }
 
+bool Controller::ShouldShowWarning() {
+  return state_ == AutofillAssistantState::RUNNING ||
+         state_ == AutofillAssistantState::PROMPT;
+}
+
 void Controller::AddNavigationListener(
     ScriptExecutorDelegate::NavigationListener* listener) {
   navigation_listeners_.AddObserver(listener);
diff --git a/components/autofill_assistant/browser/controller.h b/components/autofill_assistant/browser/controller.h
index 219c2ec..a01e3c8 100644
--- a/components/autofill_assistant/browser/controller.h
+++ b/components/autofill_assistant/browser/controller.h
@@ -154,6 +154,7 @@
           view_inflation_finished_callback) override;
   void ClearGenericUi() override;
   void SetBrowseModeInvisible(bool invisible) override;
+  bool ShouldShowWarning() override;
 
   // Show the UI if it's not already shown. This is only meaningful while in
   // states where showing the UI is optional, such as RUNNING, in tracking mode.
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.cc b/components/autofill_assistant/browser/fake_script_executor_delegate.cc
index 5ae3812..1416ff3 100644
--- a/components/autofill_assistant/browser/fake_script_executor_delegate.cc
+++ b/components/autofill_assistant/browser/fake_script_executor_delegate.cc
@@ -86,11 +86,11 @@
 }
 
 void FakeScriptExecutorDelegate::SetBubbleMessage(const std::string& message) {
-  status_message_ = message;
+  bubble_message_ = message;
 }
 
 std::string FakeScriptExecutorDelegate::GetBubbleMessage() const {
-  return status_message_;
+  return bubble_message_;
 }
 
 void FakeScriptExecutorDelegate::SetDetails(std::unique_ptr<Details> details,
@@ -264,4 +264,8 @@
 
 void FakeScriptExecutorDelegate::SetBrowseModeInvisible(bool invisible) {}
 
+bool FakeScriptExecutorDelegate::ShouldShowWarning() {
+  return true;
+}
+
 }  // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/fake_script_executor_delegate.h b/components/autofill_assistant/browser/fake_script_executor_delegate.h
index a5a4409..70b17df 100644
--- a/components/autofill_assistant/browser/fake_script_executor_delegate.h
+++ b/components/autofill_assistant/browser/fake_script_executor_delegate.h
@@ -101,6 +101,8 @@
       ConfigureUiStateProto::OverlayBehavior overlay_behavior) override;
   void SetBrowseModeInvisible(bool invisible) override;
 
+  bool ShouldShowWarning() override;
+
   ClientSettings* GetMutableSettings() { return &client_settings_; }
 
   void SetCurrentURL(const GURL& url) { current_url_ = url; }
@@ -120,10 +122,10 @@
   }
 
   void SetUserModel(UserModel* user_model) { user_model_ = user_model; }
-
   std::vector<AutofillAssistantState> GetStateHistory() {
     return state_history_;
   }
+
   AutofillAssistantState GetState() const {
     return state_history_.empty() ? AutofillAssistantState::INACTIVE
                                   : state_history_.back();
@@ -161,6 +163,7 @@
   std::unique_ptr<TriggerContext> trigger_context_;
   std::vector<AutofillAssistantState> state_history_;
   std::string status_message_;
+  std::string bubble_message_;
   std::vector<Details> details_;
   std::unique_ptr<InfoBox> info_box_;
   std::unique_ptr<std::vector<UserAction>> user_actions_;
diff --git a/components/autofill_assistant/browser/script_executor.cc b/components/autofill_assistant/browser/script_executor.cc
index daf2f2a..4689c867 100644
--- a/components/autofill_assistant/browser/script_executor.cc
+++ b/components/autofill_assistant/browser/script_executor.cc
@@ -296,6 +296,9 @@
                           weak_ptr_factory_.GetWeakPtr(), selector),
       base::BindOnce(&ScriptExecutor::OnShortWaitForElement,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  current_action_data_.wait_for_dom->SetTimeoutWarningCallback(
+      base::BindOnce(&ScriptExecutor::MaybeShowSlowWebsiteWarning,
+                     weak_ptr_factory_.GetWeakPtr()));
   current_action_data_.wait_for_dom->Run();
 }
 
@@ -310,6 +313,9 @@
       this, delegate_, max_wait_time, allow_interrupt, check_elements,
       base::BindOnce(&ScriptExecutor::OnWaitForElementVisibleWithInterrupts,
                      weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
+  current_action_data_.wait_for_dom->SetTimeoutWarningCallback(base::BindOnce(
+      &ScriptExecutor::SetBubbleMessage, weak_ptr_factory_.GetWeakPtr(),
+      delegate_->GetSettings().slow_website_message));
   current_action_data_.wait_for_dom->Run();
 }
 
@@ -829,6 +835,32 @@
   delegate_->SetOverlayBehavior(overlay_behavior);
 }
 
+void ScriptExecutor::MaybeShowSlowWebsiteWarning() {
+  MaybeShowSlowWarning(delegate_->GetSettings().slow_website_message,
+                       delegate_->GetSettings().enable_slow_website_warnings);
+}
+
+void ScriptExecutor::MaybeShowSlowConnectionWarning() {
+  MaybeShowSlowWarning(
+      delegate_->GetSettings().slow_connection_message,
+      delegate_->GetSettings().enable_slow_connection_warnings);
+}
+
+void ScriptExecutor::MaybeShowSlowWarning(const std::string& message,
+                                          bool enabled) {
+  if (message.empty() || !enabled || !delegate_->ShouldShowWarning()) {
+    return;
+  }
+
+  if (delegate_->GetSettings().only_show_warning_once &&
+      warning_callout_already_shown_) {
+    return;
+  }
+
+  warning_callout_already_shown_ = true;
+  SetBubbleMessage(message);
+}
+
 base::WeakPtr<ActionDelegate> ScriptExecutor::GetWeakPtr() const {
   return weak_ptr_factory_.GetWeakPtr();
 }
@@ -838,8 +870,10 @@
                                   const std::string& response) {
   VLOG(2) << __func__ << " http-status=" << http_status;
   batch_start_time_ = base::TimeTicks::Now();
+  const base::TimeDelta& roundtrip_duration = batch_start_time_ - start_time;
+  // Doesn't trigger when the script is completed.
   roundtrip_timing_stats_.set_roundtrip_time_ms(
-      (batch_start_time_ - start_time).InMilliseconds());
+      roundtrip_duration.InMilliseconds());
   bool success =
       http_status == net::HTTP_OK && ProcessNextActionResponse(response);
   if (should_stop_script_) {
@@ -857,6 +891,16 @@
   }
 
   if (!actions_.empty()) {
+    if (roundtrip_duration >
+        delegate_->GetSettings().slow_roundtrip_threshold) {
+      consecutive_slow_roundtrip_counter_++;
+      if (consecutive_slow_roundtrip_counter_ >=
+          delegate_->GetSettings().max_consecutive_slow_roundtrips) {
+        MaybeShowSlowConnectionWarning();
+      }
+    } else {
+      consecutive_slow_roundtrip_counter_ = 0;
+    }
     ProcessNextAction();
     return;
   }
@@ -1077,6 +1121,8 @@
       allow_interrupt_(allow_interrupt),
       check_elements_(std::move(check_elements)),
       callback_(std::move(callback)),
+      timeout_warning_period_(
+          main_script->delegate_->GetSettings().timeout_warning_delay),
       retry_timer_(main_script->delegate_->GetSettings()
                        .periodic_element_check_interval) {}
 
@@ -1090,6 +1136,11 @@
   Start();
 }
 
+void ScriptExecutor::WaitForDomOperation::SetTimeoutWarningCallback(
+    base::OnceCallback<void()> timeout_warning) {
+  timeout_warning_callback_ = std::move(timeout_warning);
+}
+
 void ScriptExecutor::WaitForDomOperation::Start() {
   retry_timer_.Start(
       max_wait_time_,
@@ -1137,8 +1188,19 @@
   main_script_->ReportScriptsUpdateToListener(std::move(scripts));
 }
 
+void ScriptExecutor::WaitForDomOperation::TimeoutWarning() {
+  if (timeout_warning_callback_) {
+    std::move(timeout_warning_callback_).Run();
+  }
+}
+
 void ScriptExecutor::WaitForDomOperation::RunChecks(
     base::OnceCallback<void(const ClientStatus&)> report_attempt_result) {
+  warning_timer_ = std::make_unique<base::OneShotTimer>();
+  warning_timer_->Start(
+      FROM_HERE, timeout_warning_period_,
+      base::BindOnce(&ScriptExecutor::WaitForDomOperation::TimeoutWarning,
+                     weak_ptr_factory_.GetWeakPtr()));
   wait_time_total_ =
       (wait_time_stopwatch_.TotalElapsed() < retry_timer_.period())
           // It's the first run of the checks, set the total time waited to 0.
@@ -1196,6 +1258,7 @@
 
 void ScriptExecutor::WaitForDomOperation::OnAllChecksDone(
     base::OnceCallback<void(const ClientStatus&)> report_attempt_result) {
+  warning_timer_->Stop();
   if (runnable_interrupts_.empty()) {
     // Since no interrupts fired, allow previously-run interrupts to be run
     // again in the next round. This is meant to give elements one round to
diff --git a/components/autofill_assistant/browser/script_executor.h b/components/autofill_assistant/browser/script_executor.h
index 79bd45c..0ded07b 100644
--- a/components/autofill_assistant/browser/script_executor.h
+++ b/components/autofill_assistant/browser/script_executor.h
@@ -273,6 +273,8 @@
   void ClearGenericUi() override;
   void SetOverlayBehavior(
       ConfigureUiStateProto::OverlayBehavior overlay_behavior) override;
+  void MaybeShowSlowWebsiteWarning() override;
+  void MaybeShowSlowConnectionWarning() override;
   base::WeakPtr<ActionDelegate> GetWeakPtr() const override;
 
  private:
@@ -304,6 +306,7 @@
 
     void Run();
     void Terminate();
+    void SetTimeoutWarningCallback(base::OnceCallback<void()> timeout_warning);
 
    private:
     void Start();
@@ -342,6 +345,8 @@
     // the original area.
     void RestorePreInterruptScroll();
 
+    void TimeoutWarning();
+
     ScriptExecutor* main_script_;
     ScriptExecutorDelegate* delegate_;
     const base::TimeDelta max_wait_time_;
@@ -350,6 +355,9 @@
                                  base::OnceCallback<void(const ClientStatus&)>)>
         check_elements_;
     WaitForDomOperation::Callback callback_;
+    base::OnceCallback<void()> timeout_warning_callback_;
+    std::unique_ptr<base::OneShotTimer> warning_timer_;
+    base::TimeDelta timeout_warning_period_;
 
     std::unique_ptr<BatchElementChecker> batch_element_checker_;
 
@@ -449,6 +457,10 @@
   // that they do not overwrite the paused state.
   bool ShouldInterruptOnPause(const ActionProto& proto);
 
+  // Maybe shows the message specified in a callout, depending on the current
+  // state and client settings.
+  void MaybeShowSlowWarning(const std::string& message, bool enabled);
+
   const std::string script_path_;
   std::unique_ptr<TriggerContext> additional_context_;
   std::string last_global_payload_;
@@ -525,6 +537,9 @@
   base::TimeTicks batch_start_time_;
   RoundtripTimingStats roundtrip_timing_stats_;
 
+  bool warning_callout_already_shown_ = false;
+  int consecutive_slow_roundtrip_counter_ = 0;
+
   base::WeakPtrFactory<ScriptExecutor> weak_ptr_factory_{this};
   DISALLOW_COPY_AND_ASSIGN(ScriptExecutor);
 };
diff --git a/components/autofill_assistant/browser/script_executor_delegate.h b/components/autofill_assistant/browser/script_executor_delegate.h
index 78dc335..33e71c23 100644
--- a/components/autofill_assistant/browser/script_executor_delegate.h
+++ b/components/autofill_assistant/browser/script_executor_delegate.h
@@ -192,6 +192,10 @@
   // calling |EnterState(BROWSE)| to take effect.
   virtual void SetBrowseModeInvisible(bool invisible) = 0;
 
+  // Whether the slow connection or website warning should be shown. Depends on
+  // the state at the moment of the invocation.
+  virtual bool ShouldShowWarning() = 0;
+
  protected:
   virtual ~ScriptExecutorDelegate() {}
 };
diff --git a/components/autofill_assistant/browser/script_executor_unittest.cc b/components/autofill_assistant/browser/script_executor_unittest.cc
index 7a86d49..80cdb61 100644
--- a/components/autofill_assistant/browser/script_executor_unittest.cc
+++ b/components/autofill_assistant/browser/script_executor_unittest.cc
@@ -264,6 +264,88 @@
   EXPECT_EQ(1u, processed_actions2_capture.size());
 }
 
+ACTION_P2(Delay, env, delay) {
+  env->FastForwardBy(base::TimeDelta::FromMilliseconds(delay));
+}
+
+TEST_F(ScriptExecutorTest, ShowsSlowConnectionWarning) {
+  ClientSettings* client_settings = delegate_.GetMutableSettings();
+  client_settings->slow_connection_message = "slow";
+  client_settings->enable_slow_connection_warnings = true;
+  client_settings->max_consecutive_slow_roundtrips = 2;
+  ActionsResponseProto initial_actions_response;
+  initial_actions_response.add_actions()->mutable_tell()->set_message("1");
+  EXPECT_CALL(mock_service_, OnGetActions(StrEq(kScriptPath), _, _, _, _, _))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))));
+
+  ActionsResponseProto next_actions_response;
+  next_actions_response.add_actions()->mutable_tell()->set_message("2");
+  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _, _))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))))
+      .WillOnce(RunOnceCallback<5>(net::HTTP_OK, ""));
+  EXPECT_CALL(executor_callback_,
+              Run(Field(&ScriptExecutor::Result::success, true)));
+  executor_->Run(&user_data_, executor_callback_.Get());
+
+  EXPECT_EQ(delegate_.GetBubbleMessage(), "slow");
+}
+
+TEST_F(ScriptExecutorTest, SlowConnectionWarningNotShowingIfNotConsecutive) {
+  ClientSettings* client_settings = delegate_.GetMutableSettings();
+  client_settings->slow_connection_message = "slow";
+  client_settings->enable_slow_connection_warnings = true;
+  client_settings->max_consecutive_slow_roundtrips = 2;
+  ActionsResponseProto initial_actions_response;
+  initial_actions_response.add_actions()->mutable_tell()->set_message("1");
+  EXPECT_CALL(mock_service_, OnGetActions(StrEq(kScriptPath), _, _, _, _, _))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))));
+
+  ActionsResponseProto next_actions_response;
+  next_actions_response.add_actions()->mutable_tell()->set_message("2");
+  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _, _))
+      .WillOnce(DoAll(RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))))
+      .WillOnce(RunOnceCallback<5>(net::HTTP_OK, ""));
+  EXPECT_CALL(executor_callback_,
+              Run(Field(&ScriptExecutor::Result::success, true)));
+  executor_->Run(&user_data_, executor_callback_.Get());
+
+  EXPECT_NE(delegate_.GetBubbleMessage(), "slow");
+}
+
+TEST_F(ScriptExecutorTest, SlowConnectionWarningNotShowingIfOnCompleted) {
+  ClientSettings* client_settings = delegate_.GetMutableSettings();
+  client_settings->slow_connection_message = "slow";
+  client_settings->enable_slow_connection_warnings = true;
+  client_settings->max_consecutive_slow_roundtrips = 2;
+  ActionsResponseProto initial_actions_response;
+  initial_actions_response.add_actions()->mutable_tell()->set_message("1");
+  EXPECT_CALL(mock_service_, OnGetActions(StrEq(kScriptPath), _, _, _, _, _))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK,
+                                         Serialize(initial_actions_response))));
+
+  EXPECT_CALL(mock_service_, OnGetNextActions(_, _, _, _, _, _))
+      .WillOnce(
+          RunOnceCallback<5>(net::HTTP_OK, Serialize(initial_actions_response)))
+      .WillOnce(DoAll(Delay(&task_environment_, 600),
+                      RunOnceCallback<5>(net::HTTP_OK, "")));
+  EXPECT_CALL(executor_callback_,
+              Run(Field(&ScriptExecutor::Result::success, true)));
+  executor_->Run(&user_data_, executor_callback_.Get());
+
+  EXPECT_NE(delegate_.GetBubbleMessage(), "slow");
+}
+
 TEST_F(ScriptExecutorTest, UnsupportedAction) {
   ActionsResponseProto actions_response;
   actions_response.add_actions();  // action definition missing
@@ -539,6 +621,27 @@
   EXPECT_EQ(ACTION_APPLIED, processed_actions_capture[0].status());
 }
 
+TEST_F(ScriptExecutorTest, WaitForDomSlowWarning) {
+  ClientSettings* client_settings = delegate_.GetMutableSettings();
+  client_settings->slow_website_message = "slow";
+  client_settings->enable_slow_website_warnings = true;
+  ActionsResponseProto actions_response;
+  auto* wait_for_dom = actions_response.add_actions()->mutable_wait_for_dom();
+  *wait_for_dom->mutable_wait_condition()->mutable_match() =
+      ToSelectorProto("element");
+
+  EXPECT_CALL(mock_service_, OnGetActions(_, _, _, _, _, _))
+      .WillOnce(RunOnceCallback<5>(net::HTTP_OK, Serialize(actions_response)));
+
+  // First check does not find the element, wait for dom waits 1s, then the
+  // element is found, and the action succeeds.
+  EXPECT_CALL(mock_web_controller_, OnFindElement(Selector({"element"}), _))
+      .WillOnce(Delay(&task_environment_, 2000));
+  executor_->Run(&user_data_, executor_callback_.Get());
+
+  EXPECT_EQ(delegate_.GetBubbleMessage(), "slow");
+}
+
 TEST_F(ScriptExecutorTest, RunInterrupt) {
   // All elements exist, so first the interrupt should be run, then the element
   // should be reported as found.
@@ -1636,10 +1739,6 @@
   EXPECT_EQ(AutofillAssistantState::PROMPT, delegate_.GetState());
 }
 
-ACTION_P2(Delay, env, delay) {
-  env->FastForwardBy(base::TimeDelta::FromMilliseconds(delay));
-}
-
 TEST_F(ScriptExecutorTest, RoundtripTimingStats) {
   ActionsResponseProto actions_response;
   ActionProto* action = actions_response.add_actions();
diff --git a/components/autofill_assistant/browser/script_tracker_unittest.cc b/components/autofill_assistant/browser/script_tracker_unittest.cc
index fc358c5..a1918fe 100644
--- a/components/autofill_assistant/browser/script_tracker_unittest.cc
+++ b/components/autofill_assistant/browser/script_tracker_unittest.cc
@@ -8,6 +8,7 @@
 
 #include "base/test/gmock_callback_support.h"
 #include "base/test/mock_callback.h"
+#include "base/test/task_environment.h"
 #include "components/autofill_assistant/browser/fake_script_executor_delegate.h"
 #include "components/autofill_assistant/browser/protocol_utils.h"
 #include "components/autofill_assistant/browser/script_executor_delegate.h"
@@ -126,6 +127,10 @@
     return output;
   }
 
+  // task_environment_ must be first to guarantee other field
+  // creation run in that environment.
+  base::test::TaskEnvironment task_environment_;
+
   GURL url_;
   NiceMock<MockService> mock_service_;
   NiceMock<MockWebController> mock_web_controller_;
diff --git a/components/autofill_assistant/browser/service.proto b/components/autofill_assistant/browser/service.proto
index 0748f4c..3fc8a73 100644
--- a/components/autofill_assistant/browser/service.proto
+++ b/components/autofill_assistant/browser/service.proto
@@ -155,6 +155,7 @@
   optional ClientDimensionProto text_size = 7;
 }
 
+// Next ID: 22
 message ClientSettingsProto {
   message IntegrationTestSettings {
     // Disables animations for the poodle and the progress bar.
@@ -231,6 +232,32 @@
   }
   optional BackButtonSettings back_button_settings = 19;
 
+  // Settings to define the behavior for showing warnings about slow connection
+  // and/or websites to users.
+  message SlowWarningSettings {
+    // Whether to show warnings related to a slow connection to the user.
+    optional bool enable_slow_connection_warnings = 1;
+    // Whether to show warnings related to a slow website to the user.
+    optional bool enable_slow_website_warnings = 2;
+    // If true, the slow connection or website warning will be only shown once.
+    optional bool show_only_once = 3;
+    // Defines the maximum wait on a dom find element operation before showing
+    // the slow website warning.
+    optional int32 warning_delay_ms = 4;
+    // Defines the threshold above which a roundtrip is considered too slow.
+    optional int32 slow_roundtrip_threshold_ms = 5;
+    // Defines the number of consecutive slow roundtrips allowed before showing
+    // the slow connection warning.
+    optional int32 max_consecutive_slow_roundtrips = 6;
+    // The message to show as a warning to inform the user of a slow connection.
+    // If this is not set, no warning will be shown in case of slow connection.
+    optional string slow_connection_message = 7;
+    // The message to show as a warning to inform the user of a slow website.
+    // If this is not set, no warning will be shown in case of a slow website.
+    optional string slow_website_message = 8;
+  }
+  optional SlowWarningSettings slow_warning_settings = 21;
+
   reserved 8 to 11;
 }
 
diff --git a/components/browser_sync/active_devices_provider_impl.cc b/components/browser_sync/active_devices_provider_impl.cc
index ec07f79..94aedba 100644
--- a/components/browser_sync/active_devices_provider_impl.cc
+++ b/components/browser_sync/active_devices_provider_impl.cc
@@ -8,22 +8,12 @@
 
 #include "base/feature_list.h"
 #include "base/metrics/field_trial_params.h"
+#include "base/stl_util.h"
 #include "components/browser_sync/active_devices_provider_impl.h"
+#include "components/browser_sync/browser_sync_switches.h"
 
 namespace browser_sync {
 
-// Enables filtering out inactive devices which haven't sent DeviceInfo update
-// recently (depending on the device's pulse_interval and an additional margin).
-const base::Feature kSyncFilterOutInactiveDevicesForSingleClient{
-    "SyncFilterOutInactiveDevicesForSingleClient",
-    base::FEATURE_ENABLED_BY_DEFAULT};
-
-// An additional threshold to consider devices as active. It extends device's
-// pulse interval to mitigate possible latency after DeviceInfo commit.
-const base::FeatureParam<base::TimeDelta> kSyncActiveDeviceMargin{
-    &kSyncFilterOutInactiveDevicesForSingleClient, "SyncActiveDeviceMargin",
-    base::TimeDelta::FromMinutes(30)};
-
 ActiveDevicesProviderImpl::ActiveDevicesProviderImpl(
     syncer::DeviceInfoTracker* device_info_tracker,
     base::Clock* clock)
@@ -40,25 +30,43 @@
 
 size_t ActiveDevicesProviderImpl::CountActiveDevicesIfAvailable() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-  std::vector<std::unique_ptr<syncer::DeviceInfo>> all_devices =
-      device_info_tracker_->GetAllDeviceInfo();
+
+  return GetActiveDevices().size();
+}
+
+std::vector<std::string>
+ActiveDevicesProviderImpl::CollectFCMRegistrationTokensForInvalidations(
+    const std::string& local_cache_guid) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+  std::vector<std::string> fcm_registration_tokens;
   if (!base::FeatureList::IsEnabled(
-          kSyncFilterOutInactiveDevicesForSingleClient)) {
-    return all_devices.size();
+          switches::kSyncUseFCMRegistrationTokensList)) {
+    return fcm_registration_tokens;
   }
 
-  size_t active_devices = 0;
-  for (const auto& device : all_devices) {
-    const base::Time expected_expiration_time =
-        device->last_updated_timestamp() + device->pulse_interval() +
-        kSyncActiveDeviceMargin.Get();
-    // If the device's expiration time hasn't been reached, then it is
-    // considered active device.
-    if (expected_expiration_time > clock_->Now()) {
-      active_devices++;
+  for (const std::unique_ptr<syncer::DeviceInfo>& device : GetActiveDevices()) {
+    if (!local_cache_guid.empty() && device->guid() == local_cache_guid) {
+      continue;
     }
+    if (device->fcm_registration_token().empty()) {
+      continue;
+    }
+
+    fcm_registration_tokens.push_back(device->fcm_registration_token());
   }
-  return active_devices;
+
+  // Do not send tokens if the list of active devices is huge. This is similar
+  // to the case when the client doesn't know about other devices, so return an
+  // empty list. Otherwise the client would return only a part of all active
+  // clients and other clients might miss an invalidation.
+  if (fcm_registration_tokens.size() >
+      static_cast<size_t>(
+          switches::kSyncFCMRegistrationTokensListMaxSize.Get())) {
+    return std::vector<std::string>();
+  }
+
+  return fcm_registration_tokens;
 }
 
 void ActiveDevicesProviderImpl::SetActiveDevicesChangedCallback(
@@ -77,4 +85,26 @@
   }
 }
 
+std::vector<std::unique_ptr<syncer::DeviceInfo>>
+ActiveDevicesProviderImpl::GetActiveDevices() const {
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> all_devices =
+      device_info_tracker_->GetAllDeviceInfo();
+  if (!base::FeatureList::IsEnabled(
+          switches::kSyncFilterOutInactiveDevicesForSingleClient)) {
+    return all_devices;
+  }
+
+  base::EraseIf(
+      all_devices, [this](const std::unique_ptr<syncer::DeviceInfo>& device) {
+        const base::Time expected_expiration_time =
+            device->last_updated_timestamp() + device->pulse_interval() +
+            switches::kSyncActiveDeviceMargin.Get();
+        // If the device's expiration time hasn't been reached, then
+        // it is considered active device.
+        return expected_expiration_time <= clock_->Now();
+      });
+
+  return all_devices;
+}
+
 }  // namespace browser_sync
diff --git a/components/browser_sync/active_devices_provider_impl.h b/components/browser_sync/active_devices_provider_impl.h
index d0bbed0..5bca0e5 100644
--- a/components/browser_sync/active_devices_provider_impl.h
+++ b/components/browser_sync/active_devices_provider_impl.h
@@ -5,6 +5,10 @@
 #ifndef COMPONENTS_BROWSER_SYNC_ACTIVE_DEVICES_PROVIDER_IMPL_H_
 #define COMPONENTS_BROWSER_SYNC_ACTIVE_DEVICES_PROVIDER_IMPL_H_
 
+#include <memory>
+#include <string>
+#include <vector>
+
 #include "base/sequence_checker.h"
 #include "base/time/default_clock.h"
 #include "components/sync/driver/active_devices_provider.h"
@@ -26,6 +30,9 @@
   // syncer::ActiveDevicesProvider implementation.
   size_t CountActiveDevicesIfAvailable() override;
 
+  std::vector<std::string> CollectFCMRegistrationTokensForInvalidations(
+      const std::string& local_cache_guid) override;
+
   void SetActiveDevicesChangedCallback(
       ActiveDevicesChangedCallback callback) override;
 
@@ -33,6 +40,8 @@
   void OnDeviceInfoChange() override;
 
  private:
+  std::vector<std::unique_ptr<syncer::DeviceInfo>> GetActiveDevices() const;
+
   syncer::DeviceInfoTracker* const device_info_tracker_;
   const base::Clock* const clock_;
   ActiveDevicesChangedCallback callback_;
diff --git a/components/browser_sync/active_devices_provider_impl_unittest.cc b/components/browser_sync/active_devices_provider_impl_unittest.cc
index f9dbaa1..5ab9233c 100644
--- a/components/browser_sync/active_devices_provider_impl_unittest.cc
+++ b/components/browser_sync/active_devices_provider_impl_unittest.cc
@@ -9,15 +9,19 @@
 #include <vector>
 
 #include "base/guid.h"
+#include "base/strings/string_number_conversions.h"
 #include "base/test/mock_callback.h"
 #include "base/test/simple_test_clock.h"
 #include "base/time/time.h"
+#include "components/browser_sync/browser_sync_switches.h"
 #include "components/sync_device_info/device_info_util.h"
 #include "components/sync_device_info/fake_device_info_tracker.h"
 #include "testing/gtest/include/gtest/gtest.h"
 
 using syncer::DeviceInfo;
 using syncer::FakeDeviceInfoTracker;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
 
 namespace browser_sync {
 namespace {
@@ -26,15 +30,15 @@
 
 std::unique_ptr<DeviceInfo> CreateFakeDeviceInfo(
     const std::string& name,
+    const std::string& fcm_registration_token,
     base::Time last_updated_timestamp) {
   return std::make_unique<syncer::DeviceInfo>(
-      base::GenerateGUID(), name, "chrome_version", "user_agent",
-      sync_pb::SyncEnums::TYPE_UNSET, "device_id", "manufacturer_name",
-      "model_name", last_updated_timestamp,
+      base::GUID::GenerateRandomV4().AsLowercaseString(), name,
+      "chrome_version", "user_agent", sync_pb::SyncEnums::TYPE_UNSET,
+      "device_id", "manufacturer_name", "model_name", last_updated_timestamp,
       base::TimeDelta::FromMinutes(kPulseIntervalMinutes),
       /*send_tab_to_self_receiving_enabled=*/false,
-      /*sharing_info=*/base::nullopt,
-      /*fcm_registration_token=*/std::string(),
+      /*sharing_info=*/base::nullopt, fcm_registration_token,
       /*interested_data_types=*/syncer::ModelTypeSet());
 }
 
@@ -45,8 +49,11 @@
 
   ~ActiveDevicesProviderImplTest() override = default;
 
-  void AddDevice(const std::string& name, base::Time last_updated_timestamp) {
-    device_list_.push_back(CreateFakeDeviceInfo(name, last_updated_timestamp));
+  void AddDevice(const std::string& name,
+                 const std::string& fcm_registration_token,
+                 base::Time last_updated_timestamp) {
+    device_list_.push_back(CreateFakeDeviceInfo(name, fcm_registration_token,
+                                                last_updated_timestamp));
     fake_device_info_tracker_.Add(device_list_.back().get());
   }
 
@@ -58,16 +65,19 @@
 };
 
 TEST_F(ActiveDevicesProviderImplTest, ShouldFilterInactiveDevices) {
-  AddDevice("device_recent", clock_.Now() - base::TimeDelta::FromMinutes(1));
+  AddDevice("device_recent", /*fcm_registration_token=*/"",
+            clock_.Now() - base::TimeDelta::FromMinutes(1));
 
   // Should be considered as active device due to margin even though the device
   // is outside the pulse interval.
   AddDevice(
       "device_pulse_interval",
+      /*fcm_registration_token=*/"",
       clock_.Now() - base::TimeDelta::FromMinutes(kPulseIntervalMinutes + 1));
 
   // Very old device.
-  AddDevice("device_inactive", clock_.Now() - base::TimeDelta::FromDays(100));
+  AddDevice("device_inactive", /*fcm_registration_token=*/"",
+            clock_.Now() - base::TimeDelta::FromDays(100));
 
   EXPECT_EQ(2u, active_devices_provider_.CountActiveDevicesIfAvailable());
 }
@@ -87,5 +97,44 @@
       base::RepeatingClosure());
 }
 
+TEST_F(ActiveDevicesProviderImplTest, ShouldReturnActiveFCMRegistrationTokens) {
+  AddDevice("device_1", "fcm_token_1",
+            clock_.Now() - base::TimeDelta::FromMinutes(1));
+  AddDevice("device_2", "fcm_token_2",
+            clock_.Now() - base::TimeDelta::FromMinutes(1));
+  AddDevice("device_inactive", "fcm_token_3",
+            clock_.Now() - base::TimeDelta::FromDays(100));
+
+  ASSERT_EQ(3u, device_list_.size());
+
+  EXPECT_THAT(
+      active_devices_provider_.CollectFCMRegistrationTokensForInvalidations(
+          "other_guid"),
+      UnorderedElementsAre(device_list_[0]->fcm_registration_token(),
+                           device_list_[1]->fcm_registration_token()));
+  EXPECT_THAT(
+      active_devices_provider_.CollectFCMRegistrationTokensForInvalidations(
+          device_list_[0]->guid()),
+      UnorderedElementsAre(device_list_[1]->fcm_registration_token()));
+}
+
+TEST_F(ActiveDevicesProviderImplTest, ShouldReturnEmptyListWhenTooManyDevices) {
+  // Create many devices to exceed the limit of the list.
+  const size_t kActiveDevicesNumber =
+      switches::kSyncFCMRegistrationTokensListMaxSize.Get() + 1;
+
+  for (size_t i = 0; i < kActiveDevicesNumber; ++i) {
+    const std::string device_name = "device_" + base::NumberToString(i);
+    const std::string fcm_token = "fcm_token_" + device_name;
+    AddDevice(device_name, fcm_token,
+              clock_.Now() - base::TimeDelta::FromMinutes(1));
+  }
+
+  EXPECT_THAT(
+      active_devices_provider_.CollectFCMRegistrationTokensForInvalidations(
+          "guid"),
+      IsEmpty());
+}
+
 }  // namespace
 }  // namespace browser_sync
diff --git a/components/browser_sync/browser_sync_switches.cc b/components/browser_sync/browser_sync_switches.cc
index e327d97..4ba5ded 100644
--- a/components/browser_sync/browser_sync_switches.cc
+++ b/components/browser_sync/browser_sync_switches.cc
@@ -26,4 +26,27 @@
     "SyncUseSessionsUnregisterDelay", base::FEATURE_DISABLED_BY_DEFAULT};
 #endif  // defined(OS_ANDROID)
 
+// Enables filtering out inactive devices which haven't sent DeviceInfo update
+// recently (depending on the device's pulse_interval and an additional margin).
+const base::Feature kSyncFilterOutInactiveDevicesForSingleClient{
+    "SyncFilterOutInactiveDevicesForSingleClient",
+    base::FEATURE_ENABLED_BY_DEFAULT};
+
+// An additional threshold to consider devices as active. It extends device's
+// pulse interval to mitigate possible latency after DeviceInfo commit.
+const base::FeatureParam<base::TimeDelta> kSyncActiveDeviceMargin{
+    &kSyncFilterOutInactiveDevicesForSingleClient, "SyncActiveDeviceMargin",
+    base::TimeDelta::FromMinutes(30)};
+
+// Enables providing the list of FCM registration tokens in the commit request.
+const base::Feature kSyncUseFCMRegistrationTokensList{
+    "SyncUseFCMRegistrationTokensList", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Max size of FCM registration tokens list. If the number of active devices
+// having FCM registration tokens is higher, then the resulting list will be
+// empty meaning unknown FCM registration tokens.
+const base::FeatureParam<int> kSyncFCMRegistrationTokensListMaxSize{
+    &kSyncUseFCMRegistrationTokensList, "SyncFCMRegistrationTokensListMaxSize",
+    5};
+
 }  // namespace switches
diff --git a/components/browser_sync/browser_sync_switches.h b/components/browser_sync/browser_sync_switches.h
index 21e7612..32345cd 100644
--- a/components/browser_sync/browser_sync_switches.h
+++ b/components/browser_sync/browser_sync_switches.h
@@ -18,6 +18,11 @@
 extern const base::Feature kSyncUseSessionsUnregisterDelay;
 #endif
 
+extern const base::Feature kSyncFilterOutInactiveDevicesForSingleClient;
+extern const base::FeatureParam<base::TimeDelta> kSyncActiveDeviceMargin;
+extern const base::Feature kSyncUseFCMRegistrationTokensList;
+extern const base::FeatureParam<int> kSyncFCMRegistrationTokensListMaxSize;
+
 }  // namespace switches
 
 #endif  // COMPONENTS_BROWSER_SYNC_BROWSER_SYNC_SWITCHES_H_
diff --git a/components/browser_ui/photo_picker/android/BUILD.gn b/components/browser_ui/photo_picker/android/BUILD.gn
index ed902f8..c402ff6 100644
--- a/components/browser_ui/photo_picker/android/BUILD.gn
+++ b/components/browser_ui/photo_picker/android/BUILD.gn
@@ -5,7 +5,11 @@
 import("//build/config/android/rules.gni")
 
 source_set("android") {
-  sources = [ "photo_picker_sandbox_bridge.cc" ]
+  sources = [
+    "features.cc",
+    "features.h",
+    "photo_picker_sandbox_bridge.cc",
+  ]
   deps = [
     ":photo_picker_jni_headers",
     "//base",
diff --git a/components/browser_ui/photo_picker/android/features.cc b/components/browser_ui/photo_picker/android/features.cc
new file mode 100644
index 0000000..a517698
--- /dev/null
+++ b/components/browser_ui/photo_picker/android/features.cc
@@ -0,0 +1,14 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "components/browser_ui/photo_picker/android/features.h"
+
+namespace photo_picker {
+namespace features {
+
+const base::Feature kPhotoPickerVideoSupport{"PhotoPickerVideoSupport",
+                                             base::FEATURE_DISABLED_BY_DEFAULT};
+
+}  // namespace features
+}  // namespace photo_picker
diff --git a/components/browser_ui/photo_picker/android/features.h b/components/browser_ui/photo_picker/android/features.h
new file mode 100644
index 0000000..1834686
--- /dev/null
+++ b/components/browser_ui/photo_picker/android/features.h
@@ -0,0 +1,18 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMPONENTS_BROWSER_UI_PHOTO_PICKER_ANDROID_FEATURES_H_
+#define COMPONENTS_BROWSER_UI_PHOTO_PICKER_ANDROID_FEATURES_H_
+
+#include "base/feature_list.h"
+
+namespace photo_picker {
+namespace features {
+
+extern const base::Feature kPhotoPickerVideoSupport;
+
+}  // namespace features
+}  // namespace photo_picker
+
+#endif  // COMPONENTS_BROWSER_UI_PHOTO_PICKER_ANDROID_FEATURES_H_
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHost.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHost.java
index cacc7ff..ca09cee 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHost.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHost.java
@@ -49,6 +49,9 @@
     // A tag for logging error messages.
     private static final String TAG = "ImageDecoderHost";
 
+    // The current context.
+    private final Context mContext;
+
     // A content resolver for providing file descriptors for the images.
     private ContentResolver mContentResolver;
 
@@ -76,9 +79,18 @@
     // The number of io failures during video decoding, per batch.
     private int mFailedVideoDecodesUnknown;
 
+    // Whether animated thumbnails should be generated for video clips.
+    private final boolean mAnimatedThumbnailsSupported;
+
     // A worker task for asynchronously handling video decode requests.
     private DecodeVideoTask mWorkerTask;
 
+    // The current processing request.
+    private DecoderServiceParams mProcessingRequest;
+
+    // The callbacks used to notify the clients when the service is ready.
+    private final List<DecoderStatusCallback> mCallbacks = new ArrayList<DecoderStatusCallback>();
+
     // Keeps track of the last decoding ordinal issued.
     static int sLastDecodingOrdinal = 0;
 
@@ -215,20 +227,17 @@
     PriorityQueue<DecoderServiceParams> mPendingRequests =
             new PriorityQueue<>(/*initialCapacity=*/1, mRequestComparator);
 
-    // The current processing request.
-    private DecoderServiceParams mProcessingRequest;
-
-    // The callbacks used to notify the clients when the service is ready.
-    private final List<DecoderStatusCallback> mCallbacks = new ArrayList<DecoderStatusCallback>();
-
-    private final Context mContext;
-
     /**
      * The DecoderServiceHost constructor.
      * @param callback The callback to use when communicating back to the client.
+     * @param context The current context.
+     * @param animatedThumbnailsSupported Whether animated thumbnails should be generated for video
+     *         clips.
      */
-    public DecoderServiceHost(DecoderStatusCallback callback, Context context) {
+    public DecoderServiceHost(
+            DecoderStatusCallback callback, Context context, boolean animatedThumbnailsSupported) {
         mCallbacks.add(callback);
+        mAnimatedThumbnailsSupported = animatedThumbnailsSupported;
         if (sStatusCallbackForTesting != null) {
             mCallbacks.add(sStatusCallbackForTesting);
         }
@@ -273,7 +282,7 @@
         DecoderServiceParams params = new DecoderServiceParams(
                 uri, width, fullWidth, fileType, /*firstFrame=*/true, callback);
         mPendingRequests.add(params);
-        if (params.mFileType == PickerBitmap.TileTypes.VIDEO) {
+        if (params.mFileType == PickerBitmap.TileTypes.VIDEO && mAnimatedThumbnailsSupported) {
             // Decoding requests for videos are requests for first frames only. Add another
             // low-priority request for decoding the rest of the frames.
             DecoderServiceParams lowPriorityRequest =
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHostTest.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHostTest.java
index d2380a0..92d3688 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHostTest.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/DecoderServiceHostTest.java
@@ -47,6 +47,9 @@
     // A callback that fires when the decoder is ready.
     public final CallbackHelper mOnDecoderReadyCallback = new CallbackHelper();
 
+    // A callback that fires when the decoder is idle.
+    public final CallbackHelper mOnDecoderIdleCallback = new CallbackHelper();
+
     // A callback that fires when something is finished decoding in the dialog.
     public final CallbackHelper mOnDecodedCallback = new CallbackHelper();
 
@@ -77,7 +80,9 @@
     }
 
     @Override
-    public void decoderIdle() {}
+    public void decoderIdle() {
+        mOnDecoderIdleCallback.notifyCalled();
+    }
 
     // DecoderServiceHost.ImagesDecodedCallback:
 
@@ -100,6 +105,11 @@
                 callCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
     }
 
+    private void waitForDecoderIdle(int lastCount) throws Exception {
+        mOnDecoderIdleCallback.waitForCallback(
+                lastCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
+    }
+
     private void waitForThumbnailDecode() throws Exception {
         int callCount = mOnDecodedCallback.getCallCount();
         mOnDecodedCallback.waitForCallback(callCount, 1, WAIT_TIMEOUT_MS, TimeUnit.MILLISECONDS);
@@ -133,7 +143,8 @@
         lowerPri = new DecoderServiceHost.DecoderServiceParams(uri, width, fullWidth,
                 PickerBitmap.TileTypes.VIDEO,
                 /* firstFrame= */ true, callback);
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
         Assert.assertTrue("Still images have priority over requests for initial video frame",
                 host.mRequestComparator.compare(higherPri, lowerPri) < 0);
 
@@ -191,7 +202,8 @@
     @Test
     @LargeTest
     public void testDecodingOrder() throws Throwable {
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
         host.bind(mContext);
         waitForDecoder();
 
@@ -254,8 +266,70 @@
 
     @Test
     @LargeTest
+    public void testDecodingOrderNoAnimationSupported() throws Throwable {
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ false);
+        host.bind(mContext);
+        waitForDecoder();
+
+        String video1 = "noogler.mp4";
+        String video2 = "noogler2.mp4";
+        String jpg1 = "blue100x100.jpg";
+        File file1 = new File(UrlUtils.getIsolatedTestFilePath(TEST_FILE_PATH + video1));
+        File file2 = new File(UrlUtils.getIsolatedTestFilePath(TEST_FILE_PATH + video2));
+        File file3 = new File(UrlUtils.getIsolatedTestFilePath(TEST_FILE_PATH + jpg1));
+
+        decodeImage(host, Uri.fromFile(file1), PickerBitmap.TileTypes.VIDEO, 10,
+                /*fullWidth=*/false, this);
+        decodeImage(host, Uri.fromFile(file2), PickerBitmap.TileTypes.VIDEO, 10,
+                /*fullWidth=*/false, this);
+        decodeImage(host, Uri.fromFile(file3), PickerBitmap.TileTypes.PICTURE, 10,
+                /*fullWidth=*/false, this);
+
+        int idleCallCount = mOnDecoderIdleCallback.getCallCount();
+
+        // First decoding result should be first frame of video 1. Even though still images take
+        // priority over video decoding, video 1 will be the only item in the queue when the first
+        // decoding request is kicked off (as a result of calling decodeImage).
+        waitForThumbnailDecode();
+        Assert.assertTrue(mLastDecodedPath.contains(video1));
+        Assert.assertEquals(true, mLastIsVideo);
+        Assert.assertEquals("0:00", mLastVideoDuration);
+        Assert.assertEquals(1, mLastFrameCount);
+
+        // When the decoder is finished with the first frame of video 1, there will be two new
+        // requests available for processing. Video2 was added first, but that will be skipped in
+        // favor of the still image, so the jpg is expected to be decoded next.
+        waitForThumbnailDecode();
+        Assert.assertTrue(mLastDecodedPath.contains(jpg1));
+        Assert.assertEquals(false, mLastIsVideo);
+        Assert.assertEquals(null, mLastVideoDuration);
+        Assert.assertEquals(1, mLastFrameCount);
+
+        // Third and last decoding result is first frame of video 2.
+        waitForThumbnailDecode();
+        Assert.assertTrue(mLastDecodedPath.contains(video2));
+        Assert.assertEquals(true, mLastIsVideo);
+        Assert.assertEquals("0:00", mLastVideoDuration);
+        Assert.assertEquals(1, mLastFrameCount);
+
+        // Make sure nothing else is returned (no animations should be supported).
+        waitForDecoderIdle(idleCallCount);
+
+        // Everything should be as we left it.
+        Assert.assertTrue(mLastDecodedPath.contains(video2));
+        Assert.assertEquals(true, mLastIsVideo);
+        Assert.assertEquals("0:00", mLastVideoDuration);
+        Assert.assertEquals(1, mLastFrameCount);
+
+        host.unbind(mContext);
+    }
+
+    @Test
+    @LargeTest
     public void testDecodingSizes() throws Throwable {
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
         host.bind(mContext);
         waitForDecoder();
 
@@ -334,7 +408,8 @@
     @Test
     @LargeTest
     public void testCancelation() throws Throwable {
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
         host.bind(mContext);
         waitForDecoder();
 
@@ -370,7 +445,8 @@
     @Test
     @LargeTest
     public void testNoConnectionFailureMode() throws Throwable {
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
 
         // Try decoding without a connection to the decoder.
         String green = "green100x100.jpg";
@@ -384,7 +460,8 @@
     @Test
     @LargeTest
     public void testFileNotFoundFailureMode() throws Throwable {
-        DecoderServiceHost host = new DecoderServiceHost(this, mContext);
+        DecoderServiceHost host =
+                new DecoderServiceHost(this, mContext, /* animatedThumbnailsSupported = */ true);
         host.bind(mContext);
         waitForDecoder();
 
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialog.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialog.java
index 544c6ff..7854543 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialog.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialog.java
@@ -84,18 +84,21 @@
      * @param listener The listener object that gets notified when an action is taken.
      * @param multiSelectionAllowed Whether the photo picker should allow multiple items to be
      *                              selected.
+     * @param animatedThumbnailsSupported Whether animated thumbnails should be generated for video
+     *         clips.
      * @param mimeTypes A list of mime types to show in the dialog.
      */
     public PhotoPickerDialog(WindowAndroid windowAndroid, ContentResolver contentResolver,
-            PhotoPickerListener listener, boolean multiSelectionAllowed, List<String> mimeTypes) {
+            PhotoPickerListener listener, boolean multiSelectionAllowed,
+            boolean animatedThumbnailsSupported, List<String> mimeTypes) {
         super(windowAndroid.getContext().get(), R.style.Theme_Chromium_Fullscreen);
 
         mWindowAndroid = windowAndroid;
         mListenerWrapper = new PhotoPickerListenerWrapper(listener);
 
         // Initialize the main content view.
-        mCategoryView =
-                new PickerCategoryView(windowAndroid, contentResolver, multiSelectionAllowed, this);
+        mCategoryView = new PickerCategoryView(windowAndroid, contentResolver,
+                multiSelectionAllowed, animatedThumbnailsSupported, this);
         mCategoryView.initialize(this, mListenerWrapper, mimeTypes);
         setView(mCategoryView);
     }
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
index 3fdb2c58..c69215b 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PhotoPickerDialogTest.java
@@ -272,9 +272,9 @@
                 TestThreadUtils.runOnUiThreadBlocking(new Callable<PhotoPickerDialog>() {
                     @Override
                     public PhotoPickerDialog call() {
-                        final PhotoPickerDialog dialog =
-                                new PhotoPickerDialog(mWindowAndroid, contentResolver,
-                                        PhotoPickerDialogTest.this, multiselect, mimeTypes);
+                        final PhotoPickerDialog dialog = new PhotoPickerDialog(mWindowAndroid,
+                                contentResolver, PhotoPickerDialogTest.this, multiselect,
+                                /* animatedThumbnailsSupported = */ true, mimeTypes);
                         dialog.show();
                         return dialog;
                     }
diff --git a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java
index 9b0074f..8afb200a 100644
--- a/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java
+++ b/components/browser_ui/photo_picker/android/java/src/org/chromium/components/browser_ui/photo_picker/PickerCategoryView.java
@@ -192,17 +192,20 @@
      *         selection.
      * @param contentResolver The ContentResolver to use to retrieve image metadata from disk.
      * @param multiSelectionAllowed Whether to allow the user to select more than one image.
+     * @param animatedThumbnailsSupported Whether animated thumbnails should be generated for video
+     *         clips.
      */
     @SuppressWarnings("unchecked") // mSelectableListLayout
     public PickerCategoryView(WindowAndroid windowAndroid, ContentResolver contentResolver,
-            boolean multiSelectionAllowed, PhotoPickerToolbar.PhotoPickerToolbarDelegate delegate) {
+            boolean multiSelectionAllowed, boolean animatedThumbnailsSupported,
+            PhotoPickerToolbar.PhotoPickerToolbarDelegate delegate) {
         super(windowAndroid.getContext().get());
         mWindowAndroid = windowAndroid;
         Context context = mWindowAndroid.getContext().get();
         mContentResolver = contentResolver;
         mMultiSelectionAllowed = multiSelectionAllowed;
 
-        mDecoderServiceHost = new DecoderServiceHost(this, context);
+        mDecoderServiceHost = new DecoderServiceHost(this, context, animatedThumbnailsSupported);
         mDecoderServiceHost.bind(context);
 
         mSelectionDelegate = new SelectionDelegate<PickerBitmap>();
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
index 517861e..68ba45b1 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SingleCategorySettings.java
@@ -490,6 +490,13 @@
                 return;
         }
 
+        getSiteSettingsDelegate().dismissPrivacySandboxSnackbar();
+
+        // Display the Privacy Sandbox snackbar whenever third-party/all cookies are blocked.
+        if (mode == CookieControlsMode.BLOCK_THIRD_PARTY) {
+            getSiteSettingsDelegate().maybeDisplayPrivacySandboxSnackbar();
+        }
+
         WebsitePreferenceBridge.setCategoryEnabled(
                 getSiteSettingsDelegate().getBrowserContextHandle(), ContentSettingsType.COOKIES,
                 allowCookies);
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
index 931f996..d3ee6e05 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsDelegate.java
@@ -112,4 +112,15 @@
      * @return The set of all origins whose notification permissions are delegated to another app.
      */
     Set<String> getAllDelegatedNotificationOrigins();
+
+    /**
+     * Displays a snackbar, informing the user about the Privacy Sandbox settings page, when the
+     * corresponding flag is enabled.
+     */
+    void maybeDisplayPrivacySandboxSnackbar();
+
+    /**
+     * Dismisses the Privacy Sandbox snackbar, if active.
+     */
+    void dismissPrivacySandboxSnackbar();
 }
diff --git a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsPreferenceFragment.java b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsPreferenceFragment.java
index 9643ecef..0d816be 100644
--- a/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsPreferenceFragment.java
+++ b/components/browser_ui/site_settings/android/java/src/org/chromium/components/browser_ui/site_settings/SiteSettingsPreferenceFragment.java
@@ -25,7 +25,7 @@
     /**
      * @return the SiteSettingsDelegate instance to use when rendering the Site Settings UI.
      */
-    protected SiteSettingsDelegate getSiteSettingsDelegate() {
+    public SiteSettingsDelegate getSiteSettingsDelegate() {
         assert mSiteSettingsDelegate != null : "SiteSettingsDelegate not set";
         return mSiteSettingsDelegate;
     }
diff --git a/components/feed/core/v2/feed_network_impl_unittest.cc b/components/feed/core/v2/feed_network_impl_unittest.cc
index dfafe06..3f8c6a0 100644
--- a/components/feed/core/v2/feed_network_impl_unittest.cc
+++ b/components/feed/core/v2/feed_network_impl_unittest.cc
@@ -476,7 +476,9 @@
   auto* elements = resource_request.request_body->elements();
   ASSERT_TRUE(elements);
   ASSERT_EQ(1UL, elements->size());
-  std::string sent_body((*elements)[0].bytes(), (*elements)[0].length());
+  ASSERT_EQ(network::DataElement::Tag::kBytes, elements->at(0).type());
+  std::string sent_body(
+      elements->at(0).As<network::DataElementBytes>().AsStringPiece());
   std::string sent_body_uncompressed;
   ASSERT_TRUE(compression::GzipUncompress(sent_body, &sent_body_uncompressed));
   std::string expected_body;
diff --git a/components/optimization_guide/core/hints_fetcher_unittest.cc b/components/optimization_guide/core/hints_fetcher_unittest.cc
index a6882bc..bf009ad64 100644
--- a/components/optimization_guide/core/hints_fetcher_unittest.cc
+++ b/components/optimization_guide/core/hints_fetcher_unittest.cc
@@ -139,7 +139,12 @@
       EXPECT_EQ(pending_request.request.request_body->elements()->size(), 1u);
       auto& element =
           pending_request.request.request_body->elements_mutable()->front();
-      last_request_body_ = std::string(element.bytes(), element.length());
+      if (element.type() != network::DataElement::Tag::kBytes) {
+        ADD_FAILURE() << "network::DataElement type mismatch";
+        return;
+      }
+      last_request_body_ =
+          std::string(element.As<network::DataElementBytes>().AsStringPiece());
     }
   }
 
diff --git a/components/password_manager/core/browser/password_store_signin_notifier_impl.cc b/components/password_manager/core/browser/password_store_signin_notifier_impl.cc
index b22f058..8777fb1 100644
--- a/components/password_manager/core/browser/password_store_signin_notifier_impl.cc
+++ b/components/password_manager/core/browser/password_store_signin_notifier_impl.cc
@@ -48,9 +48,13 @@
 }
 
 // IdentityManager::Observer implementation.
-void PasswordStoreSigninNotifierImpl::OnPrimaryAccountCleared(
-    const CoreAccountInfo& account_info) {
-  NotifySignedOut(account_info.email, /* primary_account= */ true);
+void PasswordStoreSigninNotifierImpl::OnPrimaryAccountChanged(
+    const signin::PrimaryAccountChangeEvent& event) {
+  if (event.GetEventTypeFor(signin::ConsentLevel::kSync) ==
+      signin::PrimaryAccountChangeEvent::Type::kCleared) {
+    NotifySignedOut(event.GetPreviousState().primary_account.email,
+                    /* primary_account= */ true);
+  }
 }
 
 // IdentityManager::Observer implementation.
diff --git a/components/password_manager/core/browser/password_store_signin_notifier_impl.h b/components/password_manager/core/browser/password_store_signin_notifier_impl.h
index 172fa3de..32e9ad2 100644
--- a/components/password_manager/core/browser/password_store_signin_notifier_impl.h
+++ b/components/password_manager/core/browser/password_store_signin_notifier_impl.h
@@ -32,7 +32,8 @@
   void UnsubscribeFromSigninEvents() override;
 
   // IdentityManager::Observer implementations.
-  void OnPrimaryAccountCleared(const CoreAccountInfo& account_info) override;
+  void OnPrimaryAccountChanged(
+      const signin::PrimaryAccountChangeEvent& event) override;
   void OnExtendedAccountInfoRemoved(const AccountInfo& info) override;
 
  private:
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.cc b/components/password_manager/core/browser/sync/password_model_type_controller.cc
index a8e00c03..cf3ff87 100644
--- a/components/password_manager/core/browser/sync/password_model_type_controller.cc
+++ b/components/password_manager/core/browser/sync/password_model_type_controller.cc
@@ -183,15 +183,18 @@
   features_util::ClearAccountStorageSettingsForAllUsers(pref_service_);
 }
 
-void PasswordModelTypeController::OnPrimaryAccountCleared(
-    const CoreAccountInfo& previous_primary_account_info) {
-  // Note: OnPrimaryAccountCleared() basically means that the consent for
-  // Sync-the-feature was revoked. In this case, also clear any possible
-  // matching opt-in for the account-scoped storage, since it'd probably be
-  // surprising to the user if their account passwords still remained after
-  // disabling Sync.
-  features_util::OptOutOfAccountStorageAndClearSettingsForAccount(
-      pref_service_, previous_primary_account_info.gaia);
+void PasswordModelTypeController::OnPrimaryAccountChanged(
+    const signin::PrimaryAccountChangeEvent& event) {
+  if (event.GetEventTypeFor(signin::ConsentLevel::kSync) ==
+      signin::PrimaryAccountChangeEvent::Type::kCleared) {
+    // Note: kCleared event for ConsentLevel::kSync basically means that the
+    // consent for Sync-the-feature was revoked. In this case, also clear any
+    // possible matching opt-in for the account-scoped storage, since it'd
+    // probably be surprising to the user if their account passwords still
+    // remained after disabling Sync.
+    features_util::OptOutOfAccountStorageAndClearSettingsForAccount(
+        pref_service_, event.GetPreviousState().primary_account.gaia);
+  }
 }
 
 void PasswordModelTypeController::OnOptInStateMaybeChanged() {
diff --git a/components/password_manager/core/browser/sync/password_model_type_controller.h b/components/password_manager/core/browser/sync/password_model_type_controller.h
index bc5362b..4ed2ce8 100644
--- a/components/password_manager/core/browser/sync/password_model_type_controller.h
+++ b/components/password_manager/core/browser/sync/password_model_type_controller.h
@@ -59,8 +59,8 @@
       const signin::AccountsInCookieJarInfo& accounts_in_cookie_jar_info,
       const GoogleServiceAuthError& error) override;
   void OnAccountsCookieDeletedByUserAction() override;
-  void OnPrimaryAccountCleared(
-      const CoreAccountInfo& previous_primary_account_info) override;
+  void OnPrimaryAccountChanged(
+      const signin::PrimaryAccountChangeEvent& event) override;
 
  private:
   void OnOptInStateMaybeChanged();
diff --git a/components/payments/content/autofill_payment_app.cc b/components/payments/content/autofill_payment_app.cc
index d4c6f50..2274cc1 100644
--- a/components/payments/content/autofill_payment_app.cc
+++ b/components/payments/content/autofill_payment_app.cc
@@ -119,7 +119,7 @@
 void AutofillPaymentApp::RecordUse() {
   // Record the use of the credit card.
   payment_request_delegate_->GetPersonalDataManager()->RecordUseOf(
-      credit_card_);
+      &credit_card_);
 }
 
 bool AutofillPaymentApp::NeedsInstallation() const {
diff --git a/components/payments/content/payment_request_state.cc b/components/payments/content/payment_request_state.cc
index 392609c..842c5305 100644
--- a/components/payments/content/payment_request_state.cc
+++ b/components/payments/content/payment_request_state.cc
@@ -405,7 +405,7 @@
 void PaymentRequestState::RecordUseStats() {
   if (ShouldShowShippingSection()) {
     DCHECK(selected_shipping_profile_);
-    personal_data_manager_->RecordUseOf(*selected_shipping_profile_);
+    personal_data_manager_->RecordUseOf(selected_shipping_profile_);
   }
 
   if (ShouldShowContactSection()) {
@@ -415,7 +415,7 @@
     // should only be updated once.
     if (!ShouldShowShippingSection() || (selected_shipping_profile_->guid() !=
                                          selected_contact_profile_->guid())) {
-      personal_data_manager_->RecordUseOf(*selected_contact_profile_);
+      personal_data_manager_->RecordUseOf(selected_contact_profile_);
     }
   }
 
diff --git a/components/safe_search_api/DIR_METADATA b/components/safe_search_api/DIR_METADATA
index 9db75de..df2cd975 100644
--- a/components/safe_search_api/DIR_METADATA
+++ b/components/safe_search_api/DIR_METADATA
@@ -1,3 +1,3 @@
 monorail {
-  component: "FamilyLink"
+  component: "FamilyExperiences"
 }
diff --git a/components/services/storage/public/mojom/BUILD.gn b/components/services/storage/public/mojom/BUILD.gn
index 305f12c..7cb4ffc 100644
--- a/components/services/storage/public/mojom/BUILD.gn
+++ b/components/services/storage/public/mojom/BUILD.gn
@@ -7,6 +7,7 @@
 mojom("mojom") {
   sources = [
     "blob_storage_context.mojom",
+    "cache_storage_control.mojom",
     "file_system_access_context.mojom",
     "indexed_db_control.mojom",
     "indexed_db_control_test.mojom",
diff --git a/components/services/storage/public/mojom/cache_storage_control.mojom b/components/services/storage/public/mojom/cache_storage_control.mojom
new file mode 100644
index 0000000..3bec5b0
--- /dev/null
+++ b/components/services/storage/public/mojom/cache_storage_control.mojom
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+module storage.mojom;
+
+import "services/network/public/mojom/cross_origin_embedder_policy.mojom";
+import "third_party/blink/public/mojom/cache_storage/cache_storage.mojom";
+import "url/mojom/origin.mojom";
+
+enum CacheStorageOwner {
+  // Caches that can be accessed by the JS CacheStorage API (developer facing).
+  kCacheAPI,
+
+  // Private cache to store background fetch downloads.
+  kBackgroundFetch,
+};
+
+// Controls the state of CacheStorage within a partition. This is a privileged
+// interface and must not be brokered to untrusted clients.
+//
+// Currently this is consumed and implemented in the browser process, but the
+// implementation will eventually live in the storage service which may run
+// out-of-process.
+interface CacheStorageControl {
+  // Binds a CacheStorage receiver to the CacheStorageControl to access
+  // the cache storage for a particular origin and owner.
+  AddReceiver(
+      network.mojom.CrossOriginEmbedderPolicy policy,
+      pending_remote<network.mojom.CrossOriginEmbedderPolicyReporter>?
+          coep_reporter,
+      url.mojom.Origin origin,
+      CacheStorageOwner owner,
+      pending_receiver<blink.mojom.CacheStorage> receiver);
+};
diff --git a/components/signin/core/browser/chrome_connected_header_helper.cc b/components/signin/core/browser/chrome_connected_header_helper.cc
index 6ea1976..4dde387 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.cc
+++ b/components/signin/core/browser/chrome_connected_header_helper.cc
@@ -58,6 +58,8 @@
 
 }  // namespace
 
+const char kChromeConnectedCookieName[] = "CHROME_CONNECTED";
+
 ChromeConnectedHeaderHelper::ChromeConnectedHeaderHelper(
     AccountConsistencyMethod account_consistency)
     : account_consistency_(account_consistency) {}
diff --git a/components/signin/core/browser/chrome_connected_header_helper.h b/components/signin/core/browser/chrome_connected_header_helper.h
index cf37ab1e..c17dc782 100644
--- a/components/signin/core/browser/chrome_connected_header_helper.h
+++ b/components/signin/core/browser/chrome_connected_header_helper.h
@@ -15,6 +15,12 @@
 
 namespace signin {
 
+// Name of the cookie used by Chrome sign-in to inform GAIA that an
+// authenticating user is already signed in to Chrome. Because it is not
+// possible to intercept headers from iOS WKWebView, Chrome requires this cookie
+// to communicate its signed-in state with GAIA.
+extern const char kChromeConnectedCookieName[];
+
 // SigninHeaderHelper implementation managing the "X-Chrome-Connected" header.
 class ChromeConnectedHeaderHelper : public SigninHeaderHelper {
  public:
diff --git a/components/signin/ios/browser/DEPS b/components/signin/ios/browser/DEPS
index 4f8bc28..5edadf85 100644
--- a/components/signin/ios/browser/DEPS
+++ b/components/signin/ios/browser/DEPS
@@ -9,10 +9,12 @@
 specific_include_rules = {
     "account_consistency_service.mm": [
       "+components/signin/core/browser/account_reconcilor.h",
+      "+components/signin/core/browser/chrome_connected_header_helper.h",
       "+components/signin/core/browser/signin_header_helper.h",
     ],
     "account_consistency_service_unittest.mm": [
       "+components/signin/core/browser/account_reconcilor.h",
       "+components/signin/core/browser/account_reconcilor_delegate.h",
+      "+components/signin/core/browser/chrome_connected_header_helper.h",
     ],
 }
diff --git a/components/signin/ios/browser/account_consistency_service.h b/components/signin/ios/browser/account_consistency_service.h
index 3b0ceef0..d9e2406 100644
--- a/components/signin/ios/browser/account_consistency_service.h
+++ b/components/signin/ios/browser/account_consistency_service.h
@@ -39,11 +39,6 @@
 class AccountConsistencyService : public KeyedService,
                                   public signin::IdentityManager::Observer {
  public:
-  // Name of the cookie that is managed by AccountConsistencyService and is used
-  // to inform Google web properties that the browser is connected and that
-  // Google authentication cookies are managed by |AccountReconcilor|).
-  static const char kChromeConnectedCookieName[];
-
   AccountConsistencyService(
       web::BrowserState* browser_state,
       AccountReconcilor* account_reconcilor,
diff --git a/components/signin/ios/browser/account_consistency_service.mm b/components/signin/ios/browser/account_consistency_service.mm
index 7b1b98e..496fcad6 100644
--- a/components/signin/ios/browser/account_consistency_service.mm
+++ b/components/signin/ios/browser/account_consistency_service.mm
@@ -17,6 +17,7 @@
 #include "components/content_settings/core/browser/cookie_settings.h"
 #include "components/google/core/common/google_util.h"
 #include "components/signin/core/browser/account_reconcilor.h"
+#include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/core/browser/signin_header_helper.h"
 #include "components/signin/ios/browser/features.h"
 #include "components/signin/public/base/account_consistency_method.h"
@@ -355,9 +356,6 @@
   account_consistency_service_->RemoveWebStateHandler(web_state());
 }
 
-const char AccountConsistencyService::kChromeConnectedCookieName[] =
-    "CHROME_CONNECTED";
-
 AccountConsistencyService::AccountConsistencyService(
     web::BrowserState* browser_state,
     AccountReconcilor* account_reconcilor,
@@ -458,7 +456,7 @@
 
   network::mojom::CookieDeletionFilterPtr filter =
       network::mojom::CookieDeletionFilter::New();
-  filter->cookie_name = kChromeConnectedCookieName;
+  filter->cookie_name = signin::kChromeConnectedCookieName;
 
   ++active_cookie_manager_requests_for_testing_;
   cookie_manager->DeleteCookies(
@@ -503,7 +501,7 @@
   std::unique_ptr<net::CanonicalCookie> cookie =
       net::CanonicalCookie::CreateSanitizedCookie(
           url,
-          /*name=*/kChromeConnectedCookieName, cookie_value,
+          /*name=*/signin::kChromeConnectedCookieName, cookie_value,
           /*domain=*/domain,
           /*path=*/std::string(),
           /*creation_time=*/base::Time::Now(),
diff --git a/components/signin/ios/browser/account_consistency_service_unittest.mm b/components/signin/ios/browser/account_consistency_service_unittest.mm
index 385562e..0bff9d4a 100644
--- a/components/signin/ios/browser/account_consistency_service_unittest.mm
+++ b/components/signin/ios/browser/account_consistency_service_unittest.mm
@@ -21,6 +21,7 @@
 #include "components/prefs/pref_service.h"
 #include "components/signin/core/browser/account_reconcilor.h"
 #include "components/signin/core/browser/account_reconcilor_delegate.h"
+#include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "components/signin/ios/browser/features.h"
 #import "components/signin/ios/browser/manage_accounts_delegate.h"
 #include "components/signin/public/base/list_accounts_test_utils.h"
@@ -196,24 +197,21 @@
 
   // Cookie verification APIs.
   void CheckDomainHasChromeConnectedCookie(const std::string& domain) {
-    EXPECT_TRUE(
-        ContainsCookie(GetCookiesInCookieJar(),
-                       AccountConsistencyService::kChromeConnectedCookieName,
-                       GetCookieDomain(domain)));
+    EXPECT_TRUE(ContainsCookie(GetCookiesInCookieJar(),
+                               signin::kChromeConnectedCookieName,
+                               GetCookieDomain(domain)));
   }
 
   void CheckNoChromeConnectedCookieForDomain(const std::string& domain) {
-    EXPECT_FALSE(
-        ContainsCookie(GetCookiesInCookieJar(),
-                       AccountConsistencyService::kChromeConnectedCookieName,
-                       GetCookieDomain(domain)));
+    EXPECT_FALSE(ContainsCookie(GetCookiesInCookieJar(),
+                                signin::kChromeConnectedCookieName,
+                                GetCookieDomain(domain)));
   }
 
   void CheckNoChromeConnectedCookies() {
-    EXPECT_FALSE(
-        ContainsCookie(GetCookiesInCookieJar(),
-                       AccountConsistencyService::kChromeConnectedCookieName,
-                       /*domain=*/std::string()));
+    EXPECT_FALSE(ContainsCookie(GetCookiesInCookieJar(),
+                                signin::kChromeConnectedCookieName,
+                                /*domain=*/std::string()));
   }
 
   // Verifies the time that the Gaia cookie was last updated for google.com.
diff --git a/components/signin/public/identity_manager/identity_manager.cc b/components/signin/public/identity_manager/identity_manager.cc
index 0f64d03..97b10b9 100644
--- a/components/signin/public/identity_manager/identity_manager.cc
+++ b/components/signin/public/identity_manager/identity_manager.cc
@@ -490,14 +490,6 @@
     case PrimaryAccountChangeEvent::Type::kNone:
       break;
   }
-  switch (event_details.GetEventTypeFor(ConsentLevel::kNotRequired)) {
-    case PrimaryAccountChangeEvent::Type::kSet:
-    case PrimaryAccountChangeEvent::Type::kCleared:
-      FireUnconsentedPrimaryAccountChanged(event_details);
-      break;
-    case PrimaryAccountChangeEvent::Type::kNone:
-      break;
-  }
 
   for (auto& observer : observer_list_)
     observer.OnPrimaryAccountChanged(event_details);
@@ -528,15 +520,6 @@
   }
 }
 
-void IdentityManager::FireUnconsentedPrimaryAccountChanged(
-    const PrimaryAccountChangeEvent& event_details) {
-  const CoreAccountInfo& account_info =
-      event_details.GetCurrentState().primary_account;
-  for (auto& observer : observer_list_) {
-    observer.OnUnconsentedPrimaryAccountChanged(account_info);
-  }
-}
-
 void IdentityManager::FirePrimaryAccountCleared(
     const PrimaryAccountChangeEvent& event_details) {
   const CoreAccountInfo& account_info =
diff --git a/components/signin/public/identity_manager/identity_manager.h b/components/signin/public/identity_manager/identity_manager.h
index 57317ff3..37bec4f 100644
--- a/components/signin/public/identity_manager/identity_manager.h
+++ b/components/signin/public/identity_manager/identity_manager.h
@@ -101,22 +101,6 @@
     // General observers should use |OnPrimaryAccountChanged|.
     virtual void AfterSyncPrimaryAccountCleared() {}
 
-    // When the unconsented primary account (see ./README.md) of the user
-    // changes, this callback gets called with the new account as
-    // |unconsented_primary_account_info|. If after the change, there is no
-    // unconsented primary account, |unconsented_primary_account_info| is empty.
-    // This does not get called when the unconsented account becomes consented
-    // (as the same account was unconsented before so there is no change). In
-    // all other changes (the unconsented primary account gets added, changed or
-    // removed), this notification is called only once. Note: we do not use the
-    // {Set, Cleared} notifications like for the primary account above because
-    // the identity manager does not have clear guarantees that that account
-    // cannot change in one atomic operation (without getting cleared in the
-    // mean-time).
-    // DEPRECATED: Use OnPrimaryAccountChanged() instead.
-    virtual void OnUnconsentedPrimaryAccountChanged(
-        const CoreAccountInfo& unconsented_primary_account_info) {}
-
     // Called when a new refresh token is associated with |account_info|.
     // NOTE: On a signin event, the ordering of this callback wrt the
     // OnPrimaryAccountSet() callback is undefined. If you as a client are
@@ -679,8 +663,6 @@
   // Fire the deprecated observer methods for settings and clearing the primary
   // account.
   void FirePrimaryAccountSet(const PrimaryAccountChangeEvent& event_details);
-  void FireUnconsentedPrimaryAccountChanged(
-      const PrimaryAccountChangeEvent& event_details);
   void FirePrimaryAccountCleared(
       const PrimaryAccountChangeEvent& event_details);
 
diff --git a/components/signin/public/identity_manager/identity_manager_unittest.cc b/components/signin/public/identity_manager/identity_manager_unittest.cc
index 2170b44..a50b822 100644
--- a/components/signin/public/identity_manager/identity_manager_unittest.cc
+++ b/components/signin/public/identity_manager/identity_manager_unittest.cc
@@ -561,22 +561,23 @@
   ClearPrimaryAccount(identity_manager());
 
   SetPrimaryAccount(identity_manager(), kTestEmail);
+  auto event = identity_manager_observer()->GetPrimaryAccountChangedEvent();
+  EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+            event.GetEventTypeFor(ConsentLevel::kSync));
+  EXPECT_EQ(PrimaryAccountChangeEvent::Type::kSet,
+            event.GetEventTypeFor(ConsentLevel::kNotRequired));
 
   CoreAccountInfo primary_account_from_set_callback =
-      identity_manager_observer()->PrimaryAccountFromSetCallback();
+      event.GetCurrentState().primary_account;
   EXPECT_EQ(kTestGaiaId, primary_account_from_set_callback.gaia);
   EXPECT_EQ(kTestEmail, primary_account_from_set_callback.email);
 
-  // Primary account is by definition also unconsented primary account.
-  EXPECT_EQ(
-      primary_account_from_set_callback,
-      identity_manager_observer()->UnconsentedPrimaryAccountFromCallback());
-
   CoreAccountInfo primary_account_info =
       identity_manager()->GetPrimaryAccountInfo();
   EXPECT_EQ(kTestGaiaId, primary_account_info.gaia);
   EXPECT_EQ(kTestEmail, primary_account_info.email);
 
+  // Primary account is by definition also unconsented primary account.
   EXPECT_EQ(primary_account_info, identity_manager()->GetPrimaryAccountInfo(
                                       ConsentLevel::kNotRequired));
 
@@ -599,15 +600,20 @@
   // Sign the user out and check that the IdentityManager responds
   // appropriately.
   ClearPrimaryAccount(identity_manager());
+  auto event = identity_manager_observer()->GetPrimaryAccountChangedEvent();
+  EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+            event.GetEventTypeFor(ConsentLevel::kSync));
+  EXPECT_EQ(PrimaryAccountChangeEvent::Type::kCleared,
+            event.GetEventTypeFor(ConsentLevel::kNotRequired));
 
   CoreAccountInfo primary_account_from_cleared_callback =
-      identity_manager_observer()->PrimaryAccountFromClearedCallback();
+      event.GetPreviousState().primary_account;
   EXPECT_EQ(kTestGaiaId, primary_account_from_cleared_callback.gaia);
   EXPECT_EQ(kTestEmail, primary_account_from_cleared_callback.email);
 
   // After the sign-out, there is no unconsented primary account.
-  EXPECT_TRUE(identity_manager_observer()
-                  ->UnconsentedPrimaryAccountFromCallback()
+  EXPECT_TRUE(identity_manager()
+                  ->GetPrimaryAccountInfo(ConsentLevel::kNotRequired)
                   .IsEmpty());
 
   CoreAccountInfo primary_account_info =
@@ -675,8 +681,9 @@
   EXPECT_FALSE(
       identity_manager()->HasPrimaryAccount(ConsentLevel::kNotRequired));
   EXPECT_FALSE(identity_manager_observer()
-                   ->PrimaryAccountFromClearedCallback()
-                   .IsEmpty());
+                   ->GetPrimaryAccountChangedEvent()
+                   .GetPreviousState()
+                   .primary_account.IsEmpty());
 #endif
 }
 
diff --git a/components/signin/public/identity_manager/identity_test_utils.cc b/components/signin/public/identity_manager/identity_test_utils.cc
index 588ff69..9820d33a 100644
--- a/components/signin/public/identity_manager/identity_test_utils.cc
+++ b/components/signin/public/identity_manager/identity_test_utils.cc
@@ -198,7 +198,14 @@
   DCHECK(identity_manager->GetPrimaryAccountMutator());
   base::RunLoop run_loop;
   TestIdentityManagerObserver signout_observer(identity_manager);
-  signout_observer.SetOnPrimaryAccountClearedCallback(run_loop.QuitClosure());
+  signout_observer.SetOnPrimaryAccountChangedCallback(base::BindOnce(
+      [](base::RunLoop* run_loop, PrimaryAccountChangeEvent event) {
+        if (event.GetEventTypeFor(ConsentLevel::kSync) ==
+            PrimaryAccountChangeEvent::Type::kCleared) {
+          run_loop->Quit();
+        }
+      },
+      &run_loop));
   identity_manager->GetPrimaryAccountMutator()->RevokeSyncConsent(
       signin_metrics::SIGNOUT_TEST,
       signin_metrics::SignoutDelete::IGNORE_METRIC);
@@ -220,7 +227,14 @@
       identity_manager->HasPrimaryAccount(ConsentLevel::kSync);
   base::RunLoop run_loop;
   TestIdentityManagerObserver signout_observer(identity_manager);
-  signout_observer.SetOnPrimaryAccountClearedCallback(run_loop.QuitClosure());
+  signout_observer.SetOnPrimaryAccountChangedCallback(base::BindOnce(
+      [](base::RunLoop* run_loop, PrimaryAccountChangeEvent event) {
+        if (event.GetEventTypeFor(ConsentLevel::kNotRequired) ==
+            PrimaryAccountChangeEvent::Type::kCleared) {
+          run_loop->Quit();
+        }
+      },
+      &run_loop));
   identity_manager->GetPrimaryAccountMutator()->ClearPrimaryAccount(
       signin_metrics::SIGNOUT_TEST,
       signin_metrics::SignoutDelete::IGNORE_METRIC);
diff --git a/components/signin/public/identity_manager/test_identity_manager_observer.cc b/components/signin/public/identity_manager/test_identity_manager_observer.cc
index 6fcdd672..cd0087f 100644
--- a/components/signin/public/identity_manager/test_identity_manager_observer.cc
+++ b/components/signin/public/identity_manager/test_identity_manager_observer.cc
@@ -20,34 +20,14 @@
   identity_manager_->RemoveObserver(this);
 }
 
-void TestIdentityManagerObserver::SetOnPrimaryAccountSetCallback(
-    base::OnceClosure callback) {
-  on_primary_account_set_callback_ = std::move(callback);
+void TestIdentityManagerObserver::SetOnPrimaryAccountChangedCallback(
+    PrimaryAccountChangedCallback callback) {
+  on_primary_account_changed_callback_ = std::move(callback);
 }
 
-const CoreAccountInfo&
-TestIdentityManagerObserver::PrimaryAccountFromSetCallback() {
-  return primary_account_from_set_callback_;
-}
-
-void TestIdentityManagerObserver::SetOnPrimaryAccountClearedCallback(
-    base::OnceClosure callback) {
-  on_primary_account_cleared_callback_ = std::move(callback);
-}
-
-const CoreAccountInfo&
-TestIdentityManagerObserver::PrimaryAccountFromClearedCallback() {
-  return primary_account_from_cleared_callback_;
-}
-
-void TestIdentityManagerObserver::SetOnUnconsentedPrimaryAccountChangedCallback(
-    base::OnceClosure callback) {
-  on_unconsented_primary_account_callback_ = std::move(callback);
-}
-
-const CoreAccountInfo&
-TestIdentityManagerObserver::UnconsentedPrimaryAccountFromCallback() {
-  return unconsented_primary_account_from_callback_;
+const PrimaryAccountChangeEvent&
+TestIdentityManagerObserver::GetPrimaryAccountChangedEvent() {
+  return on_primary_account_changed_event_;
 }
 
 void TestIdentityManagerObserver::SetOnRefreshTokenUpdatedCallback(
@@ -135,36 +115,9 @@
 // IdentityManager::Observer:
 void TestIdentityManagerObserver::OnPrimaryAccountChanged(
     const PrimaryAccountChangeEvent& event) {
-  // TODO(https://crbug.com/1158855): Refactor this test observer to
-  // have a single on_primary_account_changed_callback_  and a single
-  // on_primary_account_changed_event_.
-  switch (event.GetEventTypeFor(ConsentLevel::kNotRequired)) {
-    case PrimaryAccountChangeEvent::Type::kSet:
-    case PrimaryAccountChangeEvent::Type::kCleared:
-      unconsented_primary_account_from_callback_ =
-          event.GetCurrentState().primary_account;
-      if (on_unconsented_primary_account_callback_)
-        std::move(on_unconsented_primary_account_callback_).Run();
-      break;
-    case PrimaryAccountChangeEvent::Type::kNone:
-      break;
-  }
-  switch (event.GetEventTypeFor(ConsentLevel::kSync)) {
-    case PrimaryAccountChangeEvent::Type::kSet:
-      primary_account_from_set_callback_ =
-          event.GetCurrentState().primary_account;
-      if (on_primary_account_set_callback_)
-        std::move(on_primary_account_set_callback_).Run();
-      break;
-    case PrimaryAccountChangeEvent::Type::kCleared:
-      primary_account_from_cleared_callback_ =
-          event.GetPreviousState().primary_account;
-      if (on_primary_account_cleared_callback_)
-        std::move(on_primary_account_cleared_callback_).Run();
-      break;
-    case PrimaryAccountChangeEvent::Type::kNone:
-      break;
-  }
+  on_primary_account_changed_event_ = event;
+  if (on_primary_account_changed_callback_)
+    std::move(on_primary_account_changed_callback_).Run(event);
 }
 
 void TestIdentityManagerObserver::OnRefreshTokenUpdatedForAccount(
diff --git a/components/signin/public/identity_manager/test_identity_manager_observer.h b/components/signin/public/identity_manager/test_identity_manager_observer.h
index 91479fe..59064de 100644
--- a/components/signin/public/identity_manager/test_identity_manager_observer.h
+++ b/components/signin/public/identity_manager/test_identity_manager_observer.h
@@ -20,18 +20,15 @@
 // the potential results and/or errors returned after such events have occurred.
 class TestIdentityManagerObserver : IdentityManager::Observer {
  public:
+  using PrimaryAccountChangedCallback =
+      base::OnceCallback<void(PrimaryAccountChangeEvent)>;
+
   explicit TestIdentityManagerObserver(IdentityManager* identity_manager);
   ~TestIdentityManagerObserver() override;
 
-  void SetOnPrimaryAccountSetCallback(base::OnceClosure callback);
-  const CoreAccountInfo& PrimaryAccountFromSetCallback();
-
-  void SetOnPrimaryAccountClearedCallback(base::OnceClosure callback);
-  const CoreAccountInfo& PrimaryAccountFromClearedCallback();
-
-  void SetOnUnconsentedPrimaryAccountChangedCallback(
-      base::OnceClosure callback);
-  const CoreAccountInfo& UnconsentedPrimaryAccountFromCallback();
+  void SetOnPrimaryAccountChangedCallback(
+      PrimaryAccountChangedCallback callback);
+  const PrimaryAccountChangeEvent& GetPrimaryAccountChangedEvent();
 
   void SetOnRefreshTokenUpdatedCallback(base::OnceClosure callback);
   const CoreAccountInfo& AccountFromRefreshTokenUpdatedCallback();
@@ -88,14 +85,8 @@
 
   IdentityManager* identity_manager_;
 
-  base::OnceClosure on_primary_account_set_callback_;
-  CoreAccountInfo primary_account_from_set_callback_;
-
-  base::OnceClosure on_primary_account_cleared_callback_;
-  CoreAccountInfo primary_account_from_cleared_callback_;
-
-  base::OnceClosure on_unconsented_primary_account_callback_;
-  CoreAccountInfo unconsented_primary_account_from_callback_;
+  PrimaryAccountChangedCallback on_primary_account_changed_callback_;
+  PrimaryAccountChangeEvent on_primary_account_changed_event_;
 
   base::OnceClosure on_refresh_token_updated_callback_;
   CoreAccountInfo account_from_refresh_token_updated_callback_;
diff --git a/components/speech/upstream_loader.cc b/components/speech/upstream_loader.cc
index 9a88c14b..0f00733 100644
--- a/components/speech/upstream_loader.cc
+++ b/components/speech/upstream_loader.cc
@@ -19,8 +19,11 @@
   // Attach a chunked upload body.
   mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter> data_remote;
   receiver_set_.Add(this, data_remote.InitWithNewPipeAndPassReceiver());
-  resource_request->request_body = new network::ResourceRequestBody();
-  resource_request->request_body->SetToChunkedDataPipe(std::move(data_remote));
+  resource_request->request_body =
+      base::MakeRefCounted<network::ResourceRequestBody>();
+  resource_request->request_body->SetToChunkedDataPipe(
+      std::move(data_remote),
+      network::ResourceRequestBody::ReadOnlyOnce(false));
   simple_url_loader_ = network::SimpleURLLoader::Create(
       std::move(resource_request), upstream_traffic_annotation);
   simple_url_loader_->DownloadToStringOfUnboundedSizeUntilCrashAndDie(
diff --git a/components/subresource_filter/core/browser/subresource_filter_features.h b/components/subresource_filter/core/browser/subresource_filter_features.h
index 61a9f5ef..9cb949a 100644
--- a/components/subresource_filter/core/browser/subresource_filter_features.h
+++ b/components/subresource_filter/core/browser/subresource_filter_features.h
@@ -180,7 +180,7 @@
 
 // Feature and variation parameter definitions -------------------------------
 
-// The master toggle to enable/disable the Safe Browsing Subresource Filter.
+// The primary toggle to enable/disable the Safe Browsing Subresource Filter.
 extern const base::Feature kSafeBrowsingSubresourceFilter;
 
 // Enables the blocking of ads on sites that are abusive.
diff --git a/components/subresource_filter/core/common/indexed_ruleset.cc b/components/subresource_filter/core/common/indexed_ruleset.cc
index c30209b..2a2efee9 100644
--- a/components/subresource_filter/core/common/indexed_ruleset.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset.cc
@@ -74,7 +74,7 @@
   if (!offset.o)
     return false;
 
-  if (rule.semantics() == proto::RULE_SEMANTICS_BLACKLIST) {
+  if (rule.semantics() == proto::RULE_SEMANTICS_BLOCKLIST) {
     blocklist_.IndexUrlRule(offset);
   } else {
     const auto* flat_rule = flatbuffers::GetTemporaryPointer(builder_, offset);
@@ -150,7 +150,7 @@
   if (!rule)
     return LoadPolicy::ALLOW;
 
-  return rule->options() & url_pattern_index::flat::OptionFlag_IS_WHITELIST
+  return rule->options() & url_pattern_index::flat::OptionFlag_IS_ALLOWLIST
              ? LoadPolicy::EXPLICITLY_ALLOW
              : LoadPolicy::DISALLOW;
 }
diff --git a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
index cc4bc72..858efaf 100644
--- a/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
+++ b/components/subresource_filter/core/common/indexed_ruleset_unittest.cc
@@ -72,14 +72,14 @@
 
   bool AddSimpleAllowlistRule(base::StringPiece url_pattern) {
     auto rule = MakeUrlRule(UrlPattern(url_pattern, testing::kSubstring));
-    rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+    rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
     return AddUrlRule(rule);
   }
 
   bool AddSimpleAllowlistRule(base::StringPiece url_pattern,
                               int32_t activation_types) {
     auto rule = MakeUrlRule(UrlPattern(url_pattern, testing::kSubstring));
-    rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+    rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
     rule.clear_element_types();
     rule.set_activation_types(activation_types);
     return AddUrlRule(rule);
diff --git a/components/subresource_filter/core/common/test_ruleset_utils.cc b/components/subresource_filter/core/common/test_ruleset_utils.cc
index ddf32f0..2e13d78 100644
--- a/components/subresource_filter/core/common/test_ruleset_utils.cc
+++ b/components/subresource_filter/core/common/test_ruleset_utils.cc
@@ -14,7 +14,7 @@
 proto::UrlRule CreateSubstringRule(base::StringPiece substring) {
   proto::UrlRule rule;
 
-  rule.set_semantics(proto::RULE_SEMANTICS_BLACKLIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_BLOCKLIST);
   rule.set_source_type(proto::SOURCE_TYPE_ANY);
   rule.set_element_types(proto::ELEMENT_TYPE_ALL);
   rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
@@ -27,7 +27,7 @@
 
 proto::UrlRule CreateSuffixRule(base::StringPiece suffix) {
   proto::UrlRule rule;
-  rule.set_semantics(proto::RULE_SEMANTICS_BLACKLIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_BLOCKLIST);
   rule.set_source_type(proto::SOURCE_TYPE_ANY);
   rule.set_element_types(proto::ELEMENT_TYPE_ALL);
   rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
@@ -39,7 +39,7 @@
 
 proto::UrlRule CreateAllowlistSuffixRule(base::StringPiece suffix) {
   proto::UrlRule rule;
-  rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
   rule.set_source_type(proto::SOURCE_TYPE_ANY);
   rule.set_element_types(proto::ELEMENT_TYPE_ALL);
   rule.set_url_pattern_type(proto::URL_PATTERN_TYPE_SUBSTRING);
@@ -54,7 +54,7 @@
     int32_t activation_types,
     std::vector<std::string> domains) {
   proto::UrlRule rule;
-  rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
   rule.set_source_type(proto::SOURCE_TYPE_ANY);
   rule.set_activation_types(activation_types);
 
diff --git a/components/subresource_filter/core/common/unindexed_ruleset_unittest.cc b/components/subresource_filter/core/common/unindexed_ruleset_unittest.cc
index 7d68fa2..ff7c95d 100644
--- a/components/subresource_filter/core/common/unindexed_ruleset_unittest.cc
+++ b/components/subresource_filter/core/common/unindexed_ruleset_unittest.cc
@@ -55,7 +55,7 @@
                   bool is_allowlist = false) {
     auto rule = testing::MakeUrlRule(url_pattern);
     if (is_allowlist)
-      rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+      rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
     rule.set_source_type(source_type);
 
     url_rules_.push_back(rule);
diff --git a/components/subresource_filter/tools/filter_tool.cc b/components/subresource_filter/tools/filter_tool.cc
index ac1f8e7..2d56b66 100644
--- a/components/subresource_filter/tools/filter_tool.cc
+++ b/components/subresource_filter/tools/filter_tool.cc
@@ -144,7 +144,7 @@
                           ParseRequestUrl(url), ParseType(type));
 
   *blocked = rule && !(rule->options() &
-                       url_pattern_index::flat::OptionFlag_IS_WHITELIST);
+                       url_pattern_index::flat::OptionFlag_IS_ALLOWLIST);
   return rule;
 }
 
diff --git a/components/subresource_filter/tools/rule_parser/rule.cc b/components/subresource_filter/tools/rule_parser/rule.cc
index 0b9fa918..9882dce 100644
--- a/components/subresource_filter/tools/rule_parser/rule.cc
+++ b/components/subresource_filter/tools/rule_parser/rule.cc
@@ -81,8 +81,8 @@
   url_pattern_index::proto::UrlRule result;
 
   result.set_semantics(
-      is_allowlist ? url_pattern_index::proto::RULE_SEMANTICS_WHITELIST
-                   : url_pattern_index::proto::RULE_SEMANTICS_BLACKLIST);
+      is_allowlist ? url_pattern_index::proto::RULE_SEMANTICS_ALLOWLIST
+                   : url_pattern_index::proto::RULE_SEMANTICS_BLOCKLIST);
   switch (is_third_party) {
     case TriState::DONT_CARE:
       result.set_source_type(url_pattern_index::proto::SOURCE_TYPE_ANY);
@@ -151,8 +151,8 @@
   url_pattern_index::proto::CssRule result;
 
   result.set_semantics(
-      is_allowlist ? url_pattern_index::proto::RULE_SEMANTICS_WHITELIST
-                   : url_pattern_index::proto::RULE_SEMANTICS_BLACKLIST);
+      is_allowlist ? url_pattern_index::proto::RULE_SEMANTICS_ALLOWLIST
+                   : url_pattern_index::proto::RULE_SEMANTICS_BLOCKLIST);
 
   for (const std::string& domain : domains) {
     url_pattern_index::proto::DomainListItem* list_item = result.add_domains();
@@ -206,9 +206,9 @@
   std::string result;
 
   switch (rule.semantics()) {
-    case url_pattern_index::proto::RULE_SEMANTICS_BLACKLIST:
+    case url_pattern_index::proto::RULE_SEMANTICS_BLOCKLIST:
       break;
-    case url_pattern_index::proto::RULE_SEMANTICS_WHITELIST:
+    case url_pattern_index::proto::RULE_SEMANTICS_ALLOWLIST:
       result += "@@";
       break;
     default:
@@ -327,10 +327,10 @@
     DomainListJoin(rule.domains(), ',', &result);
 
   switch (rule.semantics()) {
-    case url_pattern_index::proto::RULE_SEMANTICS_BLACKLIST:
+    case url_pattern_index::proto::RULE_SEMANTICS_BLOCKLIST:
       result += "##";
       break;
-    case url_pattern_index::proto::RULE_SEMANTICS_WHITELIST:
+    case url_pattern_index::proto::RULE_SEMANTICS_ALLOWLIST:
       result += "#@#";
       break;
     default:
diff --git a/components/sync/driver/active_devices_provider.h b/components/sync/driver/active_devices_provider.h
index 3aa07080..992342b 100644
--- a/components/sync/driver/active_devices_provider.h
+++ b/components/sync/driver/active_devices_provider.h
@@ -5,11 +5,14 @@
 #ifndef COMPONENTS_SYNC_DRIVER_ACTIVE_DEVICES_PROVIDER_H_
 #define COMPONENTS_SYNC_DRIVER_ACTIVE_DEVICES_PROVIDER_H_
 
+#include <string>
+#include <vector>
+
 #include "base/callback.h"
 
 namespace syncer {
 
-// An interface helping to get the number of active devices. Devices are
+// An interface helping to get the information about active devices. Devices are
 // considered active if there are DeviceInfo entries that are (typically) less
 // than one day old (with a little margin around half an hour).
 class ActiveDevicesProvider {
@@ -22,6 +25,12 @@
   // known yet (e.g. data types are not configured).
   virtual size_t CountActiveDevicesIfAvailable() = 0;
 
+  // Returns a list with all remote FCM registration tokens known to the current
+  // device. If |local_cache_guid| is not empty, then the corresponding device
+  // will be filtered out.
+  virtual std::vector<std::string> CollectFCMRegistrationTokensForInvalidations(
+      const std::string& local_cache_guid) = 0;
+
   // The |callback| will be called on each change in device infos. It might be
   // called multiple times with the same number of active devices. The
   // |callback| must be cleared before this object is destroyed.
diff --git a/components/sync/driver/glue/sync_engine_backend.cc b/components/sync/driver/glue/sync_engine_backend.cc
index a8d46f9..36930e1 100644
--- a/components/sync/driver/glue/sync_engine_backend.cc
+++ b/components/sync/driver/glue/sync_engine_backend.cc
@@ -527,12 +527,16 @@
   }
 }
 
-void SyncEngineBackend::DoOnActiveDevicesChanged(size_t active_devices) {
+void SyncEngineBackend::DoOnActiveDevicesChanged(
+    size_t active_devices,
+    std::vector<std::string> fcm_registration_tokens) {
   // If |active_devices| is 0, then current client doesn't know if there are any
   // other devices. It's safer to consider that there are some other active
   // devices.
   const bool single_client = active_devices == 1;
   sync_manager_->UpdateSingleClientStatus(single_client);
+  sync_manager_->UpdateActiveDeviceFCMRegistrationTokens(
+      std::move(fcm_registration_tokens));
 }
 
 void SyncEngineBackend::GetNigoriNodeForDebugging(AllNodesCallback callback) {
diff --git a/components/sync/driver/glue/sync_engine_backend.h b/components/sync/driver/glue/sync_engine_backend.h
index a51d1a4..65bfc36 100644
--- a/components/sync/driver/glue/sync_engine_backend.h
+++ b/components/sync/driver/glue/sync_engine_backend.h
@@ -154,8 +154,12 @@
   bool HasUnsyncedItemsForTest() const;
 
   // Called on each device infos change and might be called more than once with
-  // the same |active_devices|.
-  void DoOnActiveDevicesChanged(size_t active_devices);
+  // the same |active_devices|. |fcm_registration_tokens| contains a list of
+  // tokens for all known active devices (if available and excluding the local
+  // device if reflections are disabled).
+  void DoOnActiveDevicesChanged(
+      size_t active_devices,
+      std::vector<std::string> fcm_registration_tokens);
 
  private:
   friend class base::RefCountedThreadSafe<SyncEngineBackend>;
diff --git a/components/sync/driver/glue/sync_engine_impl.cc b/components/sync/driver/glue/sync_engine_impl.cc
index 4aecd1f..e422d437 100644
--- a/components/sync/driver/glue/sync_engine_impl.cc
+++ b/components/sync/driver/glue/sync_engine_impl.cc
@@ -18,6 +18,7 @@
 #include "components/invalidation/public/topic_invalidation_map.h"
 #include "components/sync/base/bind_to_task_runner.h"
 #include "components/sync/base/invalidation_helper.h"
+#include "components/sync/base/sync_base_switches.h"
 #include "components/sync/base/sync_prefs.h"
 #include "components/sync/driver/active_devices_provider.h"
 #include "components/sync/driver/glue/sync_engine_backend.h"
@@ -459,11 +460,19 @@
 
 void SyncEngineImpl::OnActiveDevicesChanged() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  std::string local_cache_guid;
+  if (!base::FeatureList::IsEnabled(switches::kSyncE2ELatencyMeasurement)) {
+    // End-to-end latency measurement relies on reflection, so if this is
+    // enabled, don't filter out the local device.
+    local_cache_guid = cached_status_.sync_id;
+  }
   sync_task_runner_->PostTask(
       FROM_HERE,
-      base::BindOnce(
-          &SyncEngineBackend::DoOnActiveDevicesChanged, backend_,
-          active_devices_provider_->CountActiveDevicesIfAvailable()));
+      base::BindOnce(&SyncEngineBackend::DoOnActiveDevicesChanged, backend_,
+                     active_devices_provider_->CountActiveDevicesIfAvailable(),
+                     active_devices_provider_
+                         ->CollectFCMRegistrationTokensForInvalidations(
+                             local_cache_guid)));
 }
 
 }  // namespace syncer
diff --git a/components/sync/driver/glue/sync_engine_impl_unittest.cc b/components/sync/driver/glue/sync_engine_impl_unittest.cc
index e40c6a09..de46d76 100644
--- a/components/sync/driver/glue/sync_engine_impl_unittest.cc
+++ b/components/sync/driver/glue/sync_engine_impl_unittest.cc
@@ -182,6 +182,10 @@
               SetActiveDevicesChangedCallback,
               (ActiveDevicesProvider::ActiveDevicesChangedCallback),
               (override));
+  MOCK_METHOD(std::vector<std::string>,
+              CollectFCMRegistrationTokensForInvalidations,
+              (const std::string&),
+              (override));
 };
 
 std::unique_ptr<HttpPostProviderFactory> CreateHttpBridgeFactory() {
diff --git a/components/sync/engine/sync_manager.h b/components/sync/engine/sync_manager.h
index 4f21bb8..e944f33 100644
--- a/components/sync/engine/sync_manager.h
+++ b/components/sync/engine/sync_manager.h
@@ -243,6 +243,10 @@
 
   // Notifies SyncManager that there are no other known active devices.
   virtual void UpdateSingleClientStatus(bool single_client) = 0;
+
+  // Updates the list of known active device FCM registration tokens.
+  virtual void UpdateActiveDeviceFCMRegistrationTokens(
+      std::vector<std::string> fcm_registration_tokens) = 0;
 };
 
 }  // namespace syncer
diff --git a/components/sync/engine_impl/commit.cc b/components/sync/engine_impl/commit.cc
index 97294fe0..b1dddd9 100644
--- a/components/sync/engine_impl/commit.cc
+++ b/components/sync/engine_impl/commit.cc
@@ -86,14 +86,16 @@
 Commit::~Commit() = default;
 
 // static
-std::unique_ptr<Commit> Commit::Init(ModelTypeSet enabled_types,
-                                     size_t max_entries,
-                                     const std::string& account_name,
-                                     const std::string& cache_guid,
-                                     bool cookie_jar_mismatch,
-                                     bool single_client,
-                                     CommitProcessor* commit_processor,
-                                     ExtensionsActivity* extensions_activity) {
+std::unique_ptr<Commit> Commit::Init(
+    ModelTypeSet enabled_types,
+    size_t max_entries,
+    const std::string& account_name,
+    const std::string& cache_guid,
+    bool cookie_jar_mismatch,
+    bool single_client,
+    const std::vector<std::string>& fcm_registration_tokens,
+    CommitProcessor* commit_processor,
+    ExtensionsActivity* extensions_activity) {
   // Gather per-type contributions.
   ContributionMap contributions =
       commit_processor->GatherCommitContributions(max_entries);
@@ -124,7 +126,8 @@
 
   // Set the client config params.
   commit_util::AddClientConfigParamsToMessage(
-      enabled_types, cookie_jar_mismatch, single_client, commit_message);
+      enabled_types, cookie_jar_mismatch, single_client,
+      fcm_registration_tokens, commit_message);
 
   // Finally, serialize all our contributions.
   for (const auto& contribution : contributions) {
diff --git a/components/sync/engine_impl/commit.h b/components/sync/engine_impl/commit.h
index 8478310..138397c8 100644
--- a/components/sync/engine_impl/commit.h
+++ b/components/sync/engine_impl/commit.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 #include <string>
+#include <vector>
 
 #include "base/macros.h"
 #include "components/sync/base/extensions_activity.h"
@@ -45,14 +46,16 @@
   ~Commit();
 
   // |extensions_activity| may be null.
-  static std::unique_ptr<Commit> Init(ModelTypeSet enabled_types,
-                                      size_t max_entries,
-                                      const std::string& account_name,
-                                      const std::string& cache_guid,
-                                      bool cookie_jar_mismatch,
-                                      bool single_client,
-                                      CommitProcessor* commit_processor,
-                                      ExtensionsActivity* extensions_activity);
+  static std::unique_ptr<Commit> Init(
+      ModelTypeSet enabled_types,
+      size_t max_entries,
+      const std::string& account_name,
+      const std::string& cache_guid,
+      bool cookie_jar_mismatch,
+      bool single_client,
+      const std::vector<std::string>& fcm_registration_tokens,
+      CommitProcessor* commit_processor,
+      ExtensionsActivity* extensions_activity);
 
   // |extensions_activity| may be null.
   SyncerError PostAndProcessResponse(NudgeTracker* nudge_tracker,
diff --git a/components/sync/engine_impl/commit_util.cc b/components/sync/engine_impl/commit_util.cc
index faf4cca..6dc9a578 100644
--- a/components/sync/engine_impl/commit_util.cc
+++ b/components/sync/engine_impl/commit_util.cc
@@ -32,10 +32,12 @@
   }
 }
 
-void AddClientConfigParamsToMessage(ModelTypeSet enabled_types,
-                                    bool cookie_jar_mismatch,
-                                    bool single_client,
-                                    sync_pb::CommitMessage* message) {
+void AddClientConfigParamsToMessage(
+    ModelTypeSet enabled_types,
+    bool cookie_jar_mismatch,
+    bool single_client,
+    const std::vector<std::string>& fcm_registration_tokens,
+    sync_pb::CommitMessage* message) {
   sync_pb::ClientConfigParams* config_params = message->mutable_config_params();
   for (ModelType type : enabled_types) {
     if (ProxyTypes().Has(type))
@@ -46,6 +48,9 @@
   config_params->set_tabs_datatype_enabled(enabled_types.Has(PROXY_TABS));
   config_params->set_cookie_jar_mismatch(cookie_jar_mismatch);
   config_params->set_single_client(single_client);
+  for (const std::string& token : fcm_registration_tokens) {
+    *config_params->add_devices_fcm_registration_tokens() = token;
+  }
 }
 
 }  // namespace commit_util
diff --git a/components/sync/engine_impl/commit_util.h b/components/sync/engine_impl/commit_util.h
index bb00847..ba6aa86 100644
--- a/components/sync/engine_impl/commit_util.h
+++ b/components/sync/engine_impl/commit_util.h
@@ -6,6 +6,8 @@
 #define COMPONENTS_SYNC_ENGINE_IMPL_COMMIT_UTIL_H_
 
 #include <stdint.h>
+#include <string>
+#include <vector>
 
 #include "components/sync/base/extensions_activity.h"
 #include "components/sync/base/model_type.h"
@@ -26,10 +28,12 @@
     sync_pb::CommitMessage* message);
 
 // Fills the config_params field of |message|.
-void AddClientConfigParamsToMessage(ModelTypeSet enabled_types,
-                                    bool cookie_jar_mismatch,
-                                    bool single_client,
-                                    sync_pb::CommitMessage* message);
+void AddClientConfigParamsToMessage(
+    ModelTypeSet enabled_types,
+    bool cookie_jar_mismatch,
+    bool single_client,
+    const std::vector<std::string>& fcm_registration_tokens,
+    sync_pb::CommitMessage* message);
 
 }  // namespace commit_util
 
diff --git a/components/sync/engine_impl/cycle/sync_cycle_context.h b/components/sync/engine_impl/cycle/sync_cycle_context.h
index bc7b81e..f4b734e 100644
--- a/components/sync/engine_impl/cycle/sync_cycle_context.h
+++ b/components/sync/engine_impl/cycle/sync_cycle_context.h
@@ -8,6 +8,7 @@
 #include <stdint.h>
 
 #include <string>
+#include <utility>
 #include <vector>
 
 #include "base/macros.h"
@@ -121,6 +122,15 @@
     poll_interval_ = interval;
   }
 
+  const std::vector<std::string>& active_device_fcm_registration_tokens()
+      const {
+    return active_device_fcm_registration_tokens_;
+  }
+  void set_active_device_fcm_registration_tokens(
+      std::vector<std::string> fcm_registration_tokens) {
+    active_device_fcm_registration_tokens_ = std::move(fcm_registration_tokens);
+  }
+
  private:
   base::ObserverList<SyncEngineEventListener>::Unchecked listeners_;
 
@@ -169,6 +179,9 @@
   // If there are no other known active devices.
   bool single_client_;
 
+  // A list of FCM registration tokens to send invalidations.
+  std::vector<std::string> active_device_fcm_registration_tokens_;
+
   base::TimeDelta poll_interval_;
 
   DISALLOW_COPY_AND_ASSIGN(SyncCycleContext);
diff --git a/components/sync/engine_impl/sync_manager_impl.cc b/components/sync/engine_impl/sync_manager_impl.cc
index 4d41c63..f5b57880 100644
--- a/components/sync/engine_impl/sync_manager_impl.cc
+++ b/components/sync/engine_impl/sync_manager_impl.cc
@@ -568,4 +568,10 @@
   cycle_context_->set_single_client(single_client);
 }
 
+void SyncManagerImpl::UpdateActiveDeviceFCMRegistrationTokens(
+    std::vector<std::string> fcm_registration_tokens) {
+  cycle_context_->set_active_device_fcm_registration_tokens(
+      std::move(fcm_registration_tokens));
+}
+
 }  // namespace syncer
diff --git a/components/sync/engine_impl/sync_manager_impl.h b/components/sync/engine_impl/sync_manager_impl.h
index b45a65c..607e43f 100644
--- a/components/sync/engine_impl/sync_manager_impl.h
+++ b/components/sync/engine_impl/sync_manager_impl.h
@@ -85,6 +85,8 @@
   void OnCookieJarChanged(bool account_mismatch) override;
   void UpdateInvalidationClientId(const std::string& client_id) override;
   void UpdateSingleClientStatus(bool single_client) override;
+  void UpdateActiveDeviceFCMRegistrationTokens(
+      std::vector<std::string> fcm_registration_tokens) override;
 
   // SyncEncryptionHandler::Observer implementation.
   void OnPassphraseRequired(
diff --git a/components/sync/engine_impl/syncer.cc b/components/sync/engine_impl/syncer.cc
index 6b06059..b1fba8d 100644
--- a/components/sync/engine_impl/syncer.cc
+++ b/components/sync/engine_impl/syncer.cc
@@ -150,8 +150,9 @@
         cycle->context()->max_commit_batch_size(),
         cycle->context()->account_name(), cycle->context()->cache_guid(),
         cycle->context()->cookie_jar_mismatch(),
-        cycle->context()->single_client(), &commit_processor,
-        cycle->context()->extensions_activity()));
+        cycle->context()->single_client(),
+        cycle->context()->active_device_fcm_registration_tokens(),
+        &commit_processor, cycle->context()->extensions_activity()));
     if (!commit) {
       break;
     }
diff --git a/components/sync/protocol/sync.proto b/components/sync/protocol/sync.proto
index b1347fb..9234a208 100644
--- a/components/sync/protocol/sync.proto
+++ b/components/sync/protocol/sync.proto
@@ -447,6 +447,20 @@
   // the committed data. The client is considered active if it's DeviceInfo has
   // updated recent enough.
   optional bool single_client = 4;
+
+  // A list of FCM registration tokens which are obtained from other clients.
+  // This list is used by the server to send invalidations to all other clients.
+  // If the list is empty, the server should treat this as "there is no
+  // information about other clients". In practice, this happens by the next
+  // causes:
+  // 1. This is the old client which doesn't set this field.
+  // 2. There are too many active devices and the list would have too many
+  // items.
+  // 3. An empty list could also mean that the current client is the only
+  // client. This case should be covered by the |single_client| field instead
+  // (otherwise it could be mixed up with older clients). The server doesn't
+  // have to use this field and can ignore it.
+  repeated string devices_fcm_registration_tokens = 5;
 }
 
 message CommitMessage {
diff --git a/components/sync/test/engine/fake_sync_manager.cc b/components/sync/test/engine/fake_sync_manager.cc
index 192f00a..81d18c1 100644
--- a/components/sync/test/engine/fake_sync_manager.cc
+++ b/components/sync/test/engine/fake_sync_manager.cc
@@ -196,4 +196,9 @@
   // Do nothing.
 }
 
+void FakeSyncManager::UpdateActiveDeviceFCMRegistrationTokens(
+    std::vector<std::string> fcm_registration_tokens) {
+  // Do nothing.
+}
+
 }  // namespace syncer
diff --git a/components/sync/test/engine/fake_sync_manager.h b/components/sync/test/engine/fake_sync_manager.h
index ec0a207..811cd56 100644
--- a/components/sync/test/engine/fake_sync_manager.h
+++ b/components/sync/test/engine/fake_sync_manager.h
@@ -98,6 +98,8 @@
   void OnCookieJarChanged(bool account_mismatch) override;
   void UpdateInvalidationClientId(const std::string&) override;
   void UpdateSingleClientStatus(bool single_client) override;
+  void UpdateActiveDeviceFCMRegistrationTokens(
+      std::vector<std::string> fcm_registration_tokens) override;
 
  private:
   scoped_refptr<base::SequencedTaskRunner> sync_task_runner_;
diff --git a/components/url_pattern_index/flat/url_pattern_index.fbs b/components/url_pattern_index/flat/url_pattern_index.fbs
index fc55c34..10f16fe1 100644
--- a/components/url_pattern_index/flat/url_pattern_index.fbs
+++ b/components/url_pattern_index/flat/url_pattern_index.fbs
@@ -25,7 +25,7 @@
 // url_pattern_index::proto::UrlRule, but here, they are represented as flags
 // of the same bitmask to allow for compact storage.
 enum OptionFlag : ubyte (bit_flags) {
-  IS_WHITELIST,
+  IS_ALLOWLIST,
   APPLIES_TO_FIRST_PARTY,
   APPLIES_TO_THIRD_PARTY,
   IS_CASE_INSENSITIVE,
diff --git a/components/url_pattern_index/proto/rules.proto b/components/url_pattern_index/proto/rules.proto
index 780fec79..04a8805 100644
--- a/components/url_pattern_index/proto/rules.proto
+++ b/components/url_pattern_index/proto/rules.proto
@@ -96,10 +96,10 @@
 
   // Matching subresource requests should be aborted, matching elements should
   // be hidden.
-  RULE_SEMANTICS_BLACKLIST = 1;
-  // If the rule matches, it suppresses any matching RULE_SEMANTICS_BLACKLIST
+  RULE_SEMANTICS_BLOCKLIST = 1;
+  // If the rule matches, it suppresses any matching RULE_SEMANTICS_BLOCKLIST
   // rule.
-  RULE_SEMANTICS_WHITELIST = 2;
+  RULE_SEMANTICS_ALLOWLIST = 2;
 }
 
 // The type of relation between the source of the requested subresource and that
diff --git a/components/url_pattern_index/url_pattern_index.cc b/components/url_pattern_index/url_pattern_index.cc
index 73a48ff5..3863491b 100644
--- a/components/url_pattern_index/url_pattern_index.cc
+++ b/components/url_pattern_index/url_pattern_index.cc
@@ -241,9 +241,9 @@
     static_assert(flat::OptionFlag_ANY <= std::numeric_limits<uint8_t>::max(),
                   "Option flags can not be stored in uint8_t.");
 
-    if (rule_.semantics() == proto::RULE_SEMANTICS_WHITELIST) {
-      options_ |= flat::OptionFlag_IS_WHITELIST;
-    } else if (rule_.semantics() != proto::RULE_SEMANTICS_BLACKLIST) {
+    if (rule_.semantics() == proto::RULE_SEMANTICS_ALLOWLIST) {
+      options_ |= flat::OptionFlag_IS_ALLOWLIST;
+    } else if (rule_.semantics() != proto::RULE_SEMANTICS_BLOCKLIST) {
       return false;  // Unsupported semantics.
     }
 
diff --git a/components/url_pattern_index/url_pattern_index_unittest.cc b/components/url_pattern_index/url_pattern_index_unittest.cc
index 51d80f3f..46da07f 100644
--- a/components/url_pattern_index/url_pattern_index_unittest.cc
+++ b/components/url_pattern_index/url_pattern_index_unittest.cc
@@ -604,7 +604,7 @@
         << "; ActivationType: " << static_cast<int>(test_case.activation_type));
 
     auto rule = MakeUrlRule(UrlPattern(test_case.url_pattern, kSubstring));
-    rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+    rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
     rule.clear_element_types();
     rule.set_activation_types(test_case.activation_types);
     ASSERT_TRUE(AddUrlRule(rule));
@@ -626,7 +626,7 @@
 
 TEST_F(UrlPatternIndexTest, OneRuleWithElementAndActivationTypes) {
   auto rule = MakeUrlRule(UrlPattern("allow.ex.com", kSubstring));
-  rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
   rule.set_element_types(testing::kSubdocument);
   rule.set_activation_types(kDocument);
   ASSERT_TRUE(AddUrlRule(rule));
@@ -811,7 +811,7 @@
 
   for (const auto& rule_data : kRules) {
     auto rule = MakeUrlRule(UrlPattern("example.com", kSubstring));
-    rule.set_semantics(proto::RULE_SEMANTICS_WHITELIST);
+    rule.set_semantics(proto::RULE_SEMANTICS_ALLOWLIST);
     rule.set_element_types(rule_data.element_types);
     rule.set_activation_types(rule_data.activation_types);
     EXPECT_TRUE(AddUrlRule(rule))
diff --git a/components/url_pattern_index/url_rule_test_support.cc b/components/url_pattern_index/url_rule_test_support.cc
index 86a518a..5654e15 100644
--- a/components/url_pattern_index/url_rule_test_support.cc
+++ b/components/url_pattern_index/url_rule_test_support.cc
@@ -15,7 +15,7 @@
 proto::UrlRule MakeUrlRule(const UrlPattern& url_pattern) {
   proto::UrlRule rule;
 
-  rule.set_semantics(proto::RULE_SEMANTICS_BLACKLIST);
+  rule.set_semantics(proto::RULE_SEMANTICS_BLOCKLIST);
   rule.set_source_type(proto::SOURCE_TYPE_ANY);
   rule.set_element_types(kAllElementTypes);
 
diff --git a/components/url_pattern_index/url_rule_util.cc b/components/url_pattern_index/url_rule_util.cc
index d2e39e6..d2dd89b 100644
--- a/components/url_pattern_index/url_rule_util.cc
+++ b/components/url_pattern_index/url_rule_util.cc
@@ -153,7 +153,7 @@
 std::string FlatUrlRuleToFilterlistString(const flat::UrlRule* flat_rule) {
   std::string out;
 
-  if (flat_rule->options() & url_pattern_index::flat::OptionFlag_IS_WHITELIST)
+  if (flat_rule->options() & url_pattern_index::flat::OptionFlag_IS_ALLOWLIST)
     out += "@@";
 
   out += AnchorToString(flat_rule->anchor_left());
diff --git a/components/url_pattern_index/url_rule_util_unittest.cc b/components/url_pattern_index/url_rule_util_unittest.cc
index b06fad8..69337da 100644
--- a/components/url_pattern_index/url_rule_util_unittest.cc
+++ b/components/url_pattern_index/url_rule_util_unittest.cc
@@ -79,37 +79,37 @@
   DISALLOW_COPY_AND_ASSIGN(UrlRuleUtilTest);
 };
 
-TEST_F(UrlRuleUtilTest, Blacklist) {
+TEST_F(UrlRuleUtilTest, Blocklist) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 }
 
-TEST_F(UrlRuleUtilTest, Whitelist) {
+TEST_F(UrlRuleUtilTest, Allowlist) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_WHITELIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_ALLOWLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("@@example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 }
 
 TEST_F(UrlRuleUtilTest, LeftAnchor) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com/", proto::ANCHOR_TYPE_NONE,
                                proto::ANCHOR_TYPE_NONE),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com/", proto::ANCHOR_TYPE_BOUNDARY,
                                proto::ANCHOR_TYPE_NONE),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("|example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com/", proto::ANCHOR_TYPE_SUBDOMAIN,
                                proto::ANCHOR_TYPE_NONE),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
@@ -118,14 +118,14 @@
 
 TEST_F(UrlRuleUtilTest, RightAnchor) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
                                proto::ANCHOR_TYPE_NONE),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com", FlatUrlRuleToFilterlistString(flat_rule));
 
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com", proto::ANCHOR_TYPE_NONE,
                                proto::ANCHOR_TYPE_BOUNDARY),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
@@ -134,7 +134,7 @@
 
 TEST_F(UrlRuleUtilTest, BothSidesAnchored) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST,
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST,
                     UrlPattern("example.com", proto::ANCHOR_TYPE_SUBDOMAIN,
                                proto::ANCHOR_TYPE_BOUNDARY),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
@@ -143,13 +143,13 @@
 
 TEST_F(UrlRuleUtilTest, NonRegex) {
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("/foo/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("/foo/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("/foo/*", FlatUrlRuleToFilterlistString(flat_rule));
 
-  // Show that whitelist rules work too.
+  // Show that allowlist rules work too.
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_WHITELIST, UrlPattern("/foo/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_ALLOWLIST, UrlPattern("/foo/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("@@/foo/*", FlatUrlRuleToFilterlistString(flat_rule));
 
@@ -159,13 +159,13 @@
 
 TEST_F(UrlRuleUtilTest, Party) {
   const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
-      proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
       proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/$third-party",
             FlatUrlRuleToFilterlistString(flat_rule));
 
   flat_rule = MakeFlatRule(MakeProtoRule(
-      proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
       proto::SOURCE_TYPE_FIRST_PARTY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/$~third-party",
             FlatUrlRuleToFilterlistString(flat_rule));
@@ -173,7 +173,7 @@
 
 TEST_F(UrlRuleUtilTest, MultipleOptions) {
   const flat::UrlRule* flat_rule = MakeFlatRule(MakeProtoRule(
-      proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
       proto::SOURCE_TYPE_THIRD_PARTY, proto::ELEMENT_TYPE_SCRIPT, {}));
   EXPECT_EQ("example.com/$third-party,script",
             FlatUrlRuleToFilterlistString(flat_rule));
@@ -182,20 +182,20 @@
 TEST_F(UrlRuleUtilTest, ElementType) {
   // Test a single type.
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_SCRIPT, {}));
   EXPECT_EQ("example.com/$script", FlatUrlRuleToFilterlistString(flat_rule));
 
   // Test blocking every type.
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 
   // Block everything except other. This test will need to be updated as
   // proto::ElementType is changed.
   flat_rule = MakeFlatRule(MakeProtoRule(
-      proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
       proto::SOURCE_TYPE_ANY,
       static_cast<proto::ElementType>(proto::ELEMENT_TYPE_ALL - 1), {}));
   std::string expected =
@@ -209,13 +209,13 @@
 TEST_F(UrlRuleUtilTest, ActivationType) {
   // Test with no activiation type.
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 
   // Test with a document activation type.
   auto proto_rule =
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {});
   proto_rule.set_activation_types(proto::ACTIVATION_TYPE_DOCUMENT);
   flat_rule = MakeFlatRule(proto_rule);
@@ -232,13 +232,13 @@
 TEST_F(UrlRuleUtilTest, DomainList) {
   //  Test with no domains set.
   const flat::UrlRule* flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL, {}));
   EXPECT_EQ("example.com/", FlatUrlRuleToFilterlistString(flat_rule));
 
   // Test with domains set.
   flat_rule = MakeFlatRule(
-      MakeProtoRule(proto::RULE_SEMANTICS_BLACKLIST, UrlPattern("example.com/"),
+      MakeProtoRule(proto::RULE_SEMANTICS_BLOCKLIST, UrlPattern("example.com/"),
                     proto::SOURCE_TYPE_ANY, proto::ELEMENT_TYPE_ALL,
                     {"foo.example.com", "~bar.example.com"}));
   EXPECT_EQ("example.com/$domain=foo.example.com|~bar.example.com",
diff --git a/components/viz/common/display/overlay_strategy.h b/components/viz/common/display/overlay_strategy.h
index 3fa5ede..549b11f 100644
--- a/components/viz/common/display/overlay_strategy.h
+++ b/components/viz/common/display/overlay_strategy.h
@@ -22,7 +22,8 @@
   kUnderlay = 4,
   kUnderlayCast = 5,
   kNoStrategyAllFail = 6,
-  kMaxValue = kNoStrategyAllFail,
+  kNoStrategyFailMin = 7,
+  kMaxValue = kNoStrategyFailMin,
 };
 
 // Parses a comma separated list of overlay strategy types and returns a list
diff --git a/components/viz/service/display/overlay_candidate.cc b/components/viz/service/display/overlay_candidate.cc
index a282da4..4fa7f92 100644
--- a/components/viz/service/display/overlay_candidate.cc
+++ b/components/viz/service/display/overlay_candidate.cc
@@ -31,8 +31,6 @@
 constexpr uint32_t OverlayCandidate::kInvalidDamageIndex;
 
 namespace {
-// Tolerance for considering axis vector elements to be zero.
-const SkScalar kEpsilon = std::numeric_limits<float>::epsilon();
 
 const gfx::BufferFormat kOverlayFormats[] = {
     gfx::BufferFormat::RGBX_8888, gfx::BufferFormat::RGBA_8888,
@@ -43,14 +41,14 @@
 enum Axis { NONE, AXIS_POS_X, AXIS_NEG_X, AXIS_POS_Y, AXIS_NEG_Y };
 
 Axis VectorToAxis(const gfx::Vector3dF& vec) {
-  if (std::abs(vec.z()) > kEpsilon)
+  if (!cc::MathUtil::IsWithinEpsilon(vec.z(), 0.f))
     return NONE;
-  const bool x_zero = (std::abs(vec.x()) <= kEpsilon);
-  const bool y_zero = (std::abs(vec.y()) <= kEpsilon);
+  const bool x_zero = cc::MathUtil::IsWithinEpsilon(vec.x(), 0.f);
+  const bool y_zero = cc::MathUtil::IsWithinEpsilon(vec.y(), 0.f);
   if (x_zero && !y_zero)
-    return (vec.y() > 0) ? AXIS_POS_Y : AXIS_NEG_Y;
+    return (vec.y() > 0.f) ? AXIS_POS_Y : AXIS_NEG_Y;
   else if (y_zero && !x_zero)
-    return (vec.x() > 0) ? AXIS_POS_X : AXIS_NEG_X;
+    return (vec.x() > 0.f) ? AXIS_POS_X : AXIS_NEG_X;
   else
     return NONE;
 }
@@ -64,7 +62,7 @@
   gfx::Vector3dF x_axis = cc::MathUtil::GetXAxis(quad_transform);
   gfx::Vector3dF y_axis = cc::MathUtil::GetYAxis(quad_transform);
   if (y_flipped) {
-    y_axis.Scale(-1);
+    y_axis.Scale(-1.f);
   }
 
   Axis x_to = VectorToAxis(x_axis);
@@ -121,20 +119,7 @@
 
 }  // namespace
 
-OverlayCandidate::OverlayCandidate()
-    : transform(gfx::OVERLAY_TRANSFORM_NONE),
-      format(gfx::BufferFormat::RGBA_8888),
-      uv_rect(0.f, 0.f, 1.f, 1.f),
-      is_clipped(false),
-      is_opaque(false),
-      resource_id(0),
-#if defined(OS_ANDROID)
-      is_backed_by_surface_texture(false),
-      is_promotable_hint(false),
-#endif
-      overlay_handled(false),
-      gpu_fence_id(0) {
-}
+OverlayCandidate::OverlayCandidate() = default;
 
 OverlayCandidate::OverlayCandidate(const OverlayCandidate& other) = default;
 
@@ -153,23 +138,26 @@
   if (!output_color_matrix.isIdentity())
     return false;
 
-  // We don't support an opacity value different than one for an overlay plane.
-  if (quad->shared_quad_state->opacity != 1.f)
-    return false;
+  const SharedQuadState* sqs = quad->shared_quad_state;
 
-  candidate->overlay_damage_index =
-      quad->shared_quad_state->overlay_damage_index.value_or(
-          kInvalidDamageIndex);
+  // We don't support an opacity value different than one for an overlay plane.
+  if (sqs->opacity != 1.f)
+    return false;
 
   // We can't support overlays with mask filter.
-  if (!quad->shared_quad_state->mask_filter_info.IsEmpty())
+  if (!sqs->mask_filter_info.IsEmpty())
     return false;
   // We support only kSrc (no blending) and kSrcOver (blending with premul).
-  if (!(quad->shared_quad_state->blend_mode == SkBlendMode::kSrc ||
-        quad->shared_quad_state->blend_mode == SkBlendMode::kSrcOver)) {
+  if (!(sqs->blend_mode == SkBlendMode::kSrc ||
+        sqs->blend_mode == SkBlendMode::kSrcOver)) {
     return false;
   }
 
+  candidate->requires_overlay = OverlayCandidate::RequiresOverlay(quad);
+
+  candidate->overlay_damage_index =
+      sqs->overlay_damage_index.value_or(kInvalidDamageIndex);
+
   switch (quad->material) {
     case DrawQuad::Material::kTextureContent:
       return FromTextureQuad(resource_provider, surface_damage_rect_list,
@@ -192,14 +180,14 @@
 // static
 bool OverlayCandidate::IsInvisibleQuad(const DrawQuad* quad) {
   float opacity = quad->shared_quad_state->opacity;
-  if (opacity < std::numeric_limits<float>::epsilon())
+  if (cc::MathUtil::IsWithinEpsilon(opacity, 0.f))
     return true;
   if (quad->material != DrawQuad::Material::kSolidColor)
     return false;
   const SkColor color = SolidColorDrawQuad::MaterialCast(quad)->color;
-  const float alpha = (SkColorGetA(color) * (1.0f / 255.0f)) * opacity;
+  const float alpha = (SkColorGetA(color) * (1.f / 255.f)) * opacity;
   return quad->ShouldDrawWithBlending() &&
-         alpha < std::numeric_limits<float>::epsilon();
+         cc::MathUtil::IsWithinEpsilon(alpha, 0.f);
 }
 
 // static
@@ -313,17 +301,18 @@
   if (!base::Contains(kOverlayFormats, candidate->format))
     return false;
 
-  gfx::OverlayTransform overlay_transform = GetOverlayTransform(
-      quad->shared_quad_state->quad_to_target_transform, y_flipped);
+  const SharedQuadState* sqs = quad->shared_quad_state;
+  gfx::OverlayTransform overlay_transform =
+      GetOverlayTransform(sqs->quad_to_target_transform, y_flipped);
   if (overlay_transform == gfx::OVERLAY_TRANSFORM_INVALID)
     return false;
 
-  auto& transform = quad->shared_quad_state->quad_to_target_transform;
+  auto& transform = sqs->quad_to_target_transform;
   candidate->display_rect = gfx::RectF(quad->rect);
   transform.TransformRect(&candidate->display_rect);
 
-  candidate->clip_rect = quad->shared_quad_state->clip_rect;
-  candidate->is_clipped = quad->shared_quad_state->is_clipped;
+  candidate->clip_rect = sqs->clip_rect;
+  candidate->is_clipped = sqs->is_clipped;
   candidate->is_opaque = !quad->ShouldDrawWithBlending();
   // For underlays the function 'EstimateVisibleDamage()' is called to update
   // |damage_area_estimate| to more accurately reflect the actual visible
@@ -333,7 +322,7 @@
   candidate->resource_id = resource_id;
   candidate->transform = overlay_transform;
   candidate->mailbox = resource_provider->GetMailbox(resource_id);
-  candidate->requires_overlay = OverlayCandidate::RequiresOverlay(quad);
+
   return true;
 }
 
@@ -359,7 +348,6 @@
   // damage.
   candidate->damage_area_estimate =
       GetDamageRect(quad, surface_damage_rect_list).size().GetArea();
-  candidate->requires_overlay = OverlayCandidate::RequiresOverlay(quad);
   return true;
 }
 
@@ -375,6 +363,7 @@
       (quad->background_color != SK_ColorBLACK ||
        quad->ShouldDrawWithBlending()))
     return false;
+
   if (!FromDrawQuadResource(resource_provider, surface_damage_rect_list, quad,
                             quad->resource_id(), quad->y_flipped, candidate)) {
     return false;
@@ -446,15 +435,15 @@
       candidate->uv_rect, candidate->resource_size_in_pixels.width(),
       candidate->resource_size_in_pixels.height());
   // Make it an integral multiple of the subsampling factor.
-  constexpr int kSubsamplingFactor = 2;
-  src_rect.set_x(kSubsamplingFactor *
-                 (std::lround(src_rect.x()) / kSubsamplingFactor));
-  src_rect.set_y(kSubsamplingFactor *
-                 (std::lround(src_rect.y()) / kSubsamplingFactor));
-  src_rect.set_width(kSubsamplingFactor *
-                     (std::lround(src_rect.width()) / kSubsamplingFactor));
-  src_rect.set_height(kSubsamplingFactor *
-                      (std::lround(src_rect.height()) / kSubsamplingFactor));
+  auto subsample_round = [](float val) {
+    constexpr int kSubsamplingFactor = 2;
+    return (std::lround(val) / kSubsamplingFactor) * kSubsamplingFactor;
+  };
+
+  src_rect.set_x(subsample_round(src_rect.x()));
+  src_rect.set_y(subsample_round(src_rect.y()));
+  src_rect.set_width(subsample_round(src_rect.width()));
+  src_rect.set_height(subsample_round(src_rect.height()));
   // Scale it back into UV space and set it in the candidate.
   candidate->uv_rect = gfx::ScaleRect(
       src_rect, 1.0f / candidate->resource_size_in_pixels.width(),
diff --git a/components/viz/service/display/overlay_candidate.h b/components/viz/service/display/overlay_candidate.h
index e7f2bca..ffef7a57 100644
--- a/components/viz/service/display/overlay_candidate.h
+++ b/components/viz/service/display/overlay_candidate.h
@@ -81,9 +81,9 @@
   ~OverlayCandidate();
 
   // Transformation to apply to layer during composition.
-  gfx::OverlayTransform transform;
+  gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_NONE;
   // Format of the buffer to scanout.
-  gfx::BufferFormat format;
+  gfx::BufferFormat format = gfx::BufferFormat::RGBA_8888;
   // ColorSpace of the buffer for scanout.
   gfx::ColorSpace color_space;
   // Size of the resource, in pixels.
@@ -92,15 +92,15 @@
   // to integer coordinates if setting |overlay_handled| to true.
   gfx::RectF display_rect;
   // Crop within the buffer to be placed inside |display_rect|.
-  gfx::RectF uv_rect;
+  gfx::RectF uv_rect = gfx::RectF(0.f, 0.f, 1.f, 1.f);
   // Clip rect in the target content space after composition.
   gfx::Rect clip_rect;
   // If the quad is clipped after composition.
-  bool is_clipped;
+  bool is_clipped = false;
   // If the quad doesn't require blending.
-  bool is_opaque;
+  bool is_opaque = false;
   // Texture resource to present in an overlay.
-  unsigned resource_id;
+  unsigned resource_id = 0;
   // Mailbox from resource_id. It is used by SkiaRenderer.
   gpu::Mailbox mailbox;
 
@@ -108,11 +108,7 @@
   // For candidates from StreamVideoDrawQuads, this records whether the quad is
   // marked as being backed by a SurfaceTexture or not.  If so, it's not really
   // promotable to an overlay.
-  bool is_backed_by_surface_texture;
-
-  // Filled in by the OverlayCandidateValidator to indicate whether this is a
-  // promotable candidate or not.
-  bool is_promotable_hint;
+  bool is_backed_by_surface_texture = false;
 #endif
 
   // Stacking order of the overlay plane relative to the main surface,
@@ -121,20 +117,20 @@
 
   // To be modified by the implementer if this candidate can go into
   // an overlay.
-  bool overlay_handled;
+  bool overlay_handled = false;
 
   // Gpu fence to wait for before overlay is ready for display.
-  unsigned gpu_fence_id;
+  unsigned gpu_fence_id = 0;
 
   // The total area in square pixels of damage for this candidate's quad. This
   // is an estimate when 'EstimateOccludedDamage' function is used.
   int damage_area_estimate = 0;
 
-  // Result of call to 'RequiresOverlay' function w/ associated quad.
   static constexpr uint32_t kInvalidDamageIndex = UINT_MAX;
+  // Damage index for |SurfaceDamageRectList|.
   uint32_t overlay_damage_index = kInvalidDamageIndex;
 
-  // Cached result of call to 'RequiresOverlay' function.
+  // Is true if an HW overlay is required for the quad content.
   bool requires_overlay = false;
 
  private:
diff --git a/components/viz/service/display/overlay_candidate_temporal_tracker.cc b/components/viz/service/display/overlay_candidate_temporal_tracker.cc
index ba81334f..db9e060 100644
--- a/components/viz/service/display/overlay_candidate_temporal_tracker.cc
+++ b/components/viz/service/display/overlay_candidate_temporal_tracker.cc
@@ -41,8 +41,9 @@
     uint64_t curr_frame,
     float damage_area_ratio,
     unsigned resource_id,
-    const OverlayCandidateTemporalTracker::Config& config) {
-  if (prev_resource_id != resource_id &&
+    const OverlayCandidateTemporalTracker::Config& config,
+    bool force_resource_update) {
+  if ((prev_resource_id != resource_id || force_resource_update) &&
       frame_record[(next_index + kNumRecords - 1) % kNumRecords] !=
           curr_frame) {
     frame_record[next_index] = curr_frame;
diff --git a/components/viz/service/display/overlay_candidate_temporal_tracker.h b/components/viz/service/display/overlay_candidate_temporal_tracker.h
index 42afda5..aebcee1 100644
--- a/components/viz/service/display/overlay_candidate_temporal_tracker.h
+++ b/components/viz/service/display/overlay_candidate_temporal_tracker.h
@@ -55,10 +55,16 @@
 
   // This function adds a new record to the tracker if the |resource_id| has
   // changed since last update.
+  // The |force_resource_update| flag has been added for the case when the
+  // resource has been updated but the |resource_id| has not changed. The case
+  // for when this occurs is a low latency surface (ink). Fortunately, we can
+  // use surface damage to ascertain when these surfaces have changed despite
+  // the |resource_id| remaining constant.
   void AddRecord(uint64_t curr_frame,
                  float damage_area_ratio,
                  unsigned resource_id,
-                 const Config& config);
+                 const Config& config,
+                 bool force_resource_update = false);
 
   // This function returns true when this tracker's 'AddRecord' was not called
   // in the previous frame. We require this behavior in order to know when an
diff --git a/components/viz/service/display/overlay_processor_using_strategy.cc b/components/viz/service/display/overlay_processor_using_strategy.cc
index 1c0080a..329258f 100644
--- a/components/viz/service/display/overlay_processor_using_strategy.cc
+++ b/components/viz/service/display/overlay_processor_using_strategy.cc
@@ -16,6 +16,7 @@
 #include "components/viz/common/quads/solid_color_draw_quad.h"
 #include "components/viz/service/display/display_resource_provider.h"
 #include "components/viz/service/display/output_surface.h"
+#include "components/viz/service/display/overlay_candidate.h"
 #include "components/viz/service/display/overlay_strategy_single_on_top.h"
 #include "components/viz/service/display/overlay_strategy_underlay.h"
 #include "ui/gfx/geometry/rect_conversions.h"
@@ -285,7 +286,9 @@
     track_data.AddRecord(
         frame_sequence_number_,
         static_cast<float>(it->candidate.damage_area_estimate) / display_area,
-        it->candidate.resource_id, tracker_config_);
+        it->candidate.resource_id, tracker_config_,
+        it->candidate.overlay_damage_index !=
+            OverlayCandidate::kInvalidDamageIndex);
 
     // Here a series of criteria are considered for wholesale rejection of a
     // candidate. The rational for rejection is usually power improvements but
@@ -357,7 +360,6 @@
     std::vector<gfx::Rect>* content_bounds,
     gfx::Rect* incoming_damage) {
   last_successful_strategy_ = nullptr;
-
   Strategy::OverlayProposedCandidateList proposed_candidates;
   for (const auto& strategy : strategies_) {
     strategy->ProposePrioritized(
@@ -366,13 +368,20 @@
         &proposed_candidates, content_bounds);
   }
 
+  size_t num_proposed_pre_sort = proposed_candidates.size();
   UMA_HISTOGRAM_COUNTS_1000(
       "Viz.DisplayCompositor.OverlayNumProposedCandidates",
-      proposed_candidates.size());
+      num_proposed_pre_sort);
 
   SortProposedOverlayCandidatesPrioritized(&proposed_candidates);
 
   for (auto&& candidate : proposed_candidates) {
+    // Underlays change the material so we save it here to record proper UMA.
+    DrawQuad::Material quad_material =
+        candidate.strategy->GetUMAEnum() != OverlayStrategy::kUnknown
+            ? candidate.quad_iter->material
+            : DrawQuad::Material::kInvalid;
+
     if (candidate.strategy->AttemptPrioritized(
             output_color_matrix, render_pass_backdrop_filters,
             resource_provider, render_pass_list, surface_damage_rect_list,
@@ -383,12 +392,16 @@
       LogStrategyEnumUMA(candidate.strategy->GetUMAEnum());
       last_successful_strategy_ = candidate.strategy;
       OnOverlaySwitchUMA(ToProposeKey(candidate));
+      UMA_HISTOGRAM_ENUMERATION("Viz.DisplayCompositor.OverlayQuadMaterial",
+                                quad_material);
       return true;
     }
   }
 
   if (proposed_candidates.size() == 0) {
-    LogStrategyEnumUMA(OverlayStrategy::kNoStrategyUsed);
+    LogStrategyEnumUMA(num_proposed_pre_sort != 0
+                           ? OverlayStrategy::kNoStrategyFailMin
+                           : OverlayStrategy::kNoStrategyUsed);
   } else {
     LogStrategyEnumUMA(OverlayStrategy::kNoStrategyAllFail);
   }
diff --git a/components/viz/service/display/overlay_unittest.cc b/components/viz/service/display/overlay_unittest.cc
index 6dff1b2..cfcd49e 100644
--- a/components/viz/service/display/overlay_unittest.cc
+++ b/components/viz/service/display/overlay_unittest.cc
@@ -2555,6 +2555,28 @@
   wait_1_frame();
   tracker.AddRecord(frame_counter, 0.0f, get_id(), config);
   EXPECT_FALSE(tracker.IsAbsent());
+
+  // Tracker forced updates were added to support quads that change content but
+  // not resource ids (example here is low latency ink surface). Here we test
+  // this small feature by keeping the resource id constant but passing in true
+  // to the force update param.
+  static const float kDamageRatio = 0.7f;
+  static const int kFakeConstantResourceId = 13;
+  for (int i = 0; i < OverlayCandidateTemporalTracker::kNumRecords; i++) {
+    wait_1_frame();
+    tracker.AddRecord(frame_counter, kDamageRatio, kFakeConstantResourceId,
+                      config, true);
+  }
+  EXPECT_FLOAT_EQ(kDamageRatio, tracker.MeanFrameRatioRate(config));
+
+  // Now test the false case for the force update param.
+  for (int i = 0; i < OverlayCandidateTemporalTracker::kNumRecords; i++) {
+    wait_1_frame();
+    tracker.AddRecord(frame_counter, 0.9f, kFakeConstantResourceId, config,
+                      false);
+  }
+  // The damage should remain unchanged.
+  EXPECT_FLOAT_EQ(kDamageRatio, tracker.MeanFrameRatioRate(config));
 }
 
 TEST_F(UnderlayTest, UpdateDamageRectWhenNoPromotion) {
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
index d4d0c56..6bb2ab6f 100644
--- a/components/viz/service/display/skia_renderer.cc
+++ b/components/viz/service/display/skia_renderer.cc
@@ -1064,8 +1064,6 @@
 
     // Only sample from pixels behind the RPDQ for backdrop filters to avoid
     // color bleeding with pixel-moving filters.
-    // TODO(crbug.com/1165868): Add web platform test to verify this clip is
-    // done correctly.
     if (rpdq_params.bypass_geometry) {
       crop_rect.Intersect(rpdq_params.bypass_geometry->rect);
     } else {
diff --git a/content/browser/background_fetch/background_fetch_data_manager.cc b/content/browser/background_fetch/background_fetch_data_manager.cc
index 5368a47..66d736c 100644
--- a/content/browser/background_fetch/background_fetch_data_manager.cc
+++ b/content/browser/background_fetch/background_fetch_data_manager.cc
@@ -10,6 +10,7 @@
 #include "base/containers/queue.h"
 #include "base/strings/utf_string_conversions.h"
 #include "base/time/time.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/background_fetch/background_fetch_constants.h"
 #include "content/browser/background_fetch/background_fetch_data_manager_observer.h"
 #include "content/browser/background_fetch/background_fetch_request_info.h"
@@ -94,7 +95,8 @@
   DCHECK(cache_storage_context_);
   cache_storage_context_->AddReceiver(
       cross_origin_embedder_policy, mojo::NullRemote(), origin,
-      CacheStorageOwner::kBackgroundFetch, remote.BindNewPipeAndPassReceiver());
+      storage::mojom::CacheStorageOwner::kBackgroundFetch,
+      remote.BindNewPipeAndPassReceiver());
 
   auto result = cache_storage_remote_map_.emplace(unique_id, std::move(remote));
   DCHECK(result.second);
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
index 309f306..a315d7a 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.cc
@@ -354,13 +354,13 @@
 // static
 std::unique_ptr<CacheStorageCacheEntryHandler>
 CacheStorageCacheEntryHandler::CreateCacheEntryHandler(
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     scoped_refptr<BlobStorageContextWrapper> blob_storage_context) {
   switch (owner) {
-    case CacheStorageOwner::kCacheAPI:
+    case storage::mojom::CacheStorageOwner::kCacheAPI:
       return std::make_unique<CacheStorageCacheEntryHandlerImpl>(
           std::move(blob_storage_context));
-    case CacheStorageOwner::kBackgroundFetch:
+    case storage::mojom::CacheStorageOwner::kBackgroundFetch:
       return std::make_unique<background_fetch::CacheEntryHandlerImpl>(
           std::move(blob_storage_context));
   }
diff --git a/content/browser/cache_storage/cache_storage_cache_entry_handler.h b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
index bcbdd04..9a780db 100644
--- a/content/browser/cache_storage/cache_storage_cache_entry_handler.h
+++ b/content/browser/cache_storage/cache_storage_cache_entry_handler.h
@@ -13,6 +13,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/memory/weak_ptr.h"
 #include "base/types/pass_key.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_cache.h"
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
@@ -29,8 +30,6 @@
 
 namespace content {
 
-enum class CacheStorageOwner;
-
 // The state needed to pass when writing to a cache.
 struct PutContext {
   using ErrorCallback =
@@ -119,7 +118,7 @@
                                    blink::mojom::FetchAPIRequest* request) = 0;
 
   static std::unique_ptr<CacheStorageCacheEntryHandler> CreateCacheEntryHandler(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context);
 
   void InvalidateDiskCacheBlobEntrys();
diff --git a/content/browser/cache_storage/cache_storage_cache_unittest.cc b/content/browser/cache_storage/cache_storage_cache_unittest.cc
index 2495bd8..0fba61f6 100644
--- a/content/browser/cache_storage/cache_storage_cache_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_cache_unittest.cc
@@ -26,6 +26,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/cache_storage/cache_storage_cache.h"
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
@@ -444,7 +445,7 @@
       const scoped_refptr<storage::QuotaManagerProxy>& quota_manager_proxy,
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context)
       : LegacyCacheStorageCache(origin,
-                                CacheStorageOwner::kCacheAPI,
+                                storage::mojom::CacheStorageOwner::kCacheAPI,
                                 cache_name,
                                 path,
                                 cache_storage,
@@ -521,7 +522,7 @@
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
       LegacyCacheStorageManager* cache_storage_manager,
       const url::Origin& origin,
-      CacheStorageOwner owner)
+      storage::mojom::CacheStorageOwner owner)
       : LegacyCacheStorage(origin_path,
                            memory_only,
                            cache_task_runner,
@@ -589,7 +590,8 @@
         temp_dir_path_, MemoryOnly(), base::ThreadTaskRunnerHandle::Get().get(),
         base::ThreadTaskRunnerHandle::Get(), quota_manager_proxy_,
         blob_storage_context_, /* cache_storage_manager = */ nullptr,
-        url::Origin::Create(kTestUrl), CacheStorageOwner::kCacheAPI);
+        url::Origin::Create(kTestUrl),
+        storage::mojom::CacheStorageOwner::kCacheAPI);
 
     InitCache(mock_cache_storage_.get());
   }
diff --git a/content/browser/cache_storage/cache_storage_context_impl.cc b/content/browser/cache_storage/cache_storage_context_impl.cc
index e2b2f8a8..6c8ac38 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.cc
+++ b/content/browser/cache_storage/cache_storage_context_impl.cc
@@ -103,7 +103,7 @@
     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
         coep_reporter,
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   if (!dispatcher_host_) {
@@ -190,8 +190,9 @@
               std::move(callback).Run(std::vector<StorageUsageInfo>());
               return;
             }
-            manager->GetAllOriginsUsage(CacheStorageOwner::kCacheAPI,
-                                        std::move(callback));
+            manager->GetAllOriginsUsage(
+                storage::mojom::CacheStorageOwner::kCacheAPI,
+                std::move(callback));
           },
           base::RetainedRef(this), std::move(callback)));
 }
@@ -206,8 +207,9 @@
                            context->CacheManager();
                        if (!manager)
                          return;
-                       manager->DeleteOriginData(origin,
-                                                 CacheStorageOwner::kCacheAPI);
+                       manager->DeleteOriginData(
+                           origin,
+                           storage::mojom::CacheStorageOwner::kCacheAPI);
                      },
                      base::RetainedRef(this), origin));
 }
@@ -244,7 +246,7 @@
   if (special_storage_policy_ &&
       special_storage_policy_->HasSessionOnlyOrigins()) {
     cache_manager_->GetAllOriginsUsage(
-        CacheStorageOwner::kCacheAPI,
+        storage::mojom::CacheStorageOwner::kCacheAPI,
         base::BindOnce(
             [](scoped_refptr<CacheStorageManager> cache_manager,
                scoped_refptr<storage::SpecialStoragePolicy>
@@ -256,7 +258,7 @@
                     !special_storage_policy->IsStorageProtected(
                         info.origin.GetURL())) {
                   cache_manager->DeleteOriginData(
-                      info.origin, CacheStorageOwner::kCacheAPI,
+                      info.origin, storage::mojom::CacheStorageOwner::kCacheAPI,
 
                       // Retain a reference to the manager until the deletion is
                       // complete, since it internally uses weak pointers for
@@ -309,12 +311,12 @@
     return;
   quota_manager_proxy->RegisterClient(
       base::MakeRefCounted<CacheStorageQuotaClient>(
-          manager, CacheStorageOwner::kCacheAPI),
+          manager, storage::mojom::CacheStorageOwner::kCacheAPI),
       storage::QuotaClientType::kServiceWorkerCache,
       {blink::mojom::StorageType::kTemporary});
   quota_manager_proxy->RegisterClient(
       base::MakeRefCounted<CacheStorageQuotaClient>(
-          manager, CacheStorageOwner::kBackgroundFetch),
+          manager, storage::mojom::CacheStorageOwner::kBackgroundFetch),
       storage::QuotaClientType::kBackgroundFetch,
       {blink::mojom::StorageType::kTemporary});
 }
diff --git a/content/browser/cache_storage/cache_storage_context_impl.h b/content/browser/cache_storage/cache_storage_context_impl.h
index a060f38..ad02266b 100644
--- a/content/browser/cache_storage/cache_storage_context_impl.h
+++ b/content/browser/cache_storage/cache_storage_context_impl.h
@@ -14,6 +14,7 @@
 #include "base/synchronization/lock.h"
 #include "base/threading/sequence_bound.h"
 #include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 #include "content/common/content_export.h"
 #include "content/public/browser/cache_storage_context.h"
@@ -62,7 +63,8 @@
 // CacheStorageManager instance, which is only accessed on the target
 // sequence.
 class CONTENT_EXPORT CacheStorageContextImpl
-    : public CacheStorageContextWithManager {
+    : public CacheStorageContextWithManager,
+      public storage::mojom::CacheStorageControl {
  public:
   CacheStorageContextImpl();
 
@@ -91,8 +93,8 @@
       mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
           coep_reporter_remote,
       const url::Origin& origin,
-      CacheStorageOwner owner,
-      mojo::PendingReceiver<blink::mojom::CacheStorage> receiver);
+      storage::mojom::CacheStorageOwner owner,
+      mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) override;
 
   // If called on the cache_storage target sequence the real manager will be
   // returned directly.  If called on any other sequence then a cross-sequence
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.cc b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
index 6d2630d5..7c7d2979 100644
--- a/content/browser/cache_storage/cache_storage_dispatcher_host.cc
+++ b/content/browser/cache_storage/cache_storage_dispatcher_host.cc
@@ -170,7 +170,7 @@
       const CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
       mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
           coep_reporter,
-      CacheStorageOwner owner)
+      storage::mojom::CacheStorageOwner owner)
       : host_(host),
         cache_handle_(std::move(cache_handle)),
         origin_(origin),
@@ -369,7 +369,7 @@
                             GetAllMatchedEntriesCallback callback) override {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
-    if (owner_ != CacheStorageOwner::kBackgroundFetch) {
+    if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch) {
       host_->cache_receivers_.ReportBadMessage("CSDH_BAD_OWNER");
       return;
     }
@@ -607,7 +607,7 @@
   const CrossOriginEmbedderPolicy cross_origin_embedder_policy_;
   mojo::Remote<network::mojom::CrossOriginEmbedderPolicyReporter>
       coep_reporter_;
-  const CacheStorageOwner owner_;
+  const storage::mojom::CacheStorageOwner owner_;
   SEQUENCE_CHECKER(sequence_checker_);
 
   base::WeakPtrFactory<CacheImpl> weak_factory_{this};
@@ -628,7 +628,7 @@
       const CrossOriginEmbedderPolicy& cross_origin_embedder_policy,
       mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
           coep_reporter,
-      CacheStorageOwner owner)
+      storage::mojom::CacheStorageOwner owner)
       : host_(host),
         origin_(origin),
         cross_origin_embedder_policy_(cross_origin_embedder_policy),
@@ -950,7 +950,7 @@
   const CrossOriginEmbedderPolicy cross_origin_embedder_policy_;
   mojo::Remote<network::mojom::CrossOriginEmbedderPolicyReporter>
       coep_reporter_;
-  const CacheStorageOwner owner_;
+  const storage::mojom::CacheStorageOwner owner_;
   CacheStorageHandle cache_storage_handle_;
 
   SEQUENCE_CHECKER(sequence_checker_);
@@ -974,7 +974,7 @@
     mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
         coep_reporter,
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     mojo::PendingReceiver<blink::mojom::CacheStorage> receiver) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   bool incognito = context_ ? context_->is_incognito() : false;
@@ -998,7 +998,7 @@
 
 CacheStorageHandle CacheStorageDispatcherHost::OpenCacheStorage(
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   if (!context_ || !OriginCanAccessCacheStorage(origin))
     return CacheStorageHandle();
diff --git a/content/browser/cache_storage/cache_storage_dispatcher_host.h b/content/browser/cache_storage/cache_storage_dispatcher_host.h
index 529656c73..b3fe63a 100644
--- a/content/browser/cache_storage/cache_storage_dispatcher_host.h
+++ b/content/browser/cache_storage/cache_storage_dispatcher_host.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_handle.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
@@ -50,7 +51,7 @@
       mojo::PendingRemote<network::mojom::CrossOriginEmbedderPolicyReporter>
           coep_reporter,
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       mojo::PendingReceiver<blink::mojom::CacheStorage> receiver);
 
   void Shutdown();
@@ -65,7 +66,7 @@
       mojo::PendingAssociatedReceiver<blink::mojom::CacheStorageCache>
           receiver);
   CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
-                                      CacheStorageOwner owner);
+                                      storage::mojom::CacheStorageOwner owner);
 
   scoped_refptr<CacheStorageContextImpl> context_;
 
diff --git a/content/browser/cache_storage/cache_storage_manager.h b/content/browser/cache_storage/cache_storage_manager.h
index 80cdfaa..6a10432 100644
--- a/content/browser/cache_storage/cache_storage_manager.h
+++ b/content/browser/cache_storage/cache_storage_manager.h
@@ -8,6 +8,7 @@
 #include <string>
 
 #include "base/macros.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/blob_storage/blob_storage_context_wrapper.h"
 #include "content/browser/cache_storage/cache_storage_handle.h"
 #include "content/common/content_export.h"
@@ -22,18 +23,6 @@
 
 namespace content {
 
-enum class CacheStorageOwner {
-  kMinValue,
-
-  // Caches that can be accessed by the JS CacheStorage API (developer facing).
-  kCacheAPI = kMinValue,
-
-  // Private cache to store background fetch downloads.
-  kBackgroundFetch,
-
-  kMaxValue = kBackgroundFetch
-};
-
 // Keeps track of a CacheStorage per origin. There is one CacheStorageManager
 // per CacheStorageOwner. Created and accessed from a single sequence.
 // TODO(jkarlin): Remove CacheStorage from memory once they're no
@@ -43,30 +32,31 @@
  public:
   // Open the CacheStorage for the given origin and owner.  A reference counting
   // handle is returned which can be stored and used similar to a weak pointer.
-  virtual CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
-                                              CacheStorageOwner owner) = 0;
+  virtual CacheStorageHandle OpenCacheStorage(
+      const url::Origin& origin,
+      storage::mojom::CacheStorageOwner owner) = 0;
 
   // QuotaClient and Browsing Data Deletion support.
   virtual void GetAllOriginsUsage(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       CacheStorageContext::GetUsageInfoCallback callback) = 0;
   virtual void GetOriginUsage(
       const url::Origin& origin_url,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginUsageCallback callback) = 0;
   virtual void GetOrigins(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForTypeCallback callback) = 0;
   virtual void GetOriginsForHost(
       const std::string& host,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForHostCallback callback) = 0;
   virtual void DeleteOriginData(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::DeleteOriginDataCallback callback) = 0;
   virtual void DeleteOriginData(const url::Origin& origin,
-                                CacheStorageOwner owner) = 0;
+                                storage::mojom::CacheStorageOwner owner) = 0;
 
   // This must be called before any of the public Cache functions above.
   virtual void SetBlobParametersForCache(
diff --git a/content/browser/cache_storage/cache_storage_manager_unittest.cc b/content/browser/cache_storage/cache_storage_manager_unittest.cc
index e14a618..8bb2398 100644
--- a/content/browser/cache_storage/cache_storage_manager_unittest.cc
+++ b/content/browser/cache_storage/cache_storage_manager_unittest.cc
@@ -26,6 +26,7 @@
 #include "base/test/metrics/histogram_tester.h"
 #include "base/threading/thread_task_runner_handle.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/blob_storage/chrome_blob_storage_context.h"
 #include "content/browser/cache_storage/cache_storage.pb.h"
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
@@ -456,7 +457,8 @@
 
   bool Open(const url::Origin& origin,
             const std::string& cache_name,
-            CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+            storage::mojom::CacheStorageOwner owner =
+                storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -479,7 +481,8 @@
 
   bool Has(const url::Origin& origin,
            const std::string& cache_name,
-           CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+           storage::mojom::CacheStorageOwner owner =
+               storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -495,7 +498,8 @@
 
   bool Delete(const url::Origin& origin,
               const std::string& cache_name,
-              CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+              storage::mojom::CacheStorageOwner owner =
+                  storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -510,7 +514,8 @@
   }
 
   size_t Keys(const url::Origin& origin,
-              CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+              storage::mojom::CacheStorageOwner owner =
+                  storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -528,7 +533,8 @@
                     const std::string& cache_name,
                     const GURL& url,
                     blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
-                    CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+                    storage::mojom::CacheStorageOwner owner =
+                        storage::mojom::CacheStorageOwner::kCacheAPI) {
     auto request = blink::mojom::FetchAPIRequest::New();
     request->url = url;
     return StorageMatchWithRequest(origin, cache_name, std::move(request),
@@ -540,7 +546,8 @@
       const std::string& cache_name,
       blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
-      CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+      storage::mojom::CacheStorageOwner owner =
+          storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -570,7 +577,8 @@
       const url::Origin& origin,
       blink::mojom::FetchAPIRequestPtr request,
       blink::mojom::CacheQueryOptionsPtr match_options = nullptr,
-      CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+      storage::mojom::CacheStorageOwner owner =
+          storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::HistogramTester histogram_tester;
     base::RunLoop loop;
     CacheStorageHandle cache_storage =
@@ -587,7 +595,7 @@
   }
 
   bool Write(const url::Origin& origin,
-             CacheStorageOwner owner,
+             storage::mojom::CacheStorageOwner owner,
              const std::string& cache_name,
              const std::string& request_url) {
     auto request = blink::mojom::FetchAPIRequest::New();
@@ -725,13 +733,13 @@
   }
 
   CacheStorageHandle CacheStorageForOrigin(const url::Origin& origin) {
-    return cache_manager_->OpenCacheStorage(origin,
-                                            CacheStorageOwner::kCacheAPI);
+    return cache_manager_->OpenCacheStorage(
+        origin, storage::mojom::CacheStorageOwner::kCacheAPI);
   }
 
-  int64_t GetOriginUsage(
-      const url::Origin& origin,
-      CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+  int64_t GetOriginUsage(const url::Origin& origin,
+                         storage::mojom::CacheStorageOwner owner =
+                             storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::RunLoop loop;
     cache_manager_->GetOriginUsage(
         origin, owner,
@@ -747,7 +755,8 @@
   }
 
   std::vector<StorageUsageInfo> GetAllOriginsUsage(
-      CacheStorageOwner owner = CacheStorageOwner::kCacheAPI) {
+      storage::mojom::CacheStorageOwner owner =
+          storage::mojom::CacheStorageOwner::kCacheAPI) {
     base::RunLoop loop;
     cache_manager_->GetAllOriginsUsage(
         owner, base::BindLambdaForTesting(
@@ -876,9 +885,11 @@
 }
 
 TEST_P(CacheStorageManagerTestP, OpenSameCacheDifferentOwners) {
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(
+      Open(origin1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI));
   CacheStorageCacheHandle cache_handle = std::move(callback_cache_handle_);
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin1_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_NE(callback_cache_handle_.value(), cache_handle.value());
 }
 
@@ -910,17 +921,23 @@
 }
 
 TEST_P(CacheStorageManagerTestP, HasCacheDifferentOwners) {
-  EXPECT_TRUE(Open(origin1_, "public", CacheStorageOwner::kCacheAPI));
-  EXPECT_TRUE(Open(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(
+      Open(origin1_, "public", storage::mojom::CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(Open(origin1_, "bgf",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
 
-  EXPECT_TRUE(Has(origin1_, "public", CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(
+      Has(origin1_, "public", storage::mojom::CacheStorageOwner::kCacheAPI));
   EXPECT_TRUE(callback_bool_);
-  EXPECT_FALSE(Has(origin1_, "bgf", CacheStorageOwner::kCacheAPI));
+  EXPECT_FALSE(
+      Has(origin1_, "bgf", storage::mojom::CacheStorageOwner::kCacheAPI));
   EXPECT_FALSE(callback_bool_);
 
-  EXPECT_TRUE(Has(origin1_, "bgf", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Has(origin1_, "bgf",
+                  storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_TRUE(callback_bool_);
-  EXPECT_FALSE(Has(origin1_, "public", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_FALSE(Has(origin1_, "public",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_FALSE(callback_bool_);
 }
 
@@ -1029,24 +1046,30 @@
 }
 
 TEST_P(CacheStorageManagerTestP, StorageMatchDifferentOwners) {
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(
+      Open(origin1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI));
   EXPECT_TRUE(CachePut(callback_cache_handle_.value(),
                        GURL("http://example.com/public")));
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin1_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_TRUE(
       CachePut(callback_cache_handle_.value(), GURL("http://example.com/bgf")));
 
   // Check the public cache.
   EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
-                           nullptr, CacheStorageOwner::kCacheAPI));
+                           nullptr,
+                           storage::mojom::CacheStorageOwner::kCacheAPI));
   EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
-                            nullptr, CacheStorageOwner::kCacheAPI));
+                            nullptr,
+                            storage::mojom::CacheStorageOwner::kCacheAPI));
 
   // Check the internal cache.
-  EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/public"),
-                            nullptr, CacheStorageOwner::kBackgroundFetch));
-  EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"),
-                           nullptr, CacheStorageOwner::kBackgroundFetch));
+  EXPECT_FALSE(
+      StorageMatch(origin1_, "foo", GURL("http://example.com/public"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(
+      StorageMatch(origin1_, "foo", GURL("http://example.com/bgf"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
 }
 
 TEST_F(CacheStorageManagerTest, StorageReuseCacheName) {
@@ -1687,28 +1710,34 @@
 }
 
 TEST_P(CacheStorageManagerTestP, GetAllOriginsUsageDifferentOwners) {
-  EXPECT_EQ(0ULL, GetAllOriginsUsage(CacheStorageOwner::kCacheAPI).size());
-  EXPECT_EQ(0ULL,
-            GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch).size());
+  EXPECT_EQ(
+      0ULL,
+      GetAllOriginsUsage(storage::mojom::CacheStorageOwner::kCacheAPI).size());
+  EXPECT_EQ(0ULL, GetAllOriginsUsage(
+                      storage::mojom::CacheStorageOwner::kBackgroundFetch)
+                      .size());
 
   // Put one entry in a cache of owner 1.
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(
+      Open(origin1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI));
   EXPECT_TRUE(
       CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
 
   // Put two entries (of identical size) in two origins in a cache of owner 2.
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin1_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_TRUE(
       CachePut(callback_cache_handle_.value(), GURL("http://example.com/foo")));
-  EXPECT_TRUE(Open(origin2_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin2_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_TRUE(
       CachePut(callback_cache_handle_.value(), GURL("http://example.com/bar")));
 
   std::vector<StorageUsageInfo> usage_cache =
-      GetAllOriginsUsage(CacheStorageOwner::kCacheAPI);
+      GetAllOriginsUsage(storage::mojom::CacheStorageOwner::kCacheAPI);
   EXPECT_EQ(1ULL, usage_cache.size());
   std::vector<StorageUsageInfo> usage_bgf =
-      GetAllOriginsUsage(CacheStorageOwner::kBackgroundFetch);
+      GetAllOriginsUsage(storage::mojom::CacheStorageOwner::kBackgroundFetch);
   EXPECT_EQ(2ULL, usage_bgf.size());
 
   int origin1_index = usage_bgf[0].origin == origin1_ ? 0 : 1;
@@ -1900,9 +1929,11 @@
 }
 
 TEST_P(CacheStorageManagerLegacyOnlyTestP, GetSizeThenCloseAllCachesTwoOwners) {
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kCacheAPI));
+  EXPECT_TRUE(
+      Open(origin1_, "foo", storage::mojom::CacheStorageOwner::kCacheAPI));
   CacheStorageCacheHandle public_handle = std::move(callback_cache_handle_);
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin1_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   CacheStorageCacheHandle bgf_handle = std::move(callback_cache_handle_);
 
   EXPECT_TRUE(
@@ -1949,7 +1980,8 @@
   auto* legacy_manager =
       static_cast<LegacyCacheStorageManager*>(cache_manager_.get());
   base::FilePath origin_path = LegacyCacheStorageManager::ConstructOriginPath(
-      legacy_manager->root_path(), origin1_, CacheStorageOwner::kCacheAPI);
+      legacy_manager->root_path(), origin1_,
+      storage::mojom::CacheStorageOwner::kCacheAPI);
   base::FilePath unreferenced_path = origin_path.AppendASCII("bar");
   EXPECT_TRUE(CreateDirectory(unreferenced_path));
   EXPECT_TRUE(base::DirectoryExists(unreferenced_path));
@@ -2267,27 +2299,34 @@
 }
 
 TEST_P(CacheStorageManagerTestP, StorageWriteToCache) {
-  EXPECT_TRUE(Open(origin1_, "foo", CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(Open(origin1_, "foo",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
 
-  EXPECT_TRUE(Write(origin1_, CacheStorageOwner::kBackgroundFetch, "foo",
+  EXPECT_TRUE(Write(origin1_,
+                    storage::mojom::CacheStorageOwner::kBackgroundFetch, "foo",
                     "http://example.com/foo"));
 
   // Match request we just wrote.
-  EXPECT_TRUE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
-                           nullptr, CacheStorageOwner::kBackgroundFetch));
+  EXPECT_TRUE(
+      StorageMatch(origin1_, "foo", GURL("http://example.com/foo"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
 
   // Don't match with different origin.
-  EXPECT_FALSE(StorageMatch(origin2_, "foo", GURL("http://example.com/foo"),
-                            nullptr, CacheStorageOwner::kBackgroundFetch));
+  EXPECT_FALSE(
+      StorageMatch(origin2_, "foo", GURL("http://example.com/foo"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   // Don't match with different cache name.
-  EXPECT_FALSE(StorageMatch(origin1_, "bar", GURL("http://example.com/foo"),
-                            nullptr, CacheStorageOwner::kBackgroundFetch));
+  EXPECT_FALSE(
+      StorageMatch(origin1_, "bar", GURL("http://example.com/foo"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   // Don't match with different request.
-  EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/bar"),
-                            nullptr, CacheStorageOwner::kBackgroundFetch));
+  EXPECT_FALSE(
+      StorageMatch(origin1_, "foo", GURL("http://example.com/bar"), nullptr,
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   // Don't match with different owner.
   EXPECT_FALSE(StorageMatch(origin1_, "foo", GURL("http://example.com/foo"),
-                            nullptr, CacheStorageOwner::kCacheAPI));
+                            nullptr,
+                            storage::mojom::CacheStorageOwner::kCacheAPI));
 }
 
 TEST_F(CacheStorageManagerTest, WriteIndexOnlyScheduledWhenValueChanges) {
@@ -2377,7 +2416,7 @@
   void SetUp() override {
     CacheStorageManagerTest::SetUp();
     quota_client_ = base::MakeRefCounted<CacheStorageQuotaClient>(
-        cache_manager_, CacheStorageOwner::kCacheAPI);
+        cache_manager_, storage::mojom::CacheStorageOwner::kCacheAPI);
   }
 
   void QuotaUsageCallback(base::RunLoop* run_loop, int64_t usage) {
@@ -2479,9 +2518,10 @@
 TEST_P(CacheStorageQuotaClientTestP, QuotaGetOriginsForTypeDifferentOwners) {
   EXPECT_EQ(0u, QuotaGetOriginsForType());
   EXPECT_TRUE(Open(origin1_, "foo"));
-  // The |quota_client_| is registered for CacheStorageOwner::kCacheAPI, so this
-  // Open is ignored.
-  EXPECT_TRUE(Open(origin2_, "bar", CacheStorageOwner::kBackgroundFetch));
+  // The |quota_client_| is registered for
+  // storage::mojom::CacheStorageOwner::kCacheAPI, so this Open is ignored.
+  EXPECT_TRUE(Open(origin2_, "bar",
+                   storage::mojom::CacheStorageOwner::kBackgroundFetch));
   EXPECT_EQ(1u, QuotaGetOriginsForType());
 }
 
@@ -2543,7 +2583,7 @@
   quota_manager_proxy_->SimulateQuotaManagerDestroyed();
   RecreateStorageManager();
   quota_client_ = base::MakeRefCounted<CacheStorageQuotaClient>(
-      cache_manager_, CacheStorageOwner::kCacheAPI);
+      cache_manager_, storage::mojom::CacheStorageOwner::kCacheAPI);
 
   EXPECT_TRUE(QuotaDeleteOriginData(origin1_));
   EXPECT_EQ(0, QuotaGetOriginUsage(origin1_));
diff --git a/content/browser/cache_storage/cache_storage_quota_client.cc b/content/browser/cache_storage/cache_storage_quota_client.cc
index 7af4c174..bc68517 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.cc
+++ b/content/browser/cache_storage/cache_storage_quota_client.cc
@@ -14,7 +14,7 @@
 
 CacheStorageQuotaClient::CacheStorageQuotaClient(
     scoped_refptr<CacheStorageManager> cache_manager,
-    CacheStorageOwner owner)
+    storage::mojom::CacheStorageOwner owner)
     : cache_manager_(std::move(cache_manager)), owner_(owner) {}
 
 CacheStorageQuotaClient::~CacheStorageQuotaClient() = default;
@@ -77,11 +77,11 @@
 
 // static
 storage::QuotaClientType CacheStorageQuotaClient::GetClientTypeFromOwner(
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   switch (owner) {
-    case CacheStorageOwner::kCacheAPI:
+    case storage::mojom::CacheStorageOwner::kCacheAPI:
       return storage::QuotaClientType::kServiceWorkerCache;
-    case CacheStorageOwner::kBackgroundFetch:
+    case storage::mojom::CacheStorageOwner::kBackgroundFetch:
       return storage::QuotaClientType::kBackgroundFetch;
   }
 }
diff --git a/content/browser/cache_storage/cache_storage_quota_client.h b/content/browser/cache_storage/cache_storage_quota_client.h
index bdccd07..6eee96c 100644
--- a/content/browser/cache_storage/cache_storage_quota_client.h
+++ b/content/browser/cache_storage/cache_storage_quota_client.h
@@ -7,6 +7,7 @@
 
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/common/content_export.h"
 #include "storage/browser/quota/quota_client.h"
 #include "storage/browser/quota/quota_client_type.h"
@@ -16,7 +17,6 @@
 namespace content {
 
 class CacheStorageManager;
-enum class CacheStorageOwner;
 
 // CacheStorageQuotaClient is owned by the QuotaManager. There is one per
 // CacheStorageManager/CacheStorageOwner tuple.  Created and accessed on
@@ -24,7 +24,7 @@
 class CONTENT_EXPORT CacheStorageQuotaClient : public storage::QuotaClient {
  public:
   CacheStorageQuotaClient(scoped_refptr<CacheStorageManager> cache_manager,
-                          CacheStorageOwner owner);
+                          storage::mojom::CacheStorageOwner owner);
 
   // QuotaClient.
   void OnQuotaManagerDestroyed() override;
@@ -43,13 +43,13 @@
                              PerformStorageCleanupCallback callback) override;
 
   static storage::QuotaClientType GetClientTypeFromOwner(
-      CacheStorageOwner owner);
+      storage::mojom::CacheStorageOwner owner);
 
  private:
   ~CacheStorageQuotaClient() override;
 
   const scoped_refptr<CacheStorageManager> cache_manager_;
-  const CacheStorageOwner owner_;
+  const storage::mojom::CacheStorageOwner owner_;
 
   DISALLOW_COPY_AND_ASSIGN(CacheStorageQuotaClient);
 };
diff --git a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.cc b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.cc
index bb5e5f07..0221b14 100644
--- a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.cc
+++ b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.cc
@@ -23,7 +23,7 @@
                               blink::mojom::CacheStorageError)>;
 
   Inner(const url::Origin& origin,
-        CacheStorageOwner owner,
+        storage::mojom::CacheStorageOwner owner,
         scoped_refptr<CacheStorageContextWithManager> context) {
     scoped_refptr<CacheStorageManager> manager = context->CacheManager();
     if (manager)
@@ -158,7 +158,7 @@
 
 CrossSequenceCacheStorage::CrossSequenceCacheStorage(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     scoped_refptr<base::SequencedTaskRunner> target_task_runner,
     scoped_refptr<CacheStorageContextWithManager> context)
     : CacheStorage(origin),
diff --git a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.h b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.h
index d4a8a41..d7ae67bd 100644
--- a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.h
+++ b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage.h
@@ -8,6 +8,7 @@
 #include "base/memory/weak_ptr.h"
 #include "base/sequence_checker.h"
 #include "base/threading/sequence_bound.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 
@@ -29,7 +30,7 @@
  public:
   CrossSequenceCacheStorage(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       scoped_refptr<base::SequencedTaskRunner> target_task_runner,
       scoped_refptr<CacheStorageContextWithManager> context);
 
diff --git a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.cc b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.cc
index df47e3e..90e8851 100644
--- a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.cc
+++ b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.cc
@@ -25,20 +25,20 @@
     DCHECK(target_manager_);
   }
 
-  void GetAllOriginsUsage(CacheStorageOwner owner,
+  void GetAllOriginsUsage(storage::mojom::CacheStorageOwner owner,
                           CacheStorageContext::GetUsageInfoCallback callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     target_manager_->GetAllOriginsUsage(owner, std::move(callback));
   }
 
   void GetOriginUsage(const url::Origin& origin_url,
-                      CacheStorageOwner owner,
+                      storage::mojom::CacheStorageOwner owner,
                       storage::QuotaClient::GetOriginUsageCallback callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     target_manager_->GetOriginUsage(origin_url, owner, std::move(callback));
   }
 
-  void GetOrigins(CacheStorageOwner owner,
+  void GetOrigins(storage::mojom::CacheStorageOwner owner,
                   storage::QuotaClient::GetOriginsForTypeCallback callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     target_manager_->GetOrigins(owner, std::move(callback));
@@ -46,7 +46,7 @@
 
   void GetOriginsForHost(
       const std::string& host,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForHostCallback callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     target_manager_->GetOriginsForHost(host, owner, std::move(callback));
@@ -54,7 +54,7 @@
 
   void DeleteOriginData(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::DeleteOriginDataCallback callback) {
     DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
     target_manager_->DeleteOriginData(origin, owner, std::move(callback));
@@ -74,7 +74,7 @@
 
 CacheStorageHandle CrossSequenceCacheStorageManager::OpenCacheStorage(
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   // Construct the CrossSequenceCacheStorage object immediately on our current
   // sequence.  This is necessary in order to return a Handle synchronously.
@@ -86,7 +86,7 @@
 }
 
 void CrossSequenceCacheStorageManager::GetAllOriginsUsage(
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     CacheStorageContext::GetUsageInfoCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   inner_.Post(FROM_HERE, &Inner::GetAllOriginsUsage, owner,
@@ -95,7 +95,7 @@
 
 void CrossSequenceCacheStorageManager::GetOriginUsage(
     const url::Origin& origin_url,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginUsageCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   inner_.Post(FROM_HERE, &Inner::GetOriginUsage, origin_url, owner,
@@ -103,7 +103,7 @@
 }
 
 void CrossSequenceCacheStorageManager::GetOrigins(
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginsForTypeCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   inner_.Post(FROM_HERE, &Inner::GetOrigins, owner,
@@ -112,7 +112,7 @@
 
 void CrossSequenceCacheStorageManager::GetOriginsForHost(
     const std::string& host,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginsForHostCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   inner_.Post(FROM_HERE, &Inner::GetOriginsForHost, host, owner,
@@ -121,7 +121,7 @@
 
 void CrossSequenceCacheStorageManager::DeleteOriginData(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::DeleteOriginDataCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   inner_.Post(FROM_HERE, &Inner::DeleteOriginData, origin, owner,
@@ -130,7 +130,7 @@
 
 void CrossSequenceCacheStorageManager::DeleteOriginData(
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DeleteOriginData(origin, owner, base::DoNothing());
 }
diff --git a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.h b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.h
index 489ee5b..bd76a2e 100644
--- a/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.h
+++ b/content/browser/cache_storage/cross_sequence/cross_sequence_cache_storage_manager.h
@@ -7,6 +7,7 @@
 
 #include "base/sequence_checker.h"
 #include "base/threading/sequence_bound.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 
 namespace content {
@@ -28,28 +29,29 @@
       scoped_refptr<CacheStorageContextWithManager> context);
 
   // CacheStorageManager
-  CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
-                                      CacheStorageOwner owner) override;
+  CacheStorageHandle OpenCacheStorage(
+      const url::Origin& origin,
+      storage::mojom::CacheStorageOwner owner) override;
   void GetAllOriginsUsage(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       CacheStorageContext::GetUsageInfoCallback callback) override;
   void GetOriginUsage(
       const url::Origin& origin_url,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginUsageCallback callback) override;
   void GetOrigins(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForTypeCallback callback) override;
   void GetOriginsForHost(
       const std::string& host,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForHostCallback callback) override;
   void DeleteOriginData(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::DeleteOriginDataCallback callback) override;
   void DeleteOriginData(const url::Origin& origin,
-                        CacheStorageOwner owner) override;
+                        storage::mojom::CacheStorageOwner owner) override;
   void SetBlobParametersForCache(
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context) override;
 
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.cc b/content/browser/cache_storage/legacy/legacy_cache_storage.cc
index 0c0beb6..5e85bd8 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage.cc
@@ -99,7 +99,7 @@
               scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
               LegacyCacheStorage* cache_storage,
               const url::Origin& origin,
-              CacheStorageOwner owner)
+              storage::mojom::CacheStorageOwner owner)
       : cache_task_runner_(cache_task_runner),
         scheduler_task_runner_(std::move(scheduler_task_runner)),
         quota_manager_proxy_(std::move(quota_manager_proxy)),
@@ -158,7 +158,7 @@
   LegacyCacheStorage* cache_storage_;
 
   url::Origin origin_;
-  CacheStorageOwner owner_;
+  storage::mojom::CacheStorageOwner owner_;
 };
 
 // Creates memory-only ServiceWorkerCaches. Because these caches have no
@@ -174,7 +174,7 @@
                scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
                LegacyCacheStorage* cache_storage,
                const url::Origin& origin,
-               CacheStorageOwner owner)
+               storage::mojom::CacheStorageOwner owner)
       : CacheLoader(cache_task_runner,
                     std::move(scheduler_task_runner),
                     std::move(quota_manager_proxy),
@@ -246,7 +246,7 @@
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
       LegacyCacheStorage* cache_storage,
       const url::Origin& origin,
-      CacheStorageOwner owner)
+      storage::mojom::CacheStorageOwner owner)
       : CacheLoader(cache_task_runner,
                     std::move(scheduler_task_runner),
                     std::move(quota_manager_proxy),
@@ -589,7 +589,7 @@
     scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
     LegacyCacheStorageManager* cache_storage_manager,
     const url::Origin& origin,
-    CacheStorageOwner owner)
+    storage::mojom::CacheStorageOwner owner)
     : CacheStorage(origin),
       initialized_(false),
       initializing_(false),
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage.h b/content/browser/cache_storage/legacy/legacy_cache_storage.h
index 145f49d..516ca13 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage.h
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage.h
@@ -17,6 +17,7 @@
 #include "base/memory/weak_ptr.h"
 #include "build/build_config.h"
 #include "components/services/storage/public/mojom/blob_storage_context.mojom.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage.h"
 #include "content/browser/cache_storage/cache_storage_cache_observer.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
@@ -35,7 +36,6 @@
 namespace content {
 class CacheStorageIndex;
 class CacheStorageScheduler;
-enum class CacheStorageOwner;
 class LegacyCacheStorageManager;
 
 namespace cache_storage_manager_unittest {
@@ -65,7 +65,7 @@
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context,
       LegacyCacheStorageManager* cache_storage_manager,
       const url::Origin& origin,
-      CacheStorageOwner owner);
+      storage::mojom::CacheStorageOwner owner);
 
   // Any unfinished asynchronous operations may not complete or call their
   // callbacks.
@@ -317,7 +317,7 @@
   scoped_refptr<BlobStorageContextWrapper> blob_storage_context_;
 
   // The owner that this CacheStorage is associated with.
-  CacheStorageOwner owner_;
+  storage::mojom::CacheStorageOwner owner_;
 
   CacheStorageSchedulerId init_id_ = -1;
 
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
index 349446b..1fc6fe2 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
@@ -549,7 +549,7 @@
 std::unique_ptr<LegacyCacheStorageCache>
 LegacyCacheStorageCache::CreateMemoryCache(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     const std::string& cache_name,
     LegacyCacheStorage* cache_storage,
     scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
@@ -570,7 +570,7 @@
 std::unique_ptr<LegacyCacheStorageCache>
 LegacyCacheStorageCache::CreatePersistentCache(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     const std::string& cache_name,
     LegacyCacheStorage* cache_storage,
     const base::FilePath& path,
@@ -1022,7 +1022,7 @@
 
 LegacyCacheStorageCache::LegacyCacheStorageCache(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     const std::string& cache_name,
     const base::FilePath& path,
     LegacyCacheStorage* cache_storage,
@@ -1079,7 +1079,7 @@
     return;
   }
 
-  if (owner_ != CacheStorageOwner::kBackgroundFetch &&
+  if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch &&
       (!options || !options->ignore_method) && request &&
       !request->method.empty() &&
       request->method != net::HttpRequestHeaders::kGetMethod) {
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
index 659ed7c..c35024f4 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.h
@@ -17,6 +17,7 @@
 #include "base/macros.h"
 #include "base/memory/weak_ptr.h"
 #include "base/optional.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_cache.h"
 #include "content/browser/cache_storage/cache_storage_handle.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
@@ -41,7 +42,6 @@
 class CacheStorageCacheEntryHandler;
 class CacheStorageCacheObserver;
 class CacheStorageScheduler;
-enum class CacheStorageOwner;
 class LegacyCacheStorage;
 struct PutContext;
 
@@ -64,7 +64,7 @@
 
   static std::unique_ptr<LegacyCacheStorageCache> CreateMemoryCache(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       const std::string& cache_name,
       LegacyCacheStorage* cache_storage,
       scoped_refptr<base::SequencedTaskRunner> scheduler_task_runner,
@@ -73,7 +73,7 @@
       std::unique_ptr<crypto::SymmetricKey> cache_padding_key);
   static std::unique_ptr<LegacyCacheStorageCache> CreatePersistentCache(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       const std::string& cache_name,
       LegacyCacheStorage* cache_storage,
       const base::FilePath& path,
@@ -244,7 +244,7 @@
 
   LegacyCacheStorageCache(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       const std::string& cache_name,
       const base::FilePath& path,
       LegacyCacheStorage* cache_storage,
@@ -509,7 +509,7 @@
   std::unique_ptr<disk_cache::Backend> backend_;
 
   url::Origin origin_;
-  CacheStorageOwner owner_;
+  storage::mojom::CacheStorageOwner owner_;
   const std::string cache_name_;
   base::FilePath path_;
 
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
index 52f34e2..5503dee 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.cc
@@ -128,7 +128,7 @@
 void ListOriginsAndLastModifiedOnTaskRunner(
     std::vector<StorageUsageInfo>* usages,
     base::FilePath root_path,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   base::FileEnumerator file_enum(root_path, false /* recursive */,
                                  base::FileEnumerator::DIRECTORIES);
 
@@ -162,9 +162,10 @@
     auto origin_path = LegacyCacheStorageManager::ConstructOriginPath(
         root_path, origin, owner);
     if (path != origin_path) {
-      CacheStorageOwner other_owner = owner == CacheStorageOwner::kCacheAPI
-                                          ? CacheStorageOwner::kBackgroundFetch
-                                          : CacheStorageOwner::kCacheAPI;
+      storage::mojom::CacheStorageOwner other_owner =
+          owner == storage::mojom::CacheStorageOwner::kCacheAPI
+              ? storage::mojom::CacheStorageOwner::kBackgroundFetch
+              : storage::mojom::CacheStorageOwner::kCacheAPI;
       auto other_owner_path = LegacyCacheStorageManager::ConstructOriginPath(
           root_path, origin, other_owner);
       // Some of the paths in the |root_path| directory are for a different
@@ -186,8 +187,9 @@
   }
 }
 
-std::vector<url::Origin> ListOriginsOnTaskRunner(base::FilePath root_path,
-                                                 CacheStorageOwner owner) {
+std::vector<url::Origin> ListOriginsOnTaskRunner(
+    base::FilePath root_path,
+    storage::mojom::CacheStorageOwner owner) {
   std::vector<StorageUsageInfo> usages;
   ListOriginsAndLastModifiedOnTaskRunner(&usages, root_path, owner);
 
@@ -269,7 +271,7 @@
 
 CacheStorageHandle LegacyCacheStorageManager::OpenCacheStorage(
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
   // Wait to create the MemoryPressureListener until the first CacheStorage
@@ -323,7 +325,7 @@
 void LegacyCacheStorageManager::CacheStorageUnreferenced(
     LegacyCacheStorage* cache_storage,
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DCHECK(cache_storage);
   cache_storage->AssertUnreferenced();
@@ -337,7 +339,7 @@
 }
 
 void LegacyCacheStorageManager::GetAllOriginsUsage(
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     CacheStorageContext::GetUsageInfoCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -392,8 +394,8 @@
       scheduler_task_runner_->PostTask(FROM_HERE, barrier_closure);
       continue;
     }
-    CacheStorageHandle cache_storage =
-        OpenCacheStorage(usage.origin, CacheStorageOwner::kCacheAPI);
+    CacheStorageHandle cache_storage = OpenCacheStorage(
+        usage.origin, storage::mojom::CacheStorageOwner::kCacheAPI);
     LegacyCacheStorage::From(cache_storage)
         ->Size(base::BindOnce(&OneOriginSizeReported, barrier_closure, &usage));
   }
@@ -401,7 +403,7 @@
 
 void LegacyCacheStorageManager::GetOriginUsage(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginUsageCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -410,7 +412,7 @@
 }
 
 void LegacyCacheStorageManager::GetOrigins(
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginsForTypeCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -433,7 +435,7 @@
 
 void LegacyCacheStorageManager::GetOriginsForHost(
     const std::string& host,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::GetOriginsForHostCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -459,7 +461,7 @@
 
 void LegacyCacheStorageManager::DeleteOriginData(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::DeleteOriginDataCallback callback) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
 
@@ -478,15 +480,16 @@
                      std::move(callback), base::WrapUnique(cache_storage)));
 }
 
-void LegacyCacheStorageManager::DeleteOriginData(const url::Origin& origin,
-                                                 CacheStorageOwner owner) {
+void LegacyCacheStorageManager::DeleteOriginData(
+    const url::Origin& origin,
+    storage::mojom::CacheStorageOwner owner) {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
   DeleteOriginData(origin, owner, base::DoNothing());
 }
 
 void LegacyCacheStorageManager::DeleteOriginDidClose(
     const url::Origin& origin,
-    CacheStorageOwner owner,
+    storage::mojom::CacheStorageOwner owner,
     storage::QuotaClient::DeleteOriginDataCallback callback,
     std::unique_ptr<LegacyCacheStorage> cache_storage,
     int64_t origin_size) {
@@ -500,7 +503,7 @@
       CacheStorageQuotaClient::GetClientTypeFromOwner(owner), origin,
       blink::mojom::StorageType::kTemporary, -1 * origin_size);
 
-  if (owner == CacheStorageOwner::kCacheAPI)
+  if (owner == storage::mojom::CacheStorageOwner::kCacheAPI)
     NotifyCacheListChanged(origin);
 
   if (IsMemoryBacked()) {
@@ -533,9 +536,9 @@
 base::FilePath LegacyCacheStorageManager::ConstructOriginPath(
     const base::FilePath& root_path,
     const url::Origin& origin,
-    CacheStorageOwner owner) {
+    storage::mojom::CacheStorageOwner owner) {
   std::string identifier = storage::GetIdentifierFromOrigin(origin);
-  if (owner != CacheStorageOwner::kCacheAPI) {
+  if (owner != storage::mojom::CacheStorageOwner::kCacheAPI) {
     identifier += "-" + std::to_string(static_cast<int>(owner));
   }
   const std::string origin_hash = base::SHA1HashString(identifier);
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
index 8266ede..5f5666f 100644
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_manager.h
@@ -15,6 +15,7 @@
 #include "base/memory/memory_pressure_listener.h"
 #include "base/memory/scoped_refptr.h"
 #include "base/sequence_checker.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_context_impl.h"
 #include "content/browser/cache_storage/cache_storage_manager.h"
 #include "content/browser/cache_storage/legacy/legacy_cache_storage.h"
@@ -54,35 +55,37 @@
       LegacyCacheStorageManager* old_manager);
 
   // Map a database identifier (computed from an origin) to the path.
-  static base::FilePath ConstructOriginPath(const base::FilePath& root_path,
-                                            const url::Origin& origin,
-                                            CacheStorageOwner owner);
+  static base::FilePath ConstructOriginPath(
+      const base::FilePath& root_path,
+      const url::Origin& origin,
+      storage::mojom::CacheStorageOwner owner);
 
   // Open the CacheStorage for the given origin and owner.  A reference counting
   // handle is returned which can be stored and used similar to a weak pointer.
-  CacheStorageHandle OpenCacheStorage(const url::Origin& origin,
-                                      CacheStorageOwner owner) override;
+  CacheStorageHandle OpenCacheStorage(
+      const url::Origin& origin,
+      storage::mojom::CacheStorageOwner owner) override;
 
   void GetAllOriginsUsage(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       CacheStorageContext::GetUsageInfoCallback callback) override;
   void GetOriginUsage(
       const url::Origin& origin_url,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginUsageCallback callback) override;
   void GetOrigins(
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForTypeCallback callback) override;
   void GetOriginsForHost(
       const std::string& host,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::GetOriginsForHostCallback callback) override;
   void DeleteOriginData(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::DeleteOriginDataCallback callback) override;
   void DeleteOriginData(const url::Origin& origin,
-                        CacheStorageOwner owner) override;
+                        storage::mojom::CacheStorageOwner owner) override;
 
   void SetBlobParametersForCache(
       scoped_refptr<BlobStorageContextWrapper> blob_storage_context) override;
@@ -97,13 +100,13 @@
   // instance is destroyed and its reference count drops to zero.
   void CacheStorageUnreferenced(LegacyCacheStorage* cache_storage,
                                 const url::Origin& origin,
-                                CacheStorageOwner owner);
+                                storage::mojom::CacheStorageOwner owner);
 
  private:
   friend class cache_storage_manager_unittest::CacheStorageManagerTest;
   friend class CacheStorageContextImpl;
 
-  typedef std::map<std::pair<url::Origin, CacheStorageOwner>,
+  typedef std::map<std::pair<url::Origin, storage::mojom::CacheStorageOwner>,
                    std::unique_ptr<LegacyCacheStorage>>
       CacheStorageMap;
 
@@ -122,7 +125,7 @@
 
   void DeleteOriginDidClose(
       const url::Origin& origin,
-      CacheStorageOwner owner,
+      storage::mojom::CacheStorageOwner owner,
       storage::QuotaClient::DeleteOriginDataCallback callback,
       std::unique_ptr<LegacyCacheStorage> cache_storage,
       int64_t origin_size);
diff --git a/content/browser/child_process_security_policy_impl.cc b/content/browser/child_process_security_policy_impl.cc
index c9f95a6d..d403f389 100644
--- a/content/browser/child_process_security_policy_impl.cc
+++ b/content/browser/child_process_security_policy_impl.cc
@@ -1286,20 +1286,20 @@
 
   for (const network::DataElement& element : *body->elements()) {
     switch (element.type()) {
-      case network::mojom::DataElementType::kFile:
-        if (!CanReadFile(child_id, element.path()))
+      case network::DataElement::Tag::kFile:
+        if (!CanReadFile(child_id,
+                         element.As<network::DataElementFile>().path()))
           return false;
         break;
 
-      case network::mojom::DataElementType::kBytes:
+      case network::DataElement::Tag::kBytes:
         // Data is self-contained within |body| - no need to check access.
         break;
 
-      case network::mojom::DataElementType::kDataPipe:
+      case network::DataElement::Tag::kDataPipe:
         // Data is self-contained within |body| - no need to check access.
         break;
 
-      case network::mojom::DataElementType::kUnknown:
       default:
         // Fail safe - deny access.
         NOTREACHED();
diff --git a/content/browser/devtools/protocol/network_handler.cc b/content/browser/devtools/protocol/network_handler.cc
index 2e0dd90..bb92e30 100644
--- a/content/browser/devtools/protocol/network_handler.cc
+++ b/content/browser/devtools/protocol/network_handler.cc
@@ -524,14 +524,15 @@
     return false;
   for (const auto& element : *elements) {
     // TODO(caseq): Also support blobs.
-    if (element.type() != network::mojom::DataElementType::kBytes)
+    if (element.type() != network::DataElement::Tag::kBytes)
       return false;
-    auto bytes = protocol::Binary::fromSpan(
-        reinterpret_cast<const uint8_t*>(element.bytes()), element.length());
+    const std::vector<uint8_t>& bytes =
+        element.As<network::DataElementBytes>().bytes();
     auto data_entry = protocol::Network::PostDataEntry::Create().Build();
-    data_entry->SetBytes(std::move(bytes));
+    data_entry->SetBytes(
+        protocol::Binary::fromSpan(bytes.data(), bytes.size()));
     data_entries->push_back(std::move(data_entry));
-    result->append(element.bytes(), element.length());
+    result->append(reinterpret_cast<const char*>(bytes.data()), bytes.size());
   }
   return true;
 }
diff --git a/content/browser/direct_sockets/direct_sockets_browsertest.cc b/content/browser/direct_sockets/direct_sockets_browsertest.cc
index 074e0f9..f982e596 100644
--- a/content/browser/direct_sockets/direct_sockets_browsertest.cc
+++ b/content/browser/direct_sockets/direct_sockets_browsertest.cc
@@ -59,58 +59,40 @@
 class MockHostResolver : public network::mojom::HostResolver {
  public:
   explicit MockHostResolver(
-      mojo::PendingReceiver<network::mojom::HostResolver> resolver_receiver)
-      : receiver_(this) {
+      mojo::PendingReceiver<network::mojom::HostResolver> resolver_receiver,
+      net::HostResolver* internal_resolver)
+      : receiver_(this), internal_resolver_(internal_resolver) {
     receiver_.Bind(std::move(resolver_receiver));
   }
 
   MockHostResolver(const MockHostResolver&) = delete;
   MockHostResolver& operator=(const MockHostResolver&) = delete;
 
-  static std::map<std::string, std::string>& known_hosts() {
-    static base::NoDestructor<std::map<std::string, std::string>> hosts;
-    return *hosts;
-  }
-
-  void ResolveHost(const ::net::HostPortPair& host_port_pair,
+  void ResolveHost(const ::net::HostPortPair& host,
                    const ::net::NetworkIsolationKey& network_isolation_key,
                    network::mojom::ResolveHostParametersPtr optional_parameters,
                    ::mojo::PendingRemote<network::mojom::ResolveHostClient>
                        pending_response_client) override {
+    DCHECK(!internal_request_);
+    DCHECK(!response_client_.is_bound());
+
+    internal_request_ = internal_resolver_->CreateRequest(
+        host, network_isolation_key,
+        net::NetLogWithSource::Make(net::NetLog::Get(),
+                                    net::NetLogSourceType::NONE),
+        base::nullopt);
     mojo::Remote<network::mojom::ResolveHostClient> response_client(
         std::move(pending_response_client));
 
-    std::string host = host_port_pair.host();
-    auto iter = known_hosts().find(host);
-    if (iter != known_hosts().end())
-      host = iter->second;
-
-    net::IPAddress remote_address;
-    // TODO(crbug.com/1141241): Replace if/else with AssignFromIPLiteral.
-    if (host.find(':') != std::string::npos) {
-      // GURL expects IPv6 hostnames to be surrounded with brackets.
-      std::string host_brackets = base::StrCat({"[", host, "]"});
-      url::Component host_comp(0, host_brackets.size());
-      std::array<uint8_t, 16> bytes;
-      EXPECT_TRUE(url::IPv6AddressToNumber(host_brackets.data(), host_comp,
-                                           bytes.data()));
-      remote_address = net::IPAddress(bytes.data(), bytes.size());
-    } else {
-      // Otherwise the string is an IPv4 address.
-      url::Component host_comp(0, host.size());
-      std::array<uint8_t, 4> bytes;
-      int num_components;
-      url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
-          host.data(), host_comp, bytes.data(), &num_components);
-      EXPECT_EQ(family, url::CanonHostInfo::IPV4);
-      EXPECT_EQ(num_components, 4);
-      remote_address = net::IPAddress(bytes.data(), bytes.size());
+    int rv = internal_request_->Start(
+        base::BindOnce(&MockHostResolver::OnComplete, base::Unretained(this)));
+    if (rv != net::ERR_IO_PENDING) {
+      response_client->OnComplete(rv, internal_request_->GetResolveErrorInfo(),
+                                  internal_request_->GetAddressResults());
+      return;
     }
-    EXPECT_EQ(remote_address.ToString(), host);
 
-    response_client->OnComplete(net::OK, net::ResolveErrorInfo(),
-                                net::AddressList::CreateFromIPAddress(
-                                    remote_address, host_port_pair.port()));
+    response_client_ = std::move(response_client);
   }
 
   void MdnsListen(
@@ -122,7 +104,20 @@
   }
 
  private:
+  void OnComplete(int error) {
+    DCHECK(response_client_.is_bound());
+    DCHECK(internal_request_);
+
+    response_client_->OnComplete(error,
+                                 internal_request_->GetResolveErrorInfo(),
+                                 internal_request_->GetAddressResults());
+    response_client_.reset();
+  }
+
+  std::unique_ptr<net::HostResolver::ResolveHostRequest> internal_request_;
+  mojo::Remote<network::mojom::ResolveHostClient> response_client_;
   mojo::Receiver<network::mojom::HostResolver> receiver_;
+  net::HostResolver* const internal_resolver_;
 };
 
 class MockNetworkContext : public network::TestNetworkContext {
@@ -163,13 +158,29 @@
       const base::Optional<net::DnsConfigOverrides>& config_overrides,
       mojo::PendingReceiver<network::mojom::HostResolver> receiver) override {
     DCHECK(!config_overrides.has_value());
+    DCHECK(!internal_resolver_);
     DCHECK(!host_resolver_);
-    host_resolver_ = std::make_unique<MockHostResolver>(std::move(receiver));
+
+    internal_resolver_ = net::HostResolver::CreateStandaloneResolver(
+        net::NetLog::Get(), /*options=*/base::nullopt, host_mapping_rules_,
+        /*enable_caching=*/false);
+    host_resolver_ = std::make_unique<MockHostResolver>(
+        std::move(receiver), internal_resolver_.get());
+  }
+
+  // If set to non-empty, the mapping rules will be applied to requests to the
+  // created internal host resolver. See MappedHostResolver for details. Should
+  // be called before CreateHostResolver().
+  void set_host_mapping_rules(std::string host_mapping_rules) {
+    DCHECK(!internal_resolver_);
+    host_mapping_rules_ = std::move(host_mapping_rules);
   }
 
  private:
   const net::Error result_;
   std::vector<RecordedCall> history_;
+  std::string host_mapping_rules_;
+  std::unique_ptr<net::HostResolver> internal_resolver_;
   std::unique_ptr<network::mojom::HostResolver> host_resolver_;
 };
 
@@ -287,9 +298,11 @@
 
   const char kExampleHostname[] = "mail.example.com";
   const char kExampleAddress[] = "98.76.54.32";
-  MockHostResolver::known_hosts()[kExampleHostname] = kExampleAddress;
+  const std::string mapping_rules =
+      base::StringPrintf("MAP %s %s", kExampleHostname, kExampleAddress);
 
   MockNetworkContext mock_network_context(net::OK);
+  mock_network_context.set_host_mapping_rules(mapping_rules);
   DirectSocketsServiceImpl::SetNetworkContextForTesting(&mock_network_context);
   const std::string expected_result = base::StringPrintf(
       "openTcp succeeded: {remoteAddress: \"%s\", remotePort: 993}",
diff --git a/content/browser/direct_sockets/direct_sockets_service_impl.cc b/content/browser/direct_sockets/direct_sockets_service_impl.cc
index b1176ab..5ef284b 100644
--- a/content/browser/direct_sockets/direct_sockets_service_impl.cc
+++ b/content/browser/direct_sockets/direct_sockets_service_impl.cc
@@ -53,7 +53,6 @@
   return local_addr;
 }
 
-// True if |hostname| ends with either ".local" or ".local.".
 bool ResemblesMulticastDNSName(const std::string& hostname) {
   return base::EndsWith(hostname, ".local") ||
          base::EndsWith(hostname, ".local.");
diff --git a/content/browser/media/session/media_session_browsertest.cc b/content/browser/media/session/media_session_browsertest.cc
index b016a97..7cbada9 100644
--- a/content/browser/media/session/media_session_browsertest.cc
+++ b/content/browser/media/session/media_session_browsertest.cc
@@ -249,7 +249,8 @@
 
 // Flaky on Linux and Android and Mac. http://crbug.com/1157239,
 // http://crbug.com/1157319
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MAC)
+#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MAC) || \
+    defined(OS_CHROMEOS)
 #define MAYBE_SimplePlayPause DISABLED_SimplePlayPause
 #else
 #define MAYBE_SimplePlayPause SimplePlayPause
diff --git a/content/browser/prerender/prerender_browsertest.cc b/content/browser/prerender/prerender_browsertest.cc
index 2ae486f..b526b33 100644
--- a/content/browser/prerender/prerender_browsertest.cc
+++ b/content/browser/prerender/prerender_browsertest.cc
@@ -8,6 +8,7 @@
 #include "base/thread_annotations.h"
 #include "content/browser/prerender/prerender_host.h"
 #include "content/browser/prerender/prerender_host_registry.h"
+#include "content/browser/renderer_host/frame_tree_node.h"
 #include "content/browser/renderer_host/render_frame_host_impl.h"
 #include "content/browser/storage_partition_impl.h"
 #include "content/public/browser/browser_context.h"
@@ -133,6 +134,49 @@
 
   bool IsActivationDisabled() const { return GetParam(); }
 
+  void TestRenderFrameHostPrerenderingState(const GURL& prerender_url) {
+    const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html");
+
+    // Navigate to an initial page.
+    ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
+
+    // The initial page should not be for prerendering.
+    RenderFrameHostImpl* initiator_render_frame_host =
+        static_cast<RenderFrameHostImpl*>(
+            shell()->web_contents()->GetMainFrame());
+    EXPECT_FALSE(initiator_render_frame_host->IsPrerendering());
+    // Start a prerender.
+    AddPrerender(prerender_url);
+    PrerenderHostRegistry& registry = GetPrerenderHostRegistry();
+    PrerenderHost* prerender_host =
+        registry.FindHostByUrlForTesting(prerender_url);
+
+    // Verify all RenderFrameHostImpl in the prerendered page know the
+    // prerendering state.
+    RenderFrameHostImpl* prerendered_render_frame_host =
+        prerender_host->GetPrerenderedMainFrameHostForTesting();
+    std::vector<RenderFrameHost*> frames =
+        prerendered_render_frame_host->GetFramesInSubtree();
+    for (auto* frame : frames) {
+      auto* rfhi = static_cast<RenderFrameHostImpl*>(frame);
+      EXPECT_TRUE(rfhi->IsPrerendering());
+    }
+
+    // Activate the prerendered page.
+    NavigateWithLocation(prerender_url);
+
+    // The activated page should no longer be in the prerendering state.
+    RenderFrameHostImpl* navigated_render_frame_host =
+        static_cast<RenderFrameHostImpl*>(
+            shell()->web_contents()->GetMainFrame());
+    // The new page shouldn't be in the prerendering state.
+    frames = navigated_render_frame_host->GetFramesInSubtree();
+    for (auto* frame : frames) {
+      auto* rfhi = static_cast<RenderFrameHostImpl*>(frame);
+      EXPECT_FALSE(rfhi->IsPrerendering());
+    }
+  }
+
  private:
   net::test_server::EmbeddedTestServer ssl_server_{
       net::test_server::EmbeddedTestServer::TYPE_HTTPS};
@@ -274,56 +318,6 @@
   }
 }
 
-IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, InformedRenderFrameHost) {
-  const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html");
-  const GURL kPrerenderingUrl = GetUrl("/empty.html");
-
-  // Navigate to an initial page.
-  ASSERT_TRUE(NavigateToURL(shell(), kInitialUrl));
-  ASSERT_EQ(shell()->web_contents()->GetURL(), kInitialUrl);
-
-  // The initial page should not be for prerendering.
-  RenderFrameHostImpl* initiator_render_frame_host =
-      static_cast<RenderFrameHostImpl*>(
-          shell()->web_contents()->GetMainFrame());
-  EXPECT_FALSE(initiator_render_frame_host->IsPrerendering());
-
-  // Add <link rel=prerender> that will prerender `kPrerenderingUrl`.
-  ASSERT_EQ(GetRequestCount(kPrerenderingUrl), 0);
-  AddPrerender(kPrerenderingUrl);
-  EXPECT_EQ(GetRequestCount(kPrerenderingUrl), 1);
-
-  // A prerender host for the URL should be registered.
-  PrerenderHostRegistry& registry = GetPrerenderHostRegistry();
-  PrerenderHost* prerender_host =
-      registry.FindHostByUrlForTesting(kPrerenderingUrl);
-  EXPECT_NE(prerender_host, nullptr);
-
-  // Verify the corresponding RenderFrameHostImpl knows the prerendering state.
-  RenderFrameHostImpl* prerendered_render_frame_host =
-      prerender_host->GetPrerenderedMainFrameHostForTesting();
-  EXPECT_TRUE(prerendered_render_frame_host->IsPrerendering());
-
-  // Activate the prerendered page.
-  NavigateWithLocation(kPrerenderingUrl);
-  if (IsActivationDisabled()) {
-    // Activation is disabled, so the page should newly be rendered instead
-    // of the prerendered page.
-    RenderFrameHostImpl* new_render_frame_host =
-        static_cast<RenderFrameHostImpl*>(
-            shell()->web_contents()->GetMainFrame());
-    EXPECT_NE(prerendered_render_frame_host, new_render_frame_host);
-    // The new page shouldn't be in the prerendering state.
-    EXPECT_FALSE(new_render_frame_host->IsPrerendering());
-  } else {
-    // The prerendered page is activated. The page should no longer be in
-    // the prerendering state.
-    ASSERT_EQ(prerendered_render_frame_host,
-              shell()->web_contents()->GetMainFrame());
-    EXPECT_FALSE(prerendered_render_frame_host->IsPrerendering());
-  }
-}
-
 // Makes sure that activations on navigations for iframes don't happen.
 IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, Activation_iFrame) {
   const GURL kInitialUrl = GetUrl("/prerender/add_prerender.html");
@@ -410,6 +404,18 @@
   EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), kInitialUrl);
 }
 
+// Tests that all RenderFrameHostImpls in the prerendering page know the
+// prerendering state.
+IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, PrerenderIframe) {
+  TestRenderFrameHostPrerenderingState(GetUrl("/page_with_iframe.html"));
+}
+
+// Blank <iframe> is a special case. Tests that the blank iframe knows the
+// prerendering state as well.
+IN_PROC_BROWSER_TEST_P(PrerenderBrowserTest, PrerenderBlankIframe) {
+  TestRenderFrameHostPrerenderingState(GetUrl("/page_with_blank_iframe.html"));
+}
+
 // TODO(https://crbug.com/1132746): Test canceling prerendering.
 
 // TODO(https://crbug.com/1132746): Test prerendering for 404 page, redirection,
diff --git a/content/browser/renderer_host/code_cache_host_impl.cc b/content/browser/renderer_host/code_cache_host_impl.cc
index 8f73fd3..285c870 100644
--- a/content/browser/renderer_host/code_cache_host_impl.cc
+++ b/content/browser/renderer_host/code_cache_host_impl.cc
@@ -11,6 +11,7 @@
 #include "base/task/post_task.h"
 #include "base/threading/thread.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage_context_impl.h"
 #include "content/browser/child_process_security_policy_impl.h"
 #include "content/browser/code_cache/generated_code_cache.h"
@@ -210,7 +211,8 @@
   // storage::mojom::CacheStorageControl remote, similar to IndexedDBControl.
   cache_storage_context_->AddReceiver(
       cross_origin_embedder_policy, mojo::NullRemote(), cache_storage_origin,
-      CacheStorageOwner::kCacheAPI, remote.BindNewPipeAndPassReceiver());
+      storage::mojom::CacheStorageOwner::kCacheAPI,
+      remote.BindNewPipeAndPassReceiver());
 
   // Call the remote pointer directly so we can pass the remote to the callback
   // itself to preserve its lifetime.
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
index c47bf328..302fbaa 100644
--- a/content/browser/renderer_host/navigation_request.cc
+++ b/content/browser/renderer_host/navigation_request.cc
@@ -766,6 +766,12 @@
     }
   }
 
+  // The prerendering state of a sub-frame is decided by its parent.
+  if (base::FeatureList::IsEnabled(blink::features::kPrerender2) &&
+      frame_tree_node->parent()) {
+    is_prerendering = frame_tree_node->parent()->IsPrerendering();
+  }
+
   std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
       frame_tree_node, std::move(common_params), std::move(navigation_params),
       std::move(commit_params), browser_initiated,
@@ -880,6 +886,13 @@
   int initiator_process_id =
       frame_tree_node->current_frame_host()->GetProcess()->GetID();
 
+  // For sub-frame navigations, inherit the prerendering state from the parent.
+  bool is_prerendering = false;
+  if (base::FeatureList::IsEnabled(blink::features::kPrerender2) &&
+      frame_tree_node->parent()) {
+    is_prerendering = frame_tree_node->parent()->IsPrerendering();
+  }
+
   // `was_opener_suppressed` can be true for renderer initiated navigations, but
   // only in cases which get routed through `CreateBrowserInitiated()` instead.
   std::unique_ptr<NavigationRequest> navigation_request(new NavigationRequest(
@@ -888,8 +901,9 @@
       false,  // browser_initiated
       true,   // from_begin_navigation
       false,  // is_for_commit
-      false,  // is_prerendering
-      nullptr, entry,
+      is_prerendering,
+      nullptr,  // frame_entry
+      entry,
       nullptr,  // navigation_ui_data
       std::move(navigation_client), std::move(navigation_initiator),
       nullptr,  // rfh_restored_from_back_forward_cache
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
index 4b68268..c634bac 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7812,6 +7812,9 @@
   DCHECK(is_prerendering_);
   is_prerendering_ = false;
 
+  for (auto& child : children_)
+    child->current_frame_host()->OnPrerenderedPageActivated();
+
   // TODO(https://crbug.com/1132752): Inform `broker_` that the prerendered
   // frame is activated.
 }
@@ -8781,6 +8784,14 @@
     // create one in order to properly issue DidFinishNavigation calls to
     // WebContentsObservers.
     DCHECK(is_initial_empty_commit || is_same_document_navigation);
+
+    // Handle src-less <iframe> for prerendering.
+    // This is a special case that does not go through CommitNavigation path.
+    if (base::FeatureList::IsEnabled(blink::features::kPrerender2) &&
+        is_initial_empty_commit && !is_main_frame()) {
+      is_prerendering_ = parent_->IsPrerendering();
+    }
+
     // TODO(https://crbug.com/1131832): Do not use |params| to get the values,
     // depend on values known at commit time instead.
     navigation_request = CreateNavigationRequestForCommit(
@@ -10387,6 +10398,13 @@
   return document_used_web_otp_;
 }
 
+void RenderFrameHostImpl::SetPolicyContainerForEarlyCommitAfterCrash(
+    std::unique_ptr<PolicyContainerHost> policy_container_host) {
+  DCHECK_EQ(lifecycle_state_, LifecycleState::kSpeculative);
+  DCHECK(!policy_container_host_);
+  policy_container_host_ = std::move(policy_container_host);
+}
+
 std::ostream& operator<<(std::ostream& o,
                          const RenderFrameHostImpl::LifecycleState& s) {
   return o << LifecycleStateToString(s);
diff --git a/content/browser/renderer_host/render_frame_host_impl.h b/content/browser/renderer_host/render_frame_host_impl.h
index ad68264..484de79 100644
--- a/content/browser/renderer_host/render_frame_host_impl.h
+++ b/content/browser/renderer_host/render_frame_host_impl.h
@@ -1547,6 +1547,14 @@
     return policy_container_host_.get();
   }
 
+  // This is used by RenderFrameHostManager to ensure the replacement
+  // RenderFrameHost is properly initialized when performing an early commit
+  // as a recovery for a crashed frame.
+  // TODO(https://crbug.com/1072817): Remove this logic when removing the
+  // early commit.
+  void SetPolicyContainerForEarlyCommitAfterCrash(
+      std::unique_ptr<PolicyContainerHost> policy_container_host);
+
   // This function mimics DidCommitProvisionalLoad for navigations served from
   // the back-forward cache.
   void DidCommitBackForwardCacheNavigation(
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
index d1446d9..8c5937f 100644
--- a/content/browser/renderer_host/render_frame_host_manager.cc
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
@@ -905,6 +905,20 @@
       if (GetRenderFrameProxyHost(dest_site_instance.get()))
         navigation_rfh->SwapIn();
       navigation_rfh->OnCommittedSpeculativeBeforeNavigationCommit();
+
+      // An Active RenderFrameHost MUST always have a PolicyContainerHost. A new
+      // document is either:
+      // - The initial empty document, via frame creation.
+      // - A new document replacing the previous one, via a navigation.
+      // Here this is an additional case: A new document (in a weird state) is
+      // replacing the one crashed. In this case, it is not entirely clear what
+      // PolicyContainerHost should be used. In the absence of anything better,
+      // we simply keep the PolicyContainerHost that was previously active.
+      // TODO(https://crbug.com/1072817): Remove this logic when removing the
+      // early commit.
+      navigation_rfh->SetPolicyContainerForEarlyCommitAfterCrash(
+          current_frame_host()->policy_container_host()->Clone());
+
       CommitPending(std::move(speculative_render_frame_host_), nullptr,
                     request->coop_status().require_browsing_instance_swap());
     }
@@ -2086,7 +2100,8 @@
     }
   }
 
-  // BrowsingInstance unless the destination URL's cross-origin isolated state
+  // Start the new renderer in a new SiteInstance, but in the current
+  // BrowsingInstance, unless the destination URL's cross-origin isolated state
   // cannot be hosted by it.
   if (IsSiteInstanceCompatibleWithCoopCoepCrossOriginIsolation(
           render_frame_host_->GetSiteInstance(),
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
index 69c62ce..6eb6699b 100644
--- a/content/browser/renderer_host/render_process_host_impl.cc
+++ b/content/browser/renderer_host/render_process_host_impl.cc
@@ -74,6 +74,7 @@
 #include "components/discardable_memory/public/mojom/discardable_shared_memory_manager.mojom.h"
 #include "components/discardable_memory/service/discardable_shared_memory_manager.h"
 #include "components/metrics/single_sample_metrics.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "components/tracing/common/tracing_switches.h"
 #include "components/viz/common/switches.h"
 #include "components/viz/host/gpu_client.h"
@@ -1949,7 +1950,7 @@
   DCHECK_CURRENTLY_ON(BrowserThread::UI);
   storage_partition_impl_->GetCacheStorageContext()->AddReceiver(
       cross_origin_embedder_policy, std::move(coep_reporter_remote), origin,
-      CacheStorageOwner::kCacheAPI, std::move(receiver));
+      storage::mojom::CacheStorageOwner::kCacheAPI, std::move(receiver));
 }
 
 void RenderProcessHostImpl::BindIndexedDB(
diff --git a/content/browser/service_worker/service_worker_browsertest.cc b/content/browser/service_worker/service_worker_browsertest.cc
index 56bff13..7ca9019 100644
--- a/content/browser/service_worker/service_worker_browsertest.cc
+++ b/content/browser/service_worker/service_worker_browsertest.cc
@@ -30,6 +30,7 @@
 #include "base/test/scoped_feature_list.h"
 #include "base/time/time.h"
 #include "build/build_config.h"
+#include "components/services/storage/public/mojom/cache_storage_control.mojom.h"
 #include "content/browser/cache_storage/cache_storage.h"
 #include "content/browser/cache_storage/cache_storage_cache.h"
 #include "content/browser/cache_storage/cache_storage_cache_handle.h"
@@ -2152,7 +2153,8 @@
   void OpenCacheOnCoreThread(int* result, base::OnceClosure continuation) {
     CacheStorageHandle cache_storage =
         cache_storage_context_->CacheManager()->OpenCacheStorage(
-            url::Origin::Create(origin_), CacheStorageOwner::kCacheAPI);
+            url::Origin::Create(origin_),
+            storage::mojom::CacheStorageOwner::kCacheAPI);
     cache_storage.value()->OpenCache(
         cache_name_, /* trace_id = */ 0,
         base::BindOnce(&self::OnCacheStorageOpenCallback, this, result,
diff --git a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
index 73db1d8e..772afca5 100644
--- a/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
+++ b/content/browser/service_worker/service_worker_main_resource_loader_unittest.cc
@@ -197,8 +197,9 @@
     // So far this test expects a single bytes element.
     ASSERT_EQ(1u, elements->size());
     const network::DataElement& element = elements->front();
-    ASSERT_EQ(network::mojom::DataElementType::kBytes, element.type());
-    *out_string = std::string(element.bytes(), element.length());
+    ASSERT_EQ(network::DataElement::Tag::kBytes, element.type());
+    *out_string =
+        std::string(element.As<network::DataElementBytes>().AsStringPiece());
   }
 
   void RunUntilFetchEvent() {
diff --git a/content/browser/speech/speech_recognition_engine_unittest.cc b/content/browser/speech/speech_recognition_engine_unittest.cc
index 4515d1a..9578482 100644
--- a/content/browser/speech/speech_recognition_engine_unittest.cc
+++ b/content/browser/speech/speech_recognition_engine_unittest.cc
@@ -709,15 +709,15 @@
       EXPECT_TRUE(upstream_request);
       EXPECT_TRUE(upstream_request->request.request_body);
       EXPECT_EQ(1u, upstream_request->request.request_body->elements()->size());
-      EXPECT_EQ(
-          network::mojom::DataElementType::kChunkedDataPipe,
-          (*upstream_request->request.request_body->elements())[0].type());
-      network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
-          const_cast<network::TestURLLoaderFactory::PendingRequest*>(
-              upstream_request);
-      chunked_data_pipe_getter_.Bind((*mutable_upstream_request->request
-                                           .request_body->elements_mutable())[0]
-                                         .ReleaseChunkedDataPipeGetter());
+      auto& element =
+          (*upstream_request->request.request_body->elements_mutable())[0];
+      if (element.type() != network::DataElement::Tag::kChunkedDataPipe) {
+        ADD_FAILURE() << "element type mismatch";
+        return "";
+      }
+      chunked_data_pipe_getter_.Bind(
+          element.As<network::DataElementChunkedDataPipe>()
+              .ReleaseChunkedDataPipeGetter());
     }
     mojo::DataPipe data_pipe;
     chunked_data_pipe_getter_->StartReading(
diff --git a/content/browser/speech/speech_recognizer_impl_unittest.cc b/content/browser/speech/speech_recognizer_impl_unittest.cc
index 27700e9..c31e3ff 100644
--- a/content/browser/speech/speech_recognizer_impl_unittest.cc
+++ b/content/browser/speech/speech_recognizer_impl_unittest.cc
@@ -433,15 +433,12 @@
       ASSERT_TRUE(GetUpstreamRequest(&upstream_request));
       ASSERT_TRUE(upstream_request->request.request_body);
       ASSERT_EQ(1u, upstream_request->request.request_body->elements()->size());
-      ASSERT_EQ(
-          network::mojom::DataElementType::kChunkedDataPipe,
-          (*upstream_request->request.request_body->elements())[0].type());
-      network::TestURLLoaderFactory::PendingRequest* mutable_upstream_request =
-          const_cast<network::TestURLLoaderFactory::PendingRequest*>(
-              upstream_request);
-      chunked_data_pipe_getter.Bind((*mutable_upstream_request->request
-                                          .request_body->elements_mutable())[0]
-                                        .ReleaseChunkedDataPipeGetter());
+      auto& element =
+          (*upstream_request->request.request_body->elements_mutable())[0];
+      ASSERT_EQ(network::DataElement::Tag::kChunkedDataPipe, element.type());
+      chunked_data_pipe_getter.Bind(
+          element.As<network::DataElementChunkedDataPipe>()
+              .ReleaseChunkedDataPipeGetter());
       chunked_data_pipe_getter->StartReading(
           std::move(data_pipe.producer_handle));
     }
diff --git a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
index 6bb8191..3b8c008 100644
--- a/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
+++ b/content/renderer/service_worker/service_worker_subresource_loader_unittest.cc
@@ -204,13 +204,14 @@
     // So far this test expects a single element (bytes or data pipe).
     ASSERT_EQ(1u, elements->size());
     network::DataElement& element = elements->front();
-    if (element.type() == network::mojom::DataElementType::kBytes) {
-      *out_string = std::string(element.bytes(), element.length());
-    } else if (element.type() == network::mojom::DataElementType::kDataPipe) {
+    if (element.type() == network::DataElement::Tag::kBytes) {
+      *out_string =
+          std::string(element.As<network::DataElementBytes>().AsStringPiece());
+    } else if (element.type() == network::DataElement::Tag::kDataPipe) {
       // Read the content into |data_pipe|.
       mojo::DataPipe data_pipe;
       mojo::Remote<network::mojom::DataPipeGetter> remote(
-          element.ReleaseDataPipeGetter());
+          element.As<network::DataElementDataPipe>().ReleaseDataPipeGetter());
       base::RunLoop run_loop;
       remote->Read(
           std::move(data_pipe.producer_handle),
diff --git a/content/test/gpu/gpu_tests/gpu_helper.py b/content/test/gpu/gpu_tests/gpu_helper.py
index 16621aad..ce9c9d5 100644
--- a/content/test/gpu/gpu_tests/gpu_helper.py
+++ b/content/test/gpu/gpu_tests/gpu_helper.py
@@ -142,14 +142,17 @@
   retval = 'skia-renderer-disabled'
   skia_renderer_enabled = (
       gpu_feature_status
-      and gpu_feature_status.get('skia_renderer') == 'enabled_on')
+      and gpu_feature_status.get('skia_renderer') == 'enabled_on'
+      and gpu_feature_status.get('gpu_compositing') == 'enabled')
   if skia_renderer_enabled:
     if HasDawnSkiaRenderer(extra_browser_args):
       retval = 'skia-renderer-dawn'
-    elif HasGlSkiaRenderer(extra_browser_args):
-      retval = 'skia-renderer-gl'
     elif HasVulkanSkiaRenderer(gpu_feature_status):
       retval = 'skia-renderer-vulkan'
+    # The check for GL must come after Vulkan since the 'opengl' feature can be
+    # enabled for WebGL and interop even if SkiaRenderer is using Vulkan.
+    elif HasGlSkiaRenderer(gpu_feature_status):
+      retval = 'skia-renderer-gl'
   return retval
 
 
@@ -162,12 +165,8 @@
   return False
 
 
-def HasGlSkiaRenderer(extra_browser_args):
-  if extra_browser_args:
-    for arg in extra_browser_args:
-      if '--use-gl=' in arg:
-        return True
-  return False
+def HasGlSkiaRenderer(gpu_feature_status):
+  return gpu_feature_status and gpu_feature_status.get('opengl') == 'enabled_on'
 
 
 def HasVulkanSkiaRenderer(gpu_feature_status):
diff --git a/docs/workflow/debugging-with-swarming.md b/docs/workflow/debugging-with-swarming.md
index ace0bb8..b0845a7 100644
--- a/docs/workflow/debugging-with-swarming.md
+++ b/docs/workflow/debugging-with-swarming.md
@@ -16,7 +16,7 @@
 An *isolate* is an archive containing all the files needed to do a specific task
 on the swarming infrastructure. It contains binaries as well as any libraries
 they link against or support data. An isolate can be thought of like a tarball,
-but held by the "isolate server" and identified by a hash of its contents. The
+but held by the CAS server and identified by a digest of its contents. The
 isolate also includes the command(s) to run, which is why the command is
 specified when building the isolate, not when executing it.
 
@@ -50,7 +50,7 @@
 or perhaps:
 
 ```
-  isolate = upload_to_isolate_server(target_you_built_locally)
+  isolate = upload_to_cas(target_you_built_locally)
   use_swarming_to_run(type, isolate)
 ```
 
@@ -167,19 +167,21 @@
 
 ## Uploading an isolate
 
-You can then upload the resulting isolate to the isolate server:
+You can then upload the resulting isolate to the CAS server:
 
 ```
 $ tools/luci-go/isolate archive \
-      -I https://isolateserver.appspot.com \
+      -cas-instance chroimum-swarm \
       -i $outdir/$target.isolate \
-      -s $outdir/$target.isolated
+      -dump-json $outdir/$target.archive.json
 ```
 
-The `isolate` tool will emit something like this:
+The archive json looks like this:
 
 ```
-e625130b712096e3908266252c8cd779d7f442f1  unit_tests
+{
+  "unit_tests": "5bee0815d2ddd2b876b49d4cce8aaa23de8a6f9e2dbf134ec409fbdc224e8c64/398"
+}
 ```
 
 Do not ctrl-c it after it does this, even if it seems to be hanging for a
@@ -187,16 +189,15 @@
 
 ## Running an isolate
 
-Now that the isolate is on the isolate server with hash `$hash` from the
+Now that the isolate is on the CAS server with digest `$digest` from the
 previous step, you can run on bots of your choice:
 
 ```
 $ tools/luci-go/swarming trigger \
     -server https://chromium-swarm.appspot.com \
-    -isolate-server https://isolateserver.appspot.com \
     -dimension pool=$pool \
     $criteria \
-    -isolated $hash
+    -digest $digest
 ```
 
 There are two more things you need to fill in here. The first is the pool name;
diff --git a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
index 75f3ffcb..656a07cd 100644
--- a/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
+++ b/extensions/browser/api/declarative_net_request/filter_list_converter/converter.cc
@@ -407,13 +407,13 @@
     dnr_api::RuleActionType action_type = dnr_api::RULE_ACTION_TYPE_NONE;
 
     CHECK(!is_allow_all_requests_rule_ ||
-          input_rule_.semantics() == proto::RULE_SEMANTICS_WHITELIST);
+          input_rule_.semantics() == proto::RULE_SEMANTICS_ALLOWLIST);
 
     switch (input_rule_.semantics()) {
-      case proto::RULE_SEMANTICS_BLACKLIST:
+      case proto::RULE_SEMANTICS_BLOCKLIST:
         action_type = dnr_api::RULE_ACTION_TYPE_BLOCK;
         break;
-      case proto::RULE_SEMANTICS_WHITELIST:
+      case proto::RULE_SEMANTICS_ALLOWLIST:
         if (is_allow_all_requests_rule_)
           action_type = dnr_api::RULE_ACTION_TYPE_ALLOWALLREQUESTS;
         else
diff --git a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
index aa1deec..c5b38d23 100644
--- a/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/flat_ruleset_indexer_unittest.cc
@@ -452,7 +452,7 @@
 
   // Allow rules.
   rules_to_index.push_back(CreateIndexedRule(
-      17, kMinValidPriority, flat_rule::OptionFlag_IS_WHITELIST,
+      17, kMinValidPriority, flat_rule::OptionFlag_IS_ALLOWLIST,
       flat_rule::ElementType_PING | flat_rule::ElementType_SCRIPT,
       flat_rule::ActivationType_NONE, flat_rule::UrlPatternType_SUBSTRING,
       flat_rule::AnchorType_SUBDOMAIN, flat_rule::AnchorType_NONE,
@@ -460,7 +460,7 @@
       dnr_api::RULE_ACTION_TYPE_ALLOW, nullptr, base::nullopt, {}, {}));
   rules_to_index.push_back(CreateIndexedRule(
       16, kMinValidPriority,
-      flat_rule::OptionFlag_IS_WHITELIST |
+      flat_rule::OptionFlag_IS_ALLOWLIST |
           flat_rule::OptionFlag_IS_CASE_INSENSITIVE,
       flat_rule::ElementType_IMAGE, flat_rule::ActivationType_NONE,
       flat_rule::UrlPatternType_SUBSTRING, flat_rule::AnchorType_NONE,
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule.cc b/extensions/browser/api/declarative_net_request/indexed_rule.cc
index aab5a41..10bfa81 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule.cc
@@ -143,7 +143,7 @@
   uint8_t mask = flat_rule::OptionFlag_NONE;
 
   if (parsed_rule.action.type == dnr_api::RULE_ACTION_TYPE_ALLOW)
-    mask |= flat_rule::OptionFlag_IS_WHITELIST;
+    mask |= flat_rule::OptionFlag_IS_ALLOWLIST;
 
   if (!IsCaseSensitive(parsed_rule))
     mask |= flat_rule::OptionFlag_IS_CASE_INSENSITIVE;
diff --git a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
index 4aa4b5d..a337d81 100644
--- a/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
+++ b/extensions/browser/api/declarative_net_request/indexed_rule_unittest.cc
@@ -142,11 +142,11 @@
            flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY},
       {dnr_api::DOMAIN_TYPE_FIRSTPARTY, dnr_api::RULE_ACTION_TYPE_ALLOW,
        std::make_unique<bool>(true),
-       flat_rule::OptionFlag_IS_WHITELIST |
+       flat_rule::OptionFlag_IS_ALLOWLIST |
            flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY},
       {dnr_api::DOMAIN_TYPE_FIRSTPARTY, dnr_api::RULE_ACTION_TYPE_ALLOW,
        std::make_unique<bool>(false),
-       flat_rule::OptionFlag_IS_WHITELIST |
+       flat_rule::OptionFlag_IS_ALLOWLIST |
            flat_rule::OptionFlag_APPLIES_TO_FIRST_PARTY |
            flat_rule::OptionFlag_IS_CASE_INSENSITIVE},
   };
diff --git a/extensions/browser/api/web_request/web_request_info.cc b/extensions/browser/api/web_request/web_request_info.cc
index ad26c0ac..16e08f2 100644
--- a/extensions/browser/api/web_request/web_request_info.cc
+++ b/extensions/browser/api/web_request/web_request_info.cc
@@ -84,20 +84,19 @@
 
   for (auto& element : *request.request_body->elements()) {
     switch (element.type()) {
-      case network::mojom::DataElementType::kDataPipe:
+      case network::DataElement::Tag::kDataPipe:
         // TODO(https://crbug.com/721414): Support data pipe elements.
         break;
 
-      case network::mojom::DataElementType::kBytes:
+      case network::DataElement::Tag::kBytes:
         data_sources->push_back(std::make_unique<BytesUploadDataSource>(
-            base::StringPiece(element.bytes(), element.length())));
+            element.As<network::DataElementBytes>().AsStringPiece()));
         break;
-
-      case network::mojom::DataElementType::kFile:
+      case network::DataElement::Tag::kFile:
         // TODO(https://crbug.com/715679): This may not work when network
         // process is sandboxed.
-        data_sources->push_back(
-            std::make_unique<FileUploadDataSource>(element.path()));
+        data_sources->push_back(std::make_unique<FileUploadDataSource>(
+            element.As<network::DataElementFile>().path()));
         break;
 
       default:
diff --git a/google_apis/gaia/gaia_auth_fetcher_unittest.cc b/google_apis/gaia/gaia_auth_fetcher_unittest.cc
index 90c6033..72481f8f5 100644
--- a/google_apis/gaia/gaia_auth_fetcher_unittest.cc
+++ b/google_apis/gaia/gaia_auth_fetcher_unittest.cc
@@ -55,7 +55,10 @@
     return "";
   }
   const network::DataElement& elem = request->request_body->elements()->at(0);
-  return std::string(elem.bytes(), elem.length());
+  if (elem.type() != network::DataElement::Tag::kBytes) {
+    return "";
+  }
+  return std::string(elem.As<network::DataElementBytes>().AsStringPiece());
 }
 
 }  // namespace
diff --git a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
index 9488459..f12cf2d 100644
--- a/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
+++ b/ios/chrome/browser/signin/gaia_auth_fetcher_ios_ns_url_session_bridge.mm
@@ -10,7 +10,7 @@
 #include "base/callback_helpers.h"
 #include "base/mac/foundation_util.h"
 #include "base/strings/sys_string_conversions.h"
-#include "components/signin/ios/browser/account_consistency_service.h"
+#include "components/signin/core/browser/chrome_connected_header_helper.h"
 #include "ios/net/cookies/system_cookie_util.h"
 #include "ios/web/public/browser_state.h"
 #import "net/base/mac/url_conversions.h"
@@ -223,7 +223,7 @@
     // properties. Requests initiated from the browser services (e.g.
     // GaiaCookieManagerService) must not include this cookie.
     if (cookie_with_access_result.cookie.Name() ==
-        AccountConsistencyService::kChromeConnectedCookieName) {
+        signin::kChromeConnectedCookieName) {
       continue;
     }
     [http_cookies addObject:net::SystemCookieFromCanonicalCookie(
diff --git a/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h b/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h
index 533e79a..8c5f22c 100644
--- a/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h
+++ b/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.h
@@ -6,6 +6,7 @@
 #define IOS_CHROME_BROWSER_UI_AUTHENTICATION_CELLS_SIGNIN_PROMO_VIEW_CONFIGURATOR_H_
 
 #import <UIKit/UIKit.h>
+#import "ios/chrome/browser/ui/authentication/cells/signin_promo_view_constants.h"
 
 @class SigninPromoView;
 
@@ -14,12 +15,14 @@
 
 - (instancetype)init NS_UNAVAILABLE;
 
-// Initializes the instance. For cold state mode, set all parameters to nil.
-// For warm state mode set at least the |userEmail| to not nil.
-- (instancetype)initWithUserEmail:(NSString*)userEmail
-                     userFullName:(NSString*)userFullName
-                        userImage:(UIImage*)userImage
-                   hasCloseButton:(BOOL)hasCloseButton
+// Initializes the instance.
+// |userEmail| is used as a proxy to determine if accounts have
+// been added to the device.
+- (instancetype)initWithIdentityPromoViewMode:(IdentityPromoViewMode)viewMode
+                                    userEmail:(NSString*)userEmail
+                                 userFullName:(NSString*)userFullName
+                                    userImage:(UIImage*)userImage
+                               hasCloseButton:(BOOL)hasCloseButton
     NS_DESIGNATED_INITIALIZER;
 
 // Configures a sign-in promo view.
diff --git a/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.mm b/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.mm
index d271710d..a13dd07 100644
--- a/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.mm
+++ b/ios/chrome/browser/ui/authentication/cells/signin_promo_view_configurator.mm
@@ -36,22 +36,22 @@
 // If YES the close button will be shown.
 @property(nonatomic) BOOL hasCloseButton;
 
+// State of the identity promo view.
+@property(nonatomic, assign) IdentityPromoViewMode identityPromoViewMode;
+
 @end
 
 @implementation SigninPromoViewConfigurator
 
-@synthesize userEmail = _userEmail;
-@synthesize userFullName = _userFullName;
-@synthesize userImage = _userImage;
-@synthesize hasCloseButton = _hasCloseButton;
-
-- (instancetype)initWithUserEmail:(NSString*)userEmail
-                     userFullName:(NSString*)userFullName
-                        userImage:(UIImage*)userImage
-                   hasCloseButton:(BOOL)hasCloseButton {
+- (instancetype)initWithIdentityPromoViewMode:(IdentityPromoViewMode)viewMode
+                                    userEmail:(NSString*)userEmail
+                                 userFullName:(NSString*)userFullName
+                                    userImage:(UIImage*)userImage
+                               hasCloseButton:(BOOL)hasCloseButton {
   self = [super init];
   if (self) {
     DCHECK(userEmail || (!userEmail && !userFullName && !userImage));
+    _identityPromoViewMode = viewMode;
     _userFullName = [userFullName copy];
     _userEmail = [userEmail copy];
     _userImage = [userImage copy];
@@ -62,33 +62,38 @@
 
 - (void)configureSigninPromoView:(SigninPromoView*)signinPromoView {
   signinPromoView.closeButton.hidden = !self.hasCloseButton;
-  if (!self.userEmail) {
-    signinPromoView.mode = IdentityPromoViewModeNoAccounts;
-    NSString* signInString =
-        GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN);
-    signinPromoView.accessibilityLabel = signInString;
-    [signinPromoView.primaryButton setTitle:signInString
-                                   forState:UIControlStateNormal];
-  } else {
-    signinPromoView.mode = IdentityPromoViewModeSigninWithAccount;
-    NSString* name =
-        self.userFullName.length ? self.userFullName : self.userEmail;
-    base::string16 name16 = SysNSStringToUTF16(name);
-    [signinPromoView.primaryButton
-        setTitle:GetNSStringF(IDS_IOS_SIGNIN_PROMO_CONTINUE_AS, name16)
-        forState:UIControlStateNormal];
-    signinPromoView.accessibilityLabel =
-        GetNSStringF(IDS_IOS_SIGNIN_PROMO_ACCESSIBILITY_LABEL, name16);
-    [signinPromoView.secondaryButton
-        setTitle:GetNSString(IDS_IOS_SIGNIN_PROMO_CHANGE_ACCOUNT)
-        forState:UIControlStateNormal];
-    UIImage* image = self.userImage;
-    if (!image) {
-      image = ios::GetChromeBrowserProvider()
-                  ->GetSigninResourcesProvider()
-                  ->GetDefaultAvatar();
+  signinPromoView.mode = self.identityPromoViewMode;
+
+  switch (self.identityPromoViewMode) {
+    case IdentityPromoViewModeNoAccounts: {
+      NSString* signInString =
+          GetNSString(IDS_IOS_OPTIONS_IMPORT_DATA_TITLE_SIGNIN);
+      signinPromoView.accessibilityLabel = signInString;
+      [signinPromoView.primaryButton setTitle:signInString
+                                     forState:UIControlStateNormal];
+      break;
     }
-    [signinPromoView setProfileImage:image];
+    case IdentityPromoViewModeSigninWithAccount: {
+      NSString* name =
+          self.userFullName.length ? self.userFullName : self.userEmail;
+      base::string16 name16 = SysNSStringToUTF16(name);
+      [signinPromoView.primaryButton
+          setTitle:GetNSStringF(IDS_IOS_SIGNIN_PROMO_CONTINUE_AS, name16)
+          forState:UIControlStateNormal];
+      signinPromoView.accessibilityLabel =
+          GetNSStringF(IDS_IOS_SIGNIN_PROMO_ACCESSIBILITY_LABEL, name16);
+      [signinPromoView.secondaryButton
+          setTitle:GetNSString(IDS_IOS_SIGNIN_PROMO_CHANGE_ACCOUNT)
+          forState:UIControlStateNormal];
+      UIImage* image = self.userImage;
+      if (!image) {
+        image = ios::GetChromeBrowserProvider()
+                    ->GetSigninResourcesProvider()
+                    ->GetDefaultAvatar();
+      }
+      [signinPromoView setProfileImage:image];
+      break;
+    }
   }
 }
 
diff --git a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
index 8dad903..a5a401a 100644
--- a/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
+++ b/ios/chrome/browser/ui/authentication/signin_promo_view_mediator.mm
@@ -436,15 +436,18 @@
       AlreadySeenSigninViewPreferenceKey(self.accessPoint) != nullptr;
   if (_defaultIdentity) {
     return [[SigninPromoViewConfigurator alloc]
-        initWithUserEmail:_defaultIdentity.userEmail
-             userFullName:_defaultIdentity.userFullName
-                userImage:self.identityAvatar
-           hasCloseButton:hasCloseButton];
+        initWithIdentityPromoViewMode:IdentityPromoViewModeSigninWithAccount
+                            userEmail:_defaultIdentity.userEmail
+                         userFullName:_defaultIdentity.userFullName
+                            userImage:self.identityAvatar
+                       hasCloseButton:hasCloseButton];
   }
-  return [[SigninPromoViewConfigurator alloc] initWithUserEmail:nil
-                                                   userFullName:nil
-                                                      userImage:nil
-                                                 hasCloseButton:hasCloseButton];
+  return [[SigninPromoViewConfigurator alloc]
+      initWithIdentityPromoViewMode:IdentityPromoViewModeNoAccounts
+                          userEmail:nil
+                       userFullName:nil
+                          userImage:nil
+                     hasCloseButton:hasCloseButton];
 }
 
 - (void)signinPromoViewIsVisible {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
index 8cb45e3e..f9b4529 100644
--- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
+++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_header_view.mm
@@ -340,6 +340,10 @@
     self.fakeLocationBarTrailingConstraint.constant = 0;
     self.fakeLocationBarTopConstraint.constant = 0;
 
+    self.hintLabelLeadingConstraint.constant =
+        ntp_header::kHintLabelSidePadding;
+    self.voiceSearchTrailingMarginConstraint.constant = 0;
+
     self.separator.alpha = 0;
 
     return;
diff --git a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
index 1db1114..99972d56 100644
--- a/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
+++ b/ios/chrome/browser/ui/settings/table_cell_catalog_view_controller.mm
@@ -489,10 +489,11 @@
   TableViewSigninPromoItem* signinPromo =
       [[TableViewSigninPromoItem alloc] initWithType:ItemTypeAccount];
   signinPromo.configurator = [[SigninPromoViewConfigurator alloc]
-      initWithUserEmail:@"jonhdoe@example.com"
-           userFullName:@"John Doe"
-              userImage:nil
-         hasCloseButton:NO];
+      initWithIdentityPromoViewMode:IdentityPromoViewModeSigninWithAccount
+                          userEmail:@"jonhdoe@example.com"
+                       userFullName:@"John Doe"
+                          userImage:nil
+                     hasCloseButton:NO];
   signinPromo.text = @"Signin promo text example";
   [model addItem:signinPromo toSectionWithIdentifier:SectionIdentifierAccount];
 
diff --git a/ios/chrome/test/wpt/BUILD.gn b/ios/chrome/test/wpt/BUILD.gn
index 00531ee..3988bb4 100644
--- a/ios/chrome/test/wpt/BUILD.gn
+++ b/ios/chrome/test/wpt/BUILD.gn
@@ -2,9 +2,11 @@
 # Use of this source code is governed by a BSD-style license that can be
 # found in the LICENSE file.
 
+import("//build/apple/tweak_info_plist.gni")
 import("//build/config/ios/ios_sdk.gni")
 import("//build/config/ios/rules.gni")
-import("//ios/chrome/test/earl_grey2/chrome_ios_eg2_test.gni")
+import("//ios/build/chrome_build.gni")
+import("//ios/public/provider/chrome/browser/build_config.gni")
 
 group("all_tests") {
   testonly = true
@@ -14,15 +16,50 @@
   ]
 }
 
-chrome_ios_eg2_test_app_host("ios_cwt_chromedriver_tests") {
-  deps = [ ":eg_app_support+eg2" ]
+tweak_info_plist("chrome_app_plist") {
+  info_plists = [
+    "//ios/chrome/app/resources/Info.plist",
+    "//ios/chrome/app/resources/ChromeAddition+Info.plist",
+    "//ios/chrome/app/resources/MultiWindowEnabled+Info.plist",
+  ]
 }
 
-chrome_ios_eg2_test("ios_cwt_chromedriver_tests_module") {
+ios_app_bundle("ios_cwt_chromedriver_tests") {
+  testonly = true
+  deps = [
+    ":app_support",
+    "//ios/chrome/app:main",
+  ]
+  bundle_deps = [
+    "//ios/chrome/app/resources",
+    "//ios/third_party/gtx:gtx+bundle",
+    ios_application_icons_target,
+  ]
+  info_plist_target = ":chrome_app_plist"
+  extra_substitutions = [
+    "CHROMIUM_HANDOFF_ID=$chromium_handoff_id",
+    "CHROMIUM_SHORT_NAME=$target_name",
+    "CHROMIUM_URL_CHANNEL_SCHEME=$url_channel_scheme",
+    "CHROMIUM_URL_SCHEME_1=$url_unsecure_scheme",
+    "CHROMIUM_URL_SCHEME_2=$url_secure_scheme",
+    "CHROMIUM_URL_SCHEME_3=$url_x_callback_scheme",
+    "CHROMIUM_BUNDLE_ID=gtest.$target_name",
+    "CONTENT_WIDGET_EXTENSION_BUNDLE_ID=$chromium_bundle_id.ContentTodayExtension",
+    "IOS_MOVE_TAB_ACTIVITY_TYPE=$ios_move_tab_activity_type",
+    "SSOAUTH_URL_SCHEME=$url_ssoauth_scheme",
+  ]
+}
+
+ios_xcuitest_test("ios_cwt_chromedriver_tests_module") {
   xcode_test_application_name = "ios_cwt_chromedriver_tests"
 
   deps = [ ":cwt_chromedriver_tests" ]
   data_deps = [ ":ios_cwt_chromedriver_tests" ]
+  bundle_deps = [
+    "//ios/chrome/app/resources",
+    "//ios/third_party/gtx:gtx+bundle",
+    "//third_party/icu:icudata",
+  ]
 }
 
 source_set("shared_helper_headers") {
@@ -30,25 +67,36 @@
   sources = [ "cwt_webdriver_app_interface.h" ]
 }
 
-source_set("eg_app_support+eg2") {
-  defines = [ "CHROME_EARL_GREY_2" ]
+source_set("cwt_constants") {
+  testonly = true
+  sources = [
+    "cwt_constants.cc",
+    "cwt_constants.h",
+  ]
+}
+
+source_set("app_support") {
   testonly = true
   configs += [ "//build/config/compiler:enable_arc" ]
 
-  sources = [ "cwt_webdriver_app_interface.mm" ]
+  sources = [
+    "cwt_tests_hook.mm",
+    "cwt_webdriver_app_interface.mm",
+  ]
 
   deps = [
+    ":cwt_constants",
     "//base",
     "//base/test:test_support",
     "//ios/chrome/app:app_internal",
+    "//ios/chrome/app:tests_hook",
     "//ios/chrome/browser/main:public",
     "//ios/chrome/browser/tabs:tabs",
     "//ios/chrome/browser/web:tab_id_tab_helper",
     "//ios/chrome/browser/web_state_list",
     "//ios/chrome/test/app:test_support",
     "//ios/testing:nserror_support",
-    "//ios/testing/earl_grey:eg_app_support+eg2",
-    "//ios/third_party/earl_grey2:app_framework+link",
+    "//ios/third_party/edo",
     "//ios/web/public/test",
     "//ui/gfx",
   ]
@@ -57,7 +105,6 @@
 }
 
 source_set("cwt_chromedriver_tests") {
-  defines = [ "CHROME_EARL_GREY_2" ]
   testonly = true
   configs += [
     "//build/config/compiler:enable_arc",
@@ -71,10 +118,10 @@
   ]
 
   deps = [
+    ":cwt_constants",
     ":shared_helper_headers",
     "//components/version_info:version_info",
-    "//ios/testing/earl_grey:eg_test_support+eg2",
-    "//ios/third_party/earl_grey2:test_lib",
+    "//ios/third_party/edo",
     "//net:test_support",
   ]
 
diff --git a/ios/chrome/test/wpt/cwt_chrome_driver.mm b/ios/chrome/test/wpt/cwt_chrome_driver.mm
index 1604a6f..1fe120e 100644
--- a/ios/chrome/test/wpt/cwt_chrome_driver.mm
+++ b/ios/chrome/test/wpt/cwt_chrome_driver.mm
@@ -2,14 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-#import <TestLib/EarlGreyImpl/EarlGrey.h>
 #import <UIKit/UIKit.h>
 #import <XCTest/XCTest.h>
 
 #include "base/logging.h"
 #include "base/strings/sys_string_conversions.h"
 #import "ios/chrome/test/wpt/cwt_request_handler.h"
-#import "ios/testing/earl_grey/base_earl_grey_test_case.h"
 #include "net/base/port_util.h"
 #include "net/test/embedded_test_server/embedded_test_server.h"
 #include "url/url_constants.h"
@@ -28,17 +26,20 @@
 // Dummy test case that hosts CWTChromeDriver. CWTChromeDriver implements a
 // minimal subset of the WebDriver protocol needed to run most Web Platform
 // Tests. CWTChromeDriverTestCase launches a test server that listens for
-// WebDriver commands, and then uses EarlGrey2's eDistantObject protocol to pass
-// on corresponding messages to the app process. Each CWTChromeDriver launches a
-// single instance of Chrome, but mulitple instances of CWTChromeDriver can be
+// WebDriver commands, and then uses the eDistantObject protocol to pass on
+// corresponding messages to the app process. Each CWTChromeDriver launches a
+// single instance of Chrome, but multiple instances of CWTChromeDriver can be
 // run in parallel in order to use multiple instances of Chrome.
-@interface CWTChromeDriverTestCase : BaseEarlGreyTestCase
+@interface CWTChromeDriverTestCase : XCTestCase
 @end
 
 @implementation CWTChromeDriverTestCase
 
 // Dummy test that keeps the test app alive.
 - (void)testRunCWTChromeDriver {
+  XCUIApplication* application = [[XCUIApplication alloc] init];
+  [application launch];
+
   int port = kDefaultPort;
 
   NSArray* arguments = NSProcessInfo.processInfo.arguments;
diff --git a/ios/chrome/test/wpt/cwt_constants.cc b/ios/chrome/test/wpt/cwt_constants.cc
new file mode 100644
index 0000000..651d8fe3
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_constants.cc
@@ -0,0 +1,7 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/test/wpt/cwt_constants.h"
+
+extern const int kCwtEdoPortNumber = 56800;
diff --git a/ios/chrome/test/wpt/cwt_constants.h b/ios/chrome/test/wpt/cwt_constants.h
new file mode 100644
index 0000000..2d68304
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_constants.h
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef IOS_CHROME_TEST_WPT_CWT_CONSTANTS_H_
+#define IOS_CHROME_TEST_WPT_CWT_CONSTANTS_H_
+
+// The port that the app process listens on for EDO communication with the
+// the test process.
+extern const int kCwtEdoPortNumber;
+
+#endif  // IOS_CHROME_TEST_WPT_CWT_CONSTANTS_H_
diff --git a/ios/chrome/test/wpt/cwt_request_handler.mm b/ios/chrome/test/wpt/cwt_request_handler.mm
index 82ad195f..04df21f 100644
--- a/ios/chrome/test/wpt/cwt_request_handler.mm
+++ b/ios/chrome/test/wpt/cwt_request_handler.mm
@@ -10,15 +10,16 @@
 #include "base/json/json_writer.h"
 #include "base/strings/sys_string_conversions.h"
 #include "components/version_info/version_info.h"
+#import "ios/chrome/test/wpt/cwt_constants.h"
 #import "ios/chrome/test/wpt/cwt_webdriver_app_interface.h"
-#import "ios/testing/earl_grey/earl_grey_test.h"
+#import "ios/third_party/edo/src/Service/Sources/EDOClientService.h"
 #include "net/http/http_status_code.h"
 
 #if !defined(__has_feature) || !__has_feature(objc_arc)
 #error "This file requires ARC support."
 #endif
 
-GREY_STUB_CLASS_IN_APP_BACKGROUND_QUEUE(CWTWebDriverAppInterface)
+EDO_STUB_CLASS(CWTWebDriverAppInterface, kCwtEdoPortNumber)
 
 using net::test_server::HttpRequest;
 using net::test_server::HttpResponse;
diff --git a/ios/chrome/test/wpt/cwt_tests_hook.mm b/ios/chrome/test/wpt/cwt_tests_hook.mm
new file mode 100644
index 0000000..97ccb053
--- /dev/null
+++ b/ios/chrome/test/wpt/cwt_tests_hook.mm
@@ -0,0 +1,51 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ios/chrome/app/tests_hook.h"
+
+#import "ios/chrome/test/wpt/cwt_constants.h"
+#import "ios/chrome/test/wpt/cwt_webdriver_app_interface.h"
+#import "ios/third_party/edo/src/Service/Sources/EDOHostService.h"
+
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+namespace tests_hook {
+
+bool DisableAppGroupAccess() {
+  return true;
+}
+bool DisableContentSuggestions() {
+  return true;
+}
+bool DisableFirstRun() {
+  return true;
+}
+bool DisableGeolocation() {
+  return true;
+}
+bool DisableSigninRecallPromo() {
+  return true;
+}
+bool DisableUpdateService() {
+  return true;
+}
+bool DisableMainThreadFreezeDetection() {
+  return true;
+}
+policy::ConfigurationPolicyProvider* GetOverriddenPlatformPolicyProvider() {
+  return nullptr;
+}
+void SetUpTestsIfPresent() {
+  CWTWebDriverAppInterface* appInterface =
+      [[CWTWebDriverAppInterface alloc] init];
+  [EDOHostService serviceWithPort:kCwtEdoPortNumber
+                       rootObject:appInterface
+                            queue:[appInterface executingQueue]];
+}
+
+void RunTestsIfPresent() {}
+
+}  // namespace tests_hook
diff --git a/ios/chrome/test/wpt/cwt_webdriver_app_interface.h b/ios/chrome/test/wpt/cwt_webdriver_app_interface.h
index af4da73..572c3b8f 100644
--- a/ios/chrome/test/wpt/cwt_webdriver_app_interface.h
+++ b/ios/chrome/test/wpt/cwt_webdriver_app_interface.h
@@ -13,6 +13,9 @@
 // avoid deadlock while waiting for actions to complete on the main thread.
 @interface CWTWebDriverAppInterface : NSObject
 
+// The background thread where this class' methods are run.
+@property(nonatomic, readonly) dispatch_queue_t executingQueue;
+
 // Loads the given URL in the tab identified by |tabID|. Returns an error if the
 // page fails to load within |timeout| seconds or if no such tab exists.
 + (NSError*)loadURL:(NSString*)URL
diff --git a/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
index 74f7a8e..3e6920a 100644
--- a/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
+++ b/ios/chrome/test/wpt/cwt_webdriver_app_interface.mm
@@ -17,7 +17,6 @@
 #import "ios/chrome/test/app/chrome_test_util.h"
 #import "ios/chrome/test/app/settings_test_util.h"
 #import "ios/chrome/test/app/tab_test_util.h"
-#import "ios/testing/earl_grey/earl_grey_app.h"
 #import "ios/testing/nserror_util.h"
 #import "ios/web/public/test/navigation_test_util.h"
 #import "ios/web/public/ui/crw_web_view_proxy.h"
@@ -59,15 +58,40 @@
   return web_state_list->GetIndexOfWebState(GetWebStateWithId(tab_id));
 }
 
+void DispatchSyncOnMainThread(void (^block)(void)) {
+  if ([NSThread isMainThread]) {
+    block();
+  } else {
+    dispatch_semaphore_t waitForBlock = dispatch_semaphore_create(0);
+    CFRunLoopPerformBlock(CFRunLoopGetMain(), kCFRunLoopDefaultMode, ^{
+      block();
+      dispatch_semaphore_signal(waitForBlock);
+    });
+    // CFRunLoopPerformBlock does not wake up the main queue.
+    CFRunLoopWakeUp(CFRunLoopGetMain());
+    // Waits until block is executed and semaphore is signalled.
+    dispatch_semaphore_wait(waitForBlock, DISPATCH_TIME_FOREVER);
+  }
+}
+
 }  // namespace
 
 @implementation CWTWebDriverAppInterface
 
+- (instancetype)init {
+  self = [super init];
+  if (self) {
+    _executingQueue = dispatch_queue_create("com.google.chrome.cwt.background",
+                                            DISPATCH_QUEUE_SERIAL);
+  }
+  return self;
+}
+
 + (NSError*)loadURL:(NSString*)URL
                inTab:(NSString*)tabID
     timeoutInSeconds:(NSTimeInterval)timeout {
   __block web::WebState* webState = nullptr;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     webState = GetWebStateWithId(tabID);
     if (webState)
       web::test::LoadUrl(webState, GURL(base::SysNSStringToUTF8(URL)));
@@ -78,7 +102,7 @@
 
   bool success = WaitUntilConditionOrTimeout(timeout, ^bool {
     __block BOOL isLoading = NO;
-    grey_dispatch_sync_on_main_thread(^{
+    DispatchSyncOnMainThread(^{
       isLoading = webState->IsLoading();
     });
     return !isLoading;
@@ -92,7 +116,7 @@
 
 + (NSString*)currentTabID {
   __block NSString* tabID = nil;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     web::WebState* webState = chrome_test_util::GetCurrentWebState();
     if (webState)
       tabID = GetIdForWebState(webState);
@@ -103,7 +127,7 @@
 
 + (NSArray*)tabIDs {
   __block NSMutableArray* tabIDs;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     DCHECK(!chrome_test_util::IsIncognitoMode());
     WebStateList* webStateList = GetCurrentWebStateList();
     tabIDs = [NSMutableArray arrayWithCapacity:webStateList->count()];
@@ -119,7 +143,7 @@
 
 + (NSError*)closeTabWithID:(NSString*)ID {
   __block NSError* error = nil;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     int webStateIndex = GetIndexOfWebStateWithId(ID);
     if (webStateIndex != WebStateList::kInvalidIndex) {
       WebStateList* webStateList = GetCurrentWebStateList();
@@ -135,7 +159,7 @@
 
 + (NSError*)switchToTabWithID:(NSString*)ID {
   __block NSError* error = nil;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     DCHECK(!chrome_test_util::IsIncognitoMode());
     int webStateIndex = GetIndexOfWebStateWithId(ID);
     if (webStateIndex != WebStateList::kInvalidIndex) {
@@ -193,7 +217,7 @@
 
   __block BOOL webStateFound = NO;
   __block base::CallbackListSubscription subscription;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     web::WebState* webState = GetWebStateWithId(tabID);
     if (!webState)
       return;
@@ -208,7 +232,7 @@
 
   bool success = WaitUntilConditionOrTimeout(timeout, ^bool {
     __block BOOL scriptExecutionComplete = NO;
-    grey_dispatch_sync_on_main_thread(^{
+    DispatchSyncOnMainThread(^{
       scriptExecutionComplete = messageValue.has_value();
     });
     return scriptExecutionComplete;
@@ -223,14 +247,14 @@
 }
 
 + (void)enablePopups {
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     chrome_test_util::SetContentSettingsBlockPopups(CONTENT_SETTING_ALLOW);
   });
 }
 
 + (NSString*)takeSnapshotOfTabWithID:(NSString*)ID {
   __block web::WebState* webState;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     webState = GetWebStateWithId(ID);
   });
 
@@ -238,7 +262,7 @@
     return nil;
 
   __block UIImage* snapshot = nil;
-  grey_dispatch_sync_on_main_thread(^{
+  DispatchSyncOnMainThread(^{
     CGRect bounds = webState->GetWebViewProxy().bounds;
     UIEdgeInsets insets = webState->GetWebViewProxy().contentInset;
     CGRect adjustedBounds = UIEdgeInsetsInsetRect(bounds, insets);
@@ -252,7 +276,7 @@
   const NSTimeInterval kSnapshotTimeoutSeconds = 100;
   bool success = WaitUntilConditionOrTimeout(kSnapshotTimeoutSeconds, ^bool {
     __block BOOL snapshotComplete = NO;
-    grey_dispatch_sync_on_main_thread(^{
+    DispatchSyncOnMainThread(^{
       if (snapshot != nil)
         snapshotComplete = YES;
     });
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
index 91e2d77..99ba9909 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.h
@@ -79,14 +79,10 @@
     virtual ~Observer() {}
 
     // Handles identity list changed events.
-    // Deprecated, see OnIdentityListChanged(bool).
-    virtual void OnIdentityListChanged() {}
-
-    // Handles identity list changed events.
     // |keychainReload| is true if the identity list is updated by reloading the
     // keychain. This means that a first party Google app had added or removed
     // identities.
-    virtual void OnIdentityListChanged(bool keychainReload);
+    virtual void OnIdentityListChanged(bool keychainReload) {}
 
     // Handles access token refresh failed events.
     // |identity| is the the identity for which the access token refresh failed.
@@ -270,10 +266,6 @@
 
  protected:
   // Fires |OnIdentityListChanged| on all observers.
-  // Deprecated, see FireIdentityListChanged(bool).
-  void FireIdentityListChanged();
-
-  // Fires |OnIdentityListChanged| on all observers.
   // |keychainReload| is true if the identity list is updated by reloading the
   // keychain. This means that a first party Google app had added or removed
   // identities.
diff --git a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
index 42696fd..27c9f2f 100644
--- a/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
+++ b/ios/public/provider/chrome/browser/signin/chrome_identity_service.mm
@@ -15,13 +15,6 @@
 
 namespace ios {
 
-void ChromeIdentityService::Observer::OnIdentityListChanged(
-    bool keychainReload) {
-  // Call to OnIdentityListChanged() is temporary, until all classes in
-  // ios_internal have migrated to this method.
-  OnIdentityListChanged();
-}
-
 ChromeIdentityService::ChromeIdentityService() {}
 
 ChromeIdentityService::~ChromeIdentityService() {
@@ -163,10 +156,6 @@
   return false;
 }
 
-void ChromeIdentityService::FireIdentityListChanged() {
-  FireIdentityListChanged(true);
-}
-
 void ChromeIdentityService::FireIdentityListChanged(bool keychainReload) {
   for (auto& observer : observer_list_)
     observer.OnIdentityListChanged(keychainReload);
diff --git a/net/cookies/canonical_cookie.cc b/net/cookies/canonical_cookie.cc
index a08893c6..927fe7c 100644
--- a/net/cookies/canonical_cookie.cc
+++ b/net/cookies/canonical_cookie.cc
@@ -713,13 +713,6 @@
   CookieEffectiveSameSite effective_same_site =
       GetEffectiveSameSite(params.access_semantics);
   DCHECK(effective_same_site != CookieEffectiveSameSite::UNDEFINED);
-  // Log the effective SameSite mode that is applied to the cookie on this
-  // request, if its SameSite was not specified.
-  if (SameSite() == CookieSameSite::UNSPECIFIED) {
-    UMA_HISTOGRAM_ENUMERATION("Cookie.SameSiteUnspecifiedEffective",
-                              effective_same_site,
-                              CookieEffectiveSameSite::COUNT);
-  }
   UMA_HISTOGRAM_ENUMERATION(
       "Cookie.RequestSameSiteContext", cookie_inclusion_context,
       CookieOptions::SameSiteCookieContext::ContextType::COUNT);
diff --git a/net/http/http_network_session.cc b/net/http/http_network_session.cc
index e9c5c63..ad09937 100644
--- a/net/http/http_network_session.cc
+++ b/net/http/http_network_session.cc
@@ -95,7 +95,8 @@
       enable_quic(true),
       enable_quic_proxies_for_https_urls(false),
       disable_idle_sockets_close_on_memory_pressure(false),
-      key_auth_cache_server_entries_by_network_isolation_key(false) {
+      key_auth_cache_server_entries_by_network_isolation_key(false),
+      enable_priority_update(false) {
   enable_early_data =
       base::FeatureList::IsEnabled(features::kEnableTLS13EarlyData);
 }
@@ -183,6 +184,7 @@
                          AddDefaultHttp2Settings(params.http2_settings),
                          params.greased_http2_frame,
                          params.http2_end_stream_with_data_frame,
+                         params.enable_priority_update,
                          params.time_func,
                          context.network_quality_estimator),
       http_stream_factory_(std::make_unique<HttpStreamFactory>(this)),
diff --git a/net/http/http_network_session.h b/net/http/http_network_session.h
index 9c6dd62..8a9520af 100644
--- a/net/http/http_network_session.h
+++ b/net/http/http_network_session.h
@@ -151,6 +151,13 @@
     bool disable_idle_sockets_close_on_memory_pressure;
 
     bool key_auth_cache_server_entries_by_network_isolation_key;
+
+    // If true, enable sending PRIORITY_UPDATE frames until SETTINGS frame
+    // arrives.  After SETTINGS frame arrives, do not send PRIORITY_UPDATE
+    // frames any longer if SETTINGS_DEPRECATE_HTTP2_PRIORITIES is missing or
+    // has zero 0, but continue and also stop sending HTTP/2-style priority
+    // information in HEADERS frames and PRIORITY frames if it has value 1.
+    bool enable_priority_update;
   };
 
   // Structure with pointers to the dependencies of the HttpNetworkSession.
diff --git a/net/spdy/spdy_session.cc b/net/spdy/spdy_session.cc
index 6eb6fcb..6119091 100644
--- a/net/spdy/spdy_session.cc
+++ b/net/spdy/spdy_session.cc
@@ -926,6 +926,7 @@
     const base::Optional<SpdySessionPool::GreasedHttp2Frame>&
         greased_http2_frame,
     bool http2_end_stream_with_data_frame,
+    bool enable_priority_update,
     TimeFunc time_func,
     ServerPushDelegate* push_delegate,
     NetworkQualityEstimator* network_quality_estimator,
@@ -953,6 +954,9 @@
       initial_settings_(initial_settings),
       greased_http2_frame_(greased_http2_frame),
       http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame),
+      enable_priority_update_(enable_priority_update),
+      deprecate_http2_priorities_(false),
+      settings_frame_received_(false),
       in_confirm_handshake_(false),
       max_concurrent_streams_(kInitialMaxConcurrentStreams),
       max_concurrent_pushed_streams_(
@@ -1158,6 +1162,18 @@
       stream, stream->traffic_annotation());
 }
 
+bool SpdySession::ShouldSendHttp2Priority() const {
+  return !enable_priority_update_ || !deprecate_http2_priorities_;
+}
+
+bool SpdySession::ShouldSendPriorityUpdate() const {
+  if (!enable_priority_update_) {
+    return false;
+  }
+
+  return settings_frame_received_ ? deprecate_http2_priorities_ : true;
+}
+
 int SpdySession::ConfirmHandshake(CompletionOnceCallback callback) {
   int rv = ERR_IO_PENDING;
   if (!in_confirm_handshake_) {
@@ -2663,6 +2679,26 @@
         support_websocket_ = true;
       }
       break;
+    case spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES:
+      if (value != 0 && value != 1) {
+        DoDrainSession(
+            ERR_HTTP2_PROTOCOL_ERROR,
+            "Invalid value for spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES.");
+        return;
+      }
+      if (settings_frame_received_) {
+        if (value != (deprecate_http2_priorities_ ? 1 : 0)) {
+          DoDrainSession(ERR_HTTP2_PROTOCOL_ERROR,
+                         "spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES value "
+                         "changed after first SETTINGS frame.");
+          return;
+        }
+      } else {
+        if (value == 1) {
+          deprecate_http2_priorities_ = true;
+        }
+      }
+      break;
   }
 }
 
@@ -3309,6 +3345,10 @@
                     [&] { return NetLogSpdyRecvSettingParams(id, value); });
 }
 
+void SpdySession::OnSettingsEnd() {
+  settings_frame_received_ = true;
+}
+
 void SpdySession::OnWindowUpdate(spdy::SpdyStreamId stream_id,
                                  int delta_window_size) {
   CHECK(in_io_loop_);
diff --git a/net/spdy/spdy_session.h b/net/spdy/spdy_session.h
index 206ce41..f088e5d 100644
--- a/net/spdy/spdy_session.h
+++ b/net/spdy/spdy_session.h
@@ -353,6 +353,7 @@
               const base::Optional<SpdySessionPool::GreasedHttp2Frame>&
                   greased_http2_frame,
               bool http2_end_stream_with_data_frame,
+              bool enable_priority_update,
               TimeFunc time_func,
               ServerPushDelegate* push_delegate,
               NetworkQualityEstimator* network_quality_estimator,
@@ -442,6 +443,21 @@
   // Send greased frame, that is, a frame of reserved type.
   void EnqueueGreasedFrame(const base::WeakPtr<SpdyStream>& stream);
 
+  // Returns whether HTTP/2 style priority information (stream dependency and
+  // weight fields in HEADERS frames, and PRIORITY frames) should be sent.  True
+  // unless |enable_priority_update_| is true and
+  // SETTINGS_DEPRECATE_HTTP2_PRIORITIES with value 1 has been received from
+  // server.  In particular, if it returns false, it will always return false
+  // afterwards.
+  bool ShouldSendHttp2Priority() const;
+
+  // Returns whether PRIORITY_UPDATE frames should be sent.  False if
+  // |enable_priority_update_| is false.  Otherwise, true before SETTINGS frame
+  // is received from server, and true after SETTINGS frame is received if it
+  // contained SETTINGS_DEPRECATE_HTTP2_PRIORITIES with value 1.  In particular,
+  // if it returns false, it will always return false afterwards.
+  bool ShouldSendPriorityUpdate() const;
+
   // Runs the handshake to completion to confirm the handshake with the server.
   // If ERR_IO_PENDING is returned, then when the handshake is confirmed,
   // |callback| will be called.
@@ -904,7 +920,7 @@
   void OnSettings() override;
   void OnSettingsAck() override;
   void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
-  void OnSettingsEnd() override {}
+  void OnSettingsEnd() override;
   void OnWindowUpdate(spdy::SpdyStreamId stream_id,
                       int delta_window_size) override;
   void OnPushPromise(spdy::SpdyStreamId stream_id,
@@ -1130,7 +1146,21 @@
   // If unset, the HEADERS frame will have the END_STREAM flag set on.
   // This is useful in conjuction with |greased_http2_frame_| so that a frame
   // of reserved type can be sent out even on requests without a body.
-  bool http2_end_stream_with_data_frame_;
+  const bool http2_end_stream_with_data_frame_;
+
+  // If true, enable sending PRIORITY_UPDATE frames until SETTINGS frame
+  // arrives.  After SETTINGS frame arrives, do not send PRIORITY_UPDATE frames
+  // any longer if SETTINGS_DEPRECATE_HTTP2_PRIORITIES is missing or has zero 0,
+  // but continue and also stop sending HTTP/2-style priority information in
+  // HEADERS frames and PRIORITY frames if it has value 1.
+  const bool enable_priority_update_;
+
+  // The value of the last received SETTINGS_DEPRECATE_HTTP2_PRIORITIES, with 0
+  // mapping to false and 1 to true.  Initial value is false.
+  bool deprecate_http2_priorities_;
+
+  // True if at least one SETTINGS frame has been received.
+  bool settings_frame_received_;
 
   // The callbacks to notify a request that the handshake has been confirmed.
   std::vector<CompletionOnceCallback> waiting_for_confirmation_callbacks_;
diff --git a/net/spdy/spdy_session_pool.cc b/net/spdy/spdy_session_pool.cc
index f207996..4eb361f 100644
--- a/net/spdy/spdy_session_pool.cc
+++ b/net/spdy/spdy_session_pool.cc
@@ -90,6 +90,7 @@
     const spdy::SettingsMap& initial_settings,
     const base::Optional<GreasedHttp2Frame>& greased_http2_frame,
     bool http2_end_stream_with_data_frame,
+    bool enable_priority_update,
     SpdySessionPool::TimeFunc time_func,
     NetworkQualityEstimator* network_quality_estimator)
     : http_server_properties_(http_server_properties),
@@ -107,6 +108,7 @@
       initial_settings_(initial_settings),
       greased_http2_frame_(greased_http2_frame),
       http2_end_stream_with_data_frame_(http2_end_stream_with_data_frame),
+      enable_priority_update_(enable_priority_update),
       time_func_(time_func),
       push_delegate_(nullptr),
       network_quality_estimator_(network_quality_estimator) {
@@ -667,8 +669,9 @@
       enable_ping_based_connection_checking_, is_http2_enabled_,
       is_quic_enabled_, is_trusted_proxy, session_max_recv_window_size_,
       session_max_queued_capped_frames_, initial_settings_,
-      greased_http2_frame_, http2_end_stream_with_data_frame_, time_func_,
-      push_delegate_, network_quality_estimator_, net_log);
+      greased_http2_frame_, http2_end_stream_with_data_frame_,
+      enable_priority_update_, time_func_, push_delegate_,
+      network_quality_estimator_, net_log);
 }
 
 base::WeakPtr<SpdySession> SpdySessionPool::InsertSession(
diff --git a/net/spdy/spdy_session_pool.h b/net/spdy/spdy_session_pool.h
index 9ae9580..5fc3bf3 100644
--- a/net/spdy/spdy_session_pool.h
+++ b/net/spdy/spdy_session_pool.h
@@ -145,6 +145,7 @@
                   const spdy::SettingsMap& initial_settings,
                   const base::Optional<GreasedHttp2Frame>& greased_http2_frame,
                   bool http2_end_stream_with_data_frame,
+                  bool enable_priority_update,
                   SpdySessionPool::TimeFunc time_func,
                   NetworkQualityEstimator* network_quality_estimator);
   ~SpdySessionPool() override;
@@ -450,7 +451,14 @@
   // If unset, the HEADERS frame will have the END_STREAM flag set on.
   // This is useful in conjuction with |greased_http2_frame_| so that a frame
   // of reserved type can be sent out even on requests without a body.
-  bool http2_end_stream_with_data_frame_;
+  const bool http2_end_stream_with_data_frame_;
+
+  // If true, enable sending PRIORITY_UPDATE frames until SETTINGS frame
+  // arrives.  After SETTINGS frame arrives, do not send PRIORITY_UPDATE frames
+  // any longer if SETTINGS_DEPRECATE_HTTP2_PRIORITIES is missing or has zero 0,
+  // but continue and also stop sending HTTP/2-style priority information in
+  // HEADERS frames and PRIORITY frames if it has value 1.
+  const bool enable_priority_update_;
 
   SpdySessionRequestMap spdy_session_request_map_;
 
diff --git a/net/spdy/spdy_session_unittest.cc b/net/spdy/spdy_session_unittest.cc
index 10a403a5e..07dca05 100644
--- a/net/spdy/spdy_session_unittest.cc
+++ b/net/spdy/spdy_session_unittest.cc
@@ -7247,4 +7247,155 @@
   EXPECT_TRUE(data.AllReadDataConsumed());
 }
 
+TEST_F(SpdySessionTest, PriorityUpdateDisabled) {
+  session_deps_.enable_priority_update = false;
+
+  spdy::SettingsMap settings;
+  settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
+  auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
+  auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
+
+  MockRead reads[] = {CreateMockRead(settings_frame, 0),
+                      MockRead(ASYNC, ERR_IO_PENDING, 2),
+                      MockRead(ASYNC, 0, 3)};
+  MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
+  SequencedSocketData data(reads, writes);
+
+  session_deps_.socket_factory->AddSocketDataProvider(&data);
+  AddSSLSocketData();
+
+  CreateNetworkSession();
+  CreateSpdySession();
+
+  // HTTP/2 priorities enabled by default.
+  // PRIORITY_UPDATE is disabled by |enable_priority_update| = false.
+  EXPECT_TRUE(session_->ShouldSendHttp2Priority());
+  EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
+
+  // Receive SETTINGS frame.
+  base::RunLoop().RunUntilIdle();
+
+  // Since |enable_priority_update| = false,
+  // SETTINGS_DEPRECATE_HTTP2_PRIORITIES has no effect.
+  EXPECT_TRUE(session_->ShouldSendHttp2Priority());
+  EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
+
+  data.Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(data.AllWriteDataConsumed());
+  EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdySessionTest, PriorityUpdateEnabledHttp2PrioritiesDeprecated) {
+  session_deps_.enable_priority_update = true;
+
+  spdy::SettingsMap settings;
+  settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
+  auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
+  auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
+
+  MockRead reads[] = {CreateMockRead(settings_frame, 0),
+                      MockRead(ASYNC, ERR_IO_PENDING, 2),
+                      MockRead(ASYNC, 0, 3)};
+  MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
+  SequencedSocketData data(reads, writes);
+
+  session_deps_.socket_factory->AddSocketDataProvider(&data);
+  AddSSLSocketData();
+
+  CreateNetworkSession();
+  CreateSpdySession();
+
+  // Both priority schemes are enabled until SETTINGS frame is received.
+  EXPECT_TRUE(session_->ShouldSendHttp2Priority());
+  EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
+
+  // Receive SETTINGS frame.
+  base::RunLoop().RunUntilIdle();
+
+  // SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 1 disables HTTP/2 priorities.
+  EXPECT_FALSE(session_->ShouldSendHttp2Priority());
+  EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
+
+  data.Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(data.AllWriteDataConsumed());
+  EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdySessionTest, PriorityUpdateEnabledHttp2PrioritiesNotDeprecated) {
+  session_deps_.enable_priority_update = true;
+
+  spdy::SettingsMap settings;
+  settings[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 0;
+  auto settings_frame = spdy_util_.ConstructSpdySettings(settings);
+  auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
+
+  MockRead reads[] = {CreateMockRead(settings_frame, 0),
+                      MockRead(ASYNC, ERR_IO_PENDING, 2),
+                      MockRead(ASYNC, 0, 3)};
+  MockWrite writes[] = {CreateMockWrite(settings_ack, 1)};
+  SequencedSocketData data(reads, writes);
+
+  session_deps_.socket_factory->AddSocketDataProvider(&data);
+  AddSSLSocketData();
+
+  CreateNetworkSession();
+  CreateSpdySession();
+
+  // Both priority schemes are enabled until SETTINGS frame is received.
+  EXPECT_TRUE(session_->ShouldSendHttp2Priority());
+  EXPECT_TRUE(session_->ShouldSendPriorityUpdate());
+
+  // Receive SETTINGS frame.
+  base::RunLoop().RunUntilIdle();
+
+  // SETTINGS_DEPRECATE_HTTP2_PRIORITIES = 0 disables PRIORITY_UPDATE.
+  EXPECT_TRUE(session_->ShouldSendHttp2Priority());
+  EXPECT_FALSE(session_->ShouldSendPriorityUpdate());
+
+  data.Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(data.AllWriteDataConsumed());
+  EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
+TEST_F(SpdySessionTest, SettingsDeprecateHttp2PrioritiesValueMustNotChange) {
+  spdy::SettingsMap settings0;
+  settings0[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 0;
+  auto settings_frame0 = spdy_util_.ConstructSpdySettings(settings0);
+  spdy::SettingsMap settings1;
+  settings1[spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES] = 1;
+  auto settings_frame1 = spdy_util_.ConstructSpdySettings(settings1);
+  MockRead reads[] = {
+      CreateMockRead(settings_frame1, 0), MockRead(ASYNC, ERR_IO_PENDING, 2),
+      CreateMockRead(settings_frame1, 3), MockRead(ASYNC, ERR_IO_PENDING, 5),
+      CreateMockRead(settings_frame0, 6)};
+
+  auto settings_ack = spdy_util_.ConstructSpdySettingsAck();
+  auto goaway = spdy_util_.ConstructSpdyGoAway(
+      0, spdy::ERROR_CODE_PROTOCOL_ERROR,
+      "spdy::SETTINGS_DEPRECATE_HTTP2_PRIORITIES value changed after first "
+      "SETTINGS frame.");
+  MockWrite writes[] = {
+      CreateMockWrite(settings_ack, 1), CreateMockWrite(settings_ack, 4),
+      CreateMockWrite(settings_ack, 7), CreateMockWrite(goaway, 8)};
+
+  SequencedSocketData data(reads, writes);
+
+  session_deps_.socket_factory->AddSocketDataProvider(&data);
+  AddSSLSocketData();
+
+  CreateNetworkSession();
+  CreateSpdySession();
+
+  base::RunLoop().RunUntilIdle();
+  data.Resume();
+  base::RunLoop().RunUntilIdle();
+  data.Resume();
+  base::RunLoop().RunUntilIdle();
+  EXPECT_TRUE(data.AllWriteDataConsumed());
+  EXPECT_TRUE(data.AllReadDataConsumed());
+}
+
 }  // namespace net
diff --git a/net/spdy/spdy_stream.cc b/net/spdy/spdy_stream.cc
index 339c364..77ec27d 100644
--- a/net/spdy/spdy_stream.cc
+++ b/net/spdy/spdy_stream.cc
@@ -600,21 +600,12 @@
 
 void SpdyStream::OnFrameWriteComplete(spdy::SpdyFrameType frame_type,
                                       size_t frame_size) {
-  // PRIORITY writes are allowed at any time and do not trigger a state update.
-  if (frame_type == spdy::SpdyFrameType::PRIORITY) {
+  if (frame_type != spdy::SpdyFrameType::HEADERS &&
+      frame_type != spdy::SpdyFrameType::DATA) {
     return;
   }
 
-  // Frame types reserved in
-  // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00 ought to be
-  // ignored.
-  if (static_cast<uint8_t>(frame_type) % 0x1f == 0x0b)
-    return;
-
   DCHECK_NE(type_, SPDY_PUSH_STREAM);
-  CHECK(frame_type == spdy::SpdyFrameType::HEADERS ||
-        frame_type == spdy::SpdyFrameType::DATA)
-      << frame_type;
 
   int result = (frame_type == spdy::SpdyFrameType::HEADERS)
                    ? OnHeadersSent()
diff --git a/net/spdy/spdy_test_util_common.cc b/net/spdy/spdy_test_util_common.cc
index 8f846a3..4c2795e 100644
--- a/net/spdy/spdy_test_util_common.cc
+++ b/net/spdy/spdy_test_util_common.cc
@@ -348,7 +348,8 @@
       net_log(nullptr),
       disable_idle_sockets_close_on_memory_pressure(false),
       enable_early_data(false),
-      key_auth_cache_server_entries_by_network_isolation_key(false) {
+      key_auth_cache_server_entries_by_network_isolation_key(false),
+      enable_priority_update(false) {
   http2_settings[spdy::SETTINGS_INITIAL_WINDOW_SIZE] =
       kDefaultInitialWindowSize;
 }
@@ -406,6 +407,7 @@
   params.enable_early_data = session_deps->enable_early_data;
   params.key_auth_cache_server_entries_by_network_isolation_key =
       session_deps->key_auth_cache_server_entries_by_network_isolation_key;
+  params.enable_priority_update = session_deps->enable_priority_update;
   return params;
 }
 
diff --git a/net/spdy/spdy_test_util_common.h b/net/spdy/spdy_test_util_common.h
index 000d142..51c3c11 100644
--- a/net/spdy/spdy_test_util_common.h
+++ b/net/spdy/spdy_test_util_common.h
@@ -238,6 +238,7 @@
   bool disable_idle_sockets_close_on_memory_pressure;
   bool enable_early_data;
   bool key_auth_cache_server_entries_by_network_isolation_key;
+  bool enable_priority_update;
 };
 
 class SpdyURLRequestContext : public URLRequestContext {
diff --git a/remoting/base/protobuf_http_client_unittest.cc b/remoting/base/protobuf_http_client_unittest.cc
index 71b6c4c0..fcb6303 100644
--- a/remoting/base/protobuf_http_client_unittest.cc
+++ b/remoting/base/protobuf_http_client_unittest.cc
@@ -197,10 +197,11 @@
   ASSERT_TRUE(pending_request->request.headers.GetHeader(
       kAuthorizationHeaderKey, &auth_header));
   ASSERT_EQ(kFakeAccessTokenHeaderValue, auth_header);
-  auto& data_element =
+  const auto& data_element =
       pending_request->request.request_body->elements()->front();
-  std::string request_body_data =
-      std::string(data_element.bytes(), data_element.length());
+  ASSERT_EQ(data_element.type(), network::DataElement::Tag::kBytes);
+  std::string request_body_data(
+      data_element.As<network::DataElementBytes>().AsStringPiece());
   EchoRequest request_message;
   ASSERT_TRUE(request_message.ParseFromString(request_body_data));
   ASSERT_EQ(kRequestText, request_message.text());
diff --git a/remoting/base/protobuf_http_test_responder.cc b/remoting/base/protobuf_http_test_responder.cc
index b22b52f..88393d9 100644
--- a/remoting/base/protobuf_http_test_responder.cc
+++ b/remoting/base/protobuf_http_test_responder.cc
@@ -37,7 +37,11 @@
     google::protobuf::MessageLite* out_message) {
   std::string unified_data;
   for (const auto& data_element : *resource_request.request_body->elements()) {
-    unified_data.append(data_element.bytes(), data_element.length());
+    if (data_element.type() == network::DataElement::Tag::kBytes) {
+      const auto piece =
+          data_element.As<network::DataElementBytes>().AsStringPiece();
+      unified_data.append(piece.data(), piece.size());
+    }
   }
   return out_message->ParseFromString(unified_data);
 }
diff --git a/services/image_annotation/annotator_unittest.cc b/services/image_annotation/annotator_unittest.cc
index b8e65f5..3428038 100644
--- a/services/image_annotation/annotator_unittest.cc
+++ b/services/image_annotation/annotator_unittest.cc
@@ -326,9 +326,10 @@
 
       // We only support the simplest body structure.
       if (elements && elements->size() == 1 &&
-          (*elements)[0].type() == network::mojom::DataElementType::kBytes) {
-        actual_body =
-            std::string((*elements)[0].bytes(), (*elements)[0].length());
+          (*elements)[0].type() ==
+              network::mojom::DataElementDataView::Tag::kBytes) {
+        actual_body = std::string(
+            (*elements)[0].As<network::DataElementBytes>().AsStringPiece());
       }
     }
 
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
index fb5b459..a759807 100644
--- a/services/network/network_context.cc
+++ b/services/network/network_context.cc
@@ -96,6 +96,7 @@
 #include "services/network/public/cpp/parsed_headers.h"
 #include "services/network/public/mojom/network_context.mojom-forward.h"
 #include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
 #include "services/network/public/mojom/url_loader_factory.mojom.h"
 #include "services/network/quic_transport.h"
 #include "services/network/resolve_host_request.h"
@@ -638,6 +639,29 @@
   has_trust_tokens_answerers_.Add(std::move(answerer), std::move(receiver));
 }
 
+void NetworkContext::GetStoredTrustTokenCounts(
+    GetStoredTrustTokenCountsCallback callback) {
+  if (trust_token_store_) {
+    auto get_trust_token_counts_from_store =
+        [](NetworkContext::GetStoredTrustTokenCountsCallback callback,
+           TrustTokenStore* trust_token_store) {
+          std::vector<mojom::StoredTrustTokensForIssuerPtr> result;
+          for (auto& issuer_count_pair :
+               trust_token_store->GetStoredTrustTokenCounts()) {
+            result.push_back(mojom::StoredTrustTokensForIssuer::New(
+                std::move(issuer_count_pair.first), issuer_count_pair.second));
+          }
+          std::move(callback).Run(std::move(result));
+        };
+    trust_token_store_->ExecuteOrEnqueue(
+        base::BindOnce(get_trust_token_counts_from_store, std::move(callback)));
+  } else {
+    // The Trust Tokens feature is disabled, return immediately with an empty
+    // vector.
+    std::move(callback).Run({});
+  }
+}
+
 void NetworkContext::OnProxyLookupComplete(
     ProxyLookupRequest* proxy_lookup_request) {
   auto it = proxy_lookup_requests_.find(proxy_lookup_request);
diff --git a/services/network/network_context.h b/services/network/network_context.h
index 0b9c2c4..b3c053a 100644
--- a/services/network/network_context.h
+++ b/services/network/network_context.h
@@ -207,6 +207,8 @@
       const url::Origin& top_frame_origin) override;
   void ClearTrustTokenData(mojom::ClearDataFilterPtr filter,
                            base::OnceClosure done) override;
+  void GetStoredTrustTokenCounts(
+      GetStoredTrustTokenCountsCallback callback) override;
   void ClearNetworkingHistoryBetween(
       base::Time start_time,
       base::Time end_time,
diff --git a/services/network/network_context_unittest.cc b/services/network/network_context_unittest.cc
index 1ad562c..cbd9ada 100644
--- a/services/network/network_context_unittest.cc
+++ b/services/network/network_context_unittest.cc
@@ -6899,6 +6899,121 @@
             mojom::TrustTokenOperationStatus::kUnavailable);
 }
 
+TEST_F(NetworkContextTest, NoAvailableTrustTokensWhenTrustTokensAreDisabled) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndDisableFeature(features::kTrustTokens);
+
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(mojom::NetworkContextParams::New());
+
+  // Allow the store time to initialize asynchronously.
+  base::RunLoop run_loop;
+  base::Optional<std::vector<mojom::StoredTrustTokensForIssuerPtr>>
+      trust_tokens;
+  network_context->GetStoredTrustTokenCounts(base::BindLambdaForTesting(
+      [&trust_tokens,
+       &run_loop](std::vector<mojom::StoredTrustTokensForIssuerPtr> tokens) {
+        trust_tokens = std::move(tokens);
+        run_loop.Quit();
+      }));
+  run_loop.Run();
+
+  ASSERT_TRUE(trust_tokens.has_value());
+  EXPECT_TRUE(trust_tokens->empty());
+}
+
+TEST_F(NetworkContextTest, GetStoredTrustTokens) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
+
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(mojom::NetworkContextParams::New());
+
+  base::RunLoop run_loop;
+
+  // Query Trust Tokens before adding the mock token.
+  base::Optional<std::vector<mojom::StoredTrustTokensForIssuerPtr>>
+      trust_tokens_before_adding;
+  network_context->GetStoredTrustTokenCounts(base::BindLambdaForTesting(
+      [&](std::vector<mojom::StoredTrustTokensForIssuerPtr> tokens) {
+        trust_tokens_before_adding = std::move(tokens);
+      }));
+
+  // Add a mock token.
+  network_context->trust_token_store()->ExecuteOrEnqueue(
+      base::BindLambdaForTesting([&](TrustTokenStore* store) {
+        DCHECK(store);
+        store->AddTokens(
+            *SuitableTrustTokenOrigin::Create(GURL("https://trusttoken.com")),
+            std::vector<std::string>{"token"}, "issuing key");
+      }));
+
+  // Query Trust Tokens after adding the mock token.
+  base::Optional<std::vector<mojom::StoredTrustTokensForIssuerPtr>>
+      trust_tokens_after_adding;
+  network_context->GetStoredTrustTokenCounts(base::BindLambdaForTesting(
+      [&](std::vector<mojom::StoredTrustTokensForIssuerPtr> tokens) {
+        trust_tokens_after_adding = std::move(tokens);
+        run_loop.Quit();
+      }));
+
+  // Allow the store time to initialize asynchronously and execute the
+  // operations.
+  run_loop.Run();
+
+  ASSERT_TRUE(trust_tokens_before_adding.has_value());
+  EXPECT_EQ(trust_tokens_before_adding->size(), 0ul);
+
+  ASSERT_TRUE(trust_tokens_after_adding.has_value());
+  ASSERT_EQ(trust_tokens_after_adding->size(), 1ul);
+  EXPECT_EQ(trust_tokens_after_adding.value()[0]->issuer.Serialize(),
+            "https://trusttoken.com");
+}
+
+TEST_F(NetworkContextTest, GetStoredTrustTokensReentrant) {
+  base::test::ScopedFeatureList scoped_feature_list;
+  scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
+
+  std::unique_ptr<NetworkContext> network_context =
+      CreateContextWithParams(mojom::NetworkContextParams::New());
+
+  // Add a mock token.
+  base::RunLoop run_loop;
+  network_context->trust_token_store()->ExecuteOrEnqueue(
+      base::BindLambdaForTesting([&](TrustTokenStore* store) {
+        DCHECK(store);
+        store->AddTokens(
+            *SuitableTrustTokenOrigin::Create(GURL("https://trusttoken.com")),
+            std::vector<std::string>{"token"}, "issuing key");
+      }));
+
+  base::Optional<std::vector<mojom::StoredTrustTokensForIssuerPtr>>
+      trust_tokens;
+  base::Optional<std::vector<mojom::StoredTrustTokensForIssuerPtr>>
+      reentrant_trust_tokens;
+  network_context->GetStoredTrustTokenCounts(base::BindLambdaForTesting(
+      [&](std::vector<mojom::StoredTrustTokensForIssuerPtr> tokens) {
+        network_context->GetStoredTrustTokenCounts(base::BindLambdaForTesting(
+            [&](std::vector<mojom::StoredTrustTokensForIssuerPtr> tokens) {
+              reentrant_trust_tokens = std::move(tokens);
+              run_loop.Quit();
+            }));
+        trust_tokens = std::move(tokens);
+      }));
+
+  // Allow the store time to initialize asynchronously and execute the
+  // operations.
+  run_loop.Run();
+
+  ASSERT_TRUE(trust_tokens.has_value());
+  ASSERT_TRUE(reentrant_trust_tokens.has_value());
+  EXPECT_EQ(trust_tokens->size(), reentrant_trust_tokens->size());
+  EXPECT_EQ(trust_tokens.value()[0]->issuer,
+            reentrant_trust_tokens.value()[0]->issuer);
+  EXPECT_EQ(trust_tokens.value()[0]->count,
+            reentrant_trust_tokens.value()[0]->count);
+}
+
 }  // namespace
 
 }  // namespace network
diff --git a/services/network/public/cpp/data_element.cc b/services/network/public/cpp/data_element.cc
index db8d7309..361eb95 100644
--- a/services/network/public/cpp/data_element.cc
+++ b/services/network/public/cpp/data_element.cc
@@ -16,62 +16,35 @@
 
 namespace network {
 
-const uint64_t DataElement::kUnknownSize;
+DataElementBytes::DataElementBytes() = default;
+DataElementBytes::DataElementBytes(std::vector<uint8_t> bytes)
+    : bytes_(std::move(bytes)) {}
+DataElementBytes::DataElementBytes(DataElementBytes&& other) = default;
+DataElementBytes& DataElementBytes::operator=(DataElementBytes&& other) =
+    default;
+DataElementBytes::~DataElementBytes() = default;
 
-DataElement::DataElement()
-    : type_(mojom::DataElementType::kUnknown),
-      offset_(0),
-      length_(std::numeric_limits<uint64_t>::max()) {}
-
-DataElement::~DataElement() = default;
-
-DataElement::DataElement(DataElement&& other) = default;
-DataElement& DataElement::operator=(DataElement&& other) = default;
-
-void DataElement::SetToFilePathRange(const base::FilePath& path,
-                                     uint64_t offset,
-                                     uint64_t length,
-                                     base::Time expected_modification_time) {
-  type_ = mojom::DataElementType::kFile;
-  path_ = path;
-  offset_ = offset;
-  length_ = length;
-  expected_modification_time_ = expected_modification_time;
+DataElementDataPipe::DataElementDataPipe() = default;
+DataElementDataPipe::DataElementDataPipe(
+    mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter)
+    : data_pipe_getter_(std::move(data_pipe_getter)) {
+  DCHECK(data_pipe_getter_);
 }
-
-void DataElement::SetToDataPipe(
-    mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) {
-  DCHECK(data_pipe_getter);
-  type_ = mojom::DataElementType::kDataPipe;
-  data_pipe_getter_ = std::move(data_pipe_getter);
-}
-
-void DataElement::SetToChunkedDataPipe(
-    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-        chunked_data_pipe_getter) {
-  type_ = mojom::DataElementType::kChunkedDataPipe;
-  chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
-}
-
-void DataElement::SetToReadOnceStream(
-    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-        chunked_data_pipe_getter) {
-  type_ = mojom::DataElementType::kReadOnceStream;
-  chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
-}
+DataElementDataPipe::DataElementDataPipe(DataElementDataPipe&&) = default;
+DataElementDataPipe& DataElementDataPipe::operator=(
+    DataElementDataPipe&& other) = default;
+DataElementDataPipe::~DataElementDataPipe() = default;
 
 mojo::PendingRemote<mojom::DataPipeGetter>
-DataElement::ReleaseDataPipeGetter() {
-  DCHECK_EQ(mojom::DataElementType::kDataPipe, type_);
+DataElementDataPipe::ReleaseDataPipeGetter() {
   DCHECK(data_pipe_getter_.is_valid());
   return std::move(data_pipe_getter_);
 }
 
-mojo::PendingRemote<mojom::DataPipeGetter> DataElement::CloneDataPipeGetter()
-    const {
-  DCHECK_EQ(mojom::DataElementType::kDataPipe, type_);
+mojo::PendingRemote<mojom::DataPipeGetter>
+DataElementDataPipe::CloneDataPipeGetter() const {
   DCHECK(data_pipe_getter_.is_valid());
-  auto* mutable_this = const_cast<DataElement*>(this);
+  auto* mutable_this = const_cast<DataElementDataPipe*>(this);
   mojo::Remote<mojom::DataPipeGetter> owned(
       std::move(mutable_this->data_pipe_getter_));
   mojo::PendingRemote<mojom::DataPipeGetter> clone;
@@ -80,80 +53,42 @@
   return clone;
 }
 
-const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>&
-DataElement::chunked_data_pipe_getter() const {
-  DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe ||
-         type_ == mojom::DataElementType::kReadOnceStream);
-  return chunked_data_pipe_getter_;
+DataElementChunkedDataPipe::DataElementChunkedDataPipe() = default;
+DataElementChunkedDataPipe::DataElementChunkedDataPipe(
+    mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter,
+    ReadOnlyOnce read_only_once)
+    : chunked_data_pipe_getter_(std::move(chunked_data_pipe_getter)),
+      read_only_once_(read_only_once) {
+  DCHECK(chunked_data_pipe_getter_);
 }
+DataElementChunkedDataPipe::DataElementChunkedDataPipe(
+    DataElementChunkedDataPipe&& other) = default;
+DataElementChunkedDataPipe& DataElementChunkedDataPipe::operator=(
+    DataElementChunkedDataPipe&& other) = default;
+DataElementChunkedDataPipe::~DataElementChunkedDataPipe() = default;
 
 mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-DataElement::ReleaseChunkedDataPipeGetter() {
-  DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe ||
-         type_ == mojom::DataElementType::kReadOnceStream)
-      << type_;
+DataElementChunkedDataPipe::ReleaseChunkedDataPipeGetter() {
+  DCHECK(chunked_data_pipe_getter_.is_valid());
   return std::move(chunked_data_pipe_getter_);
 }
 
-void PrintTo(const DataElement& x, std::ostream* os) {
-  const uint64_t kMaxDataPrintLength = 40;
-  *os << "<DataElement>{type: ";
-  switch (x.type()) {
-    case mojom::DataElementType::kBytes: {
-      uint64_t length = std::min(x.length(), kMaxDataPrintLength);
-      *os << "TYPE_BYTES, data: ["
-          << base::HexEncode(x.bytes(), static_cast<size_t>(length));
-      if (length < x.length()) {
-        *os << "<...truncated due to length...>";
-      }
-      *os << "]";
-      break;
-    }
-    case mojom::DataElementType::kFile:
-      *os << "TYPE_FILE, path: " << x.path().AsUTF8Unsafe()
-          << ", expected_modification_time: " << x.expected_modification_time();
-      break;
-    case mojom::DataElementType::kDataPipe:
-      *os << "TYPE_DATA_PIPE";
-      break;
-    case mojom::DataElementType::kChunkedDataPipe:
-      *os << "TYPE_CHUNKED_DATA_PIPE";
-      break;
-    case mojom::DataElementType::kReadOnceStream:
-      *os << "TYPE_READ_ONCE_STREAM";
-      break;
-    case mojom::DataElementType::kUnknown:
-      *os << "TYPE_UNKNOWN";
-      break;
-  }
-  *os << ", length: " << x.length() << ", offset: " << x.offset() << "}";
-}
+DataElementFile::DataElementFile() = default;
+DataElementFile::DataElementFile(const base::FilePath& path,
+                                 uint64_t offset,
+                                 uint64_t length,
+                                 base::Time expected_modification_time)
+    : path_(path),
+      offset_(offset),
+      length_(length),
+      expected_modification_time_(expected_modification_time) {}
+DataElementFile::DataElementFile(DataElementFile&&) = default;
+DataElementFile& DataElementFile::operator=(DataElementFile&&) = default;
+DataElementFile::~DataElementFile() = default;
 
-bool operator==(const DataElement& a, const DataElement& b) {
-  if (a.type() != b.type() || a.offset() != b.offset() ||
-      a.length() != b.length())
-    return false;
-  switch (a.type()) {
-    case mojom::DataElementType::kBytes:
-      return memcmp(a.bytes(), b.bytes(), b.length()) == 0;
-    case mojom::DataElementType::kFile:
-      return a.path() == b.path() &&
-             a.expected_modification_time() == b.expected_modification_time();
-    case mojom::DataElementType::kDataPipe:
-      return false;
-    case mojom::DataElementType::kChunkedDataPipe:
-      return false;
-    case mojom::DataElementType::kReadOnceStream:
-      return false;
-    case mojom::DataElementType::kUnknown:
-      NOTREACHED();
-      return false;
-  }
-  return false;
-}
-
-bool operator!=(const DataElement& a, const DataElement& b) {
-  return !(a == b);
-}
+DataElement::DataElement() = default;
+DataElement::DataElement(DataElement&& other) = default;
+DataElement& DataElement::operator=(DataElement&& other) = default;
+DataElement::~DataElement() = default;
 
 }  // namespace network
diff --git a/services/network/public/cpp/data_element.h b/services/network/public/cpp/data_element.h
index 1e4d1e8..84e1859a 100644
--- a/services/network/public/cpp/data_element.h
+++ b/services/network/public/cpp/data_element.h
@@ -10,133 +10,188 @@
 
 #include <limits>
 #include <memory>
-#include <ostream>
-#include <string>
+#include <utility>
 #include <vector>
 
 #include "base/check_op.h"
 #include "base/component_export.h"
 #include "base/files/file_path.h"
-#include "base/gtest_prod_util.h"
+#include "base/strings/string_piece.h"
 #include "base/time/time.h"
-#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "base/types/strong_alias.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/system/data_pipe.h"
 #include "services/network/public/mojom/chunked_data_pipe_getter.mojom-forward.h"
 #include "services/network/public/mojom/data_pipe_getter.mojom-forward.h"
 #include "services/network/public/mojom/url_loader.mojom-shared.h"
-#include "url/gurl.h"
-
-namespace blink {
-namespace mojom {
-class FetchAPIDataElementDataView;
-}  // namespace mojom
-}  // namespace blink
+#include "third_party/abseil-cpp/absl/types/variant.h"
 
 namespace network {
 
-// Represents part of an upload body. This could be one of raw bytes, file data,
-// or a mojo pipe that streams data.
-class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement {
+// Represents a part of a request body consisting of bytes.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementBytes final {
  public:
-  static const uint64_t kUnknownSize = std::numeric_limits<uint64_t>::max();
+  // Do NOT use this constructor outside of mojo deserialization context.
+  DataElementBytes();
 
-  DataElement();
-  ~DataElement();
+  explicit DataElementBytes(std::vector<uint8_t> bytes);
+  DataElementBytes(const DataElementBytes&) = delete;
+  DataElementBytes(DataElementBytes&& other);
+  DataElementBytes& operator=(const DataElementBytes&) = delete;
+  DataElementBytes& operator=(DataElementBytes&& other);
+  ~DataElementBytes();
 
-  DataElement(const DataElement&) = delete;
-  void operator=(const DataElement&) = delete;
-  DataElement(DataElement&& other);
-  DataElement& operator=(DataElement&& other);
+  const std::vector<uint8_t>& bytes() const { return bytes_; }
 
-  mojom::DataElementType type() const { return type_; }
-  const char* bytes() const {
-    return reinterpret_cast<const char*>(buf_.data());
-  }
-  const base::FilePath& path() const { return path_; }
-  uint64_t offset() const { return offset_; }
-  uint64_t length() const { return length_; }
-  const base::Time& expected_modification_time() const {
-    return expected_modification_time_;
+  base::StringPiece AsStringPiece() const {
+    return base::StringPiece(reinterpret_cast<const char*>(bytes_.data()),
+                             bytes_.size());
   }
 
-  // Sets TYPE_BYTES data. This copies the given data into the element.
-  void SetToBytes(const char* bytes, int bytes_len) {
-    type_ = mojom::DataElementType::kBytes;
-    buf_.assign(reinterpret_cast<const uint8_t*>(bytes),
-                reinterpret_cast<const uint8_t*>(bytes + bytes_len));
-    length_ = buf_.size();
-  }
+ private:
+  std::vector<uint8_t> bytes_;
+};
 
-  // Sets TYPE_BYTES data. This moves the given data vector into the element.
-  void SetToBytes(std::vector<uint8_t> bytes) {
-    type_ = mojom::DataElementType::kBytes;
-    buf_ = std::move(bytes);
-    length_ = buf_.size();
-  }
+// Represents a part of a request body consisting of a data pipe. This is
+// typically used for blobs.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementDataPipe final {
+ public:
+  // Do NOT use this constructor outside of mojo deserialization context.
+  DataElementDataPipe();
 
-  // Sets TYPE_FILE data with range.
-  void SetToFilePathRange(const base::FilePath& path,
-                          uint64_t offset,
-                          uint64_t length,
-                          base::Time expected_modification_time);
-
-  // Sets TYPE_DATA_PIPE data. The data pipe consumer can safely wait for the
-  // callback passed to Read() to be invoked before reading the request body.
-  void SetToDataPipe(
+  explicit DataElementDataPipe(
       mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter);
+  DataElementDataPipe(const DataElementDataPipe&) = delete;
+  DataElementDataPipe(DataElementDataPipe&& other);
+  DataElementDataPipe& operator=(const DataElementDataPipe&) = delete;
+  DataElementDataPipe& operator=(DataElementDataPipe&& other);
+  ~DataElementDataPipe();
 
-  // Sets TYPE_CHUNKED_DATA_PIPE data. The data pipe consumer must not wait
-  // for the callback passed to GetSize() to be invoked before reading the
-  // request body, as the length may not be known until the entire body has been
-  // sent. This method triggers a chunked upload, which not all servers may
-  // support, so SetToDataPipe should be used instead, unless talking with a
-  // server known to support chunked uploads.
-  void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-                                chunked_data_pipe_getter);
-  // Almost same as above except |chunked_data_pipe_getter| is read only once
-  // and you must talk with a server supporting chunked upload.
-  void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-                               chunked_data_pipe_getter);
-
-  // Takes ownership of the DataPipeGetter, if this is of TYPE_DATA_PIPE.
   mojo::PendingRemote<mojom::DataPipeGetter> ReleaseDataPipeGetter();
   mojo::PendingRemote<mojom::DataPipeGetter> CloneDataPipeGetter() const;
 
-  // Can be called only when this is of type kChunkedDataPipe or
-  // kReadOnceStream.
+ private:
+  mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_;
+};
+
+// Represents a part of a request body consisting of a data pipe without a
+// known size.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementChunkedDataPipe final {
+ public:
+  using ReadOnlyOnce = base::StrongAlias<class ReadOnlyOnceTag, bool>;
+
+  // Do NOT use this constructor outside of mojo deserialization context.
+  DataElementChunkedDataPipe();
+
+  DataElementChunkedDataPipe(
+      mojo::PendingRemote<mojom::ChunkedDataPipeGetter> data_pipe_getter,
+      ReadOnlyOnce read_only_once);
+  DataElementChunkedDataPipe(const DataElementChunkedDataPipe&) = delete;
+  DataElementChunkedDataPipe(DataElementChunkedDataPipe&& other);
+  DataElementChunkedDataPipe& operator=(const DataElementChunkedDataPipe&) =
+      delete;
+  DataElementChunkedDataPipe& operator=(DataElementChunkedDataPipe&& other);
+  ~DataElementChunkedDataPipe();
+
   const mojo::PendingRemote<mojom::ChunkedDataPipeGetter>&
-  chunked_data_pipe_getter() const;
-  // Takes ownership of the DataPipeGetter, if this is of
-  // kChunkedDataPipe or kReadOnceStream.
+  chunked_data_pipe_getter() const {
+    return chunked_data_pipe_getter_;
+  }
   mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
   ReleaseChunkedDataPipeGetter();
 
+  ReadOnlyOnce read_only_once() const { return read_only_once_; }
+
  private:
-  FRIEND_TEST_ALL_PREFIXES(BlobAsyncTransportStrategyTest, TestInvalidParams);
-  friend void PrintTo(const DataElement& x, ::std::ostream* os);
-  friend struct mojo::StructTraits<network::mojom::DataElementDataView,
-                                   network::DataElement>;
-  friend struct mojo::StructTraits<blink::mojom::FetchAPIDataElementDataView,
-                                   network::DataElement>;
-  mojom::DataElementType type_;
-  // For TYPE_BYTES.
-  std::vector<uint8_t> buf_;
-  // For TYPE_FILE.
-  base::FilePath path_;
-  // For TYPE_DATA_PIPE.
-  mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter_;
-  // For TYPE_CHUNKED_DATA_PIPE.
   mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter_;
-  uint64_t offset_;
-  uint64_t length_;
+  ReadOnlyOnce read_only_once_;
+};
+
+// Represents a part of a request body consisting of (part of) a file.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElementFile final {
+ public:
+  // Do NOT use this constructor outside of mojo deserialization context.
+  DataElementFile();
+
+  DataElementFile(const base::FilePath& path,
+                  uint64_t offset,
+                  uint64_t length,
+                  base::Time expected_modification_time);
+  DataElementFile(const DataElementFile&);
+  DataElementFile& operator=(const DataElementFile&);
+  DataElementFile(DataElementFile&&);
+  DataElementFile& operator=(DataElementFile&&);
+  ~DataElementFile();
+
+  const base::FilePath& path() const { return path_; }
+  uint64_t offset() const { return offset_; }
+  uint64_t length() const { return length_; }
+  base::Time expected_modification_time() const {
+    return expected_modification_time_;
+  }
+
+ private:
+  base::FilePath path_;
+  uint64_t offset_ = 0;
+  uint64_t length_ = 0;
   base::Time expected_modification_time_;
 };
 
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-bool operator==(const DataElement& a, const DataElement& b);
-COMPONENT_EXPORT(NETWORK_CPP_BASE)
-bool operator!=(const DataElement& a, const DataElement& b);
+// Represents part of an upload body. This is a union of various types defined
+// above. See them for details.
+class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement {
+ public:
+  using Tag = mojom::DataElementDataView::Tag;
+
+  // Do NOT use this constructor outside of mojo deserialization context. A
+  // DataElement created by this constructor should be considered as invalid,
+  // and replaced with a valid value as soon as possible.
+  DataElement();
+
+  template <typename T>
+  explicit DataElement(T&& t) : variant_(std::forward<T>(t)) {}
+  DataElement(const DataElement&) = delete;
+  DataElement& operator=(const DataElement&) = delete;
+  DataElement(DataElement&& other);
+  DataElement& operator=(DataElement&& other);
+  ~DataElement();
+
+  Tag type() const {
+    switch (variant_.index()) {
+      case 0:
+        NOTREACHED();
+        return Tag::kBytes;
+      case 1:
+        return Tag::kBytes;
+      case 2:
+        return Tag::kDataPipe;
+      case 3:
+        return Tag::kChunkedDataPipe;
+      case 4:
+        return Tag::kFile;
+      default:
+        NOTREACHED();
+        return Tag::kBytes;
+    }
+  }
+
+  template <typename T>
+  const T& As() const {
+    return absl::get<T>(variant_);
+  }
+
+  template <typename T>
+  T& As() {
+    return absl::get<T>(variant_);
+  }
+
+ private:
+  absl::variant<absl::monostate,
+                DataElementBytes,
+                DataElementDataPipe,
+                DataElementChunkedDataPipe,
+                DataElementFile>
+      variant_;
+};
 
 }  // namespace network
 
diff --git a/services/network/public/cpp/network_ipc_param_traits.cc b/services/network/public/cpp/network_ipc_param_traits.cc
index edab086..f4cca33 100644
--- a/services/network/public/cpp/network_ipc_param_traits.cc
+++ b/services/network/public/cpp/network_ipc_param_traits.cc
@@ -19,31 +19,33 @@
                                               const param_type& p) {
   WriteParam(m, static_cast<int>(p.type()));
   switch (p.type()) {
-    case network::mojom::DataElementType::kBytes: {
-      m->WriteData(p.bytes(), static_cast<int>(p.length()));
+    case network::mojom::DataElementDataView::Tag::kBytes: {
+      const auto& bytes = p.As<network::DataElementBytes>().bytes();
+      m->WriteData(reinterpret_cast<const char*>(bytes.data()),
+                   static_cast<int>(bytes.size()));
       break;
     }
-    case network::mojom::DataElementType::kFile: {
-      WriteParam(m, p.path());
-      WriteParam(m, p.offset());
-      WriteParam(m, p.length());
-      WriteParam(m, p.expected_modification_time());
+    case network::mojom::DataElementDataView::Tag::kFile: {
+      const auto& file = p.As<network::DataElementFile>();
+      WriteParam(m, file.path());
+      WriteParam(m, file.offset());
+      WriteParam(m, file.length());
+      WriteParam(m, file.expected_modification_time());
       break;
     }
-    case network::mojom::DataElementType::kDataPipe: {
-      WriteParam(m, p.CloneDataPipeGetter().PassPipe().release());
-      break;
-    }
-    case network::mojom::DataElementType::kChunkedDataPipe: {
-      WriteParam(m, const_cast<network::DataElement&>(p)
-                        .ReleaseChunkedDataPipeGetter()
+    case network::mojom::DataElementDataView::Tag::kDataPipe: {
+      WriteParam(m, p.As<network::DataElementDataPipe>()
+                        .CloneDataPipeGetter()
                         .PassPipe()
                         .release());
       break;
     }
-    case network::mojom::DataElementType::kReadOnceStream:
-    case network::mojom::DataElementType::kUnknown: {
-      NOTREACHED();
+    case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: {
+      auto& element = const_cast<network::DataElement&>(p)
+                          .As<network::DataElementChunkedDataPipe>();
+      DCHECK(!element.read_only_once());
+      WriteParam(m,
+                 element.ReleaseChunkedDataPipeGetter().PassPipe().release());
       break;
     }
   }
@@ -55,16 +57,19 @@
   int type;
   if (!ReadParam(m, iter, &type))
     return false;
-  switch (static_cast<network::mojom::DataElementType>(type)) {
-    case network::mojom::DataElementType::kBytes: {
-      const char* data;
+  switch (static_cast<network::mojom::DataElementDataView::Tag>(type)) {
+    case network::mojom::DataElementDataView::Tag::kBytes: {
+      const char* char_data;
       int len;
-      if (!iter->ReadData(&data, &len))
+      if (!iter->ReadData(&char_data, &len))
         return false;
-      r->SetToBytes(data, len);
+      const uint8_t* data = reinterpret_cast<const uint8_t*>(char_data);
+      *r = network::DataElement(
+          network::DataElementBytes(std::vector<uint8_t>(data, data + len)));
+      DCHECK_EQ(static_cast<int>(r->type()), type);
       return true;
     }
-    case network::mojom::DataElementType::kFile: {
+    case network::mojom::DataElementDataView::Tag::kFile: {
       base::FilePath file_path;
       uint64_t offset, length;
       base::Time expected_modification_time;
@@ -76,35 +81,42 @@
         return false;
       if (!ReadParam(m, iter, &expected_modification_time))
         return false;
-      r->SetToFilePathRange(file_path, offset, length,
-                            expected_modification_time);
+      *r = network::DataElement(network::DataElementFile(
+          file_path, offset, length, expected_modification_time));
+      DCHECK_EQ(static_cast<int>(r->type()), type);
       return true;
     }
-    case network::mojom::DataElementType::kDataPipe: {
+    case network::mojom::DataElementDataView::Tag::kDataPipe: {
       mojo::MessagePipeHandle message_pipe;
       if (!ReadParam(m, iter, &message_pipe))
         return false;
+      if (!message_pipe) {
+        return false;
+      }
       mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
           mojo::ScopedMessagePipeHandle(message_pipe), 0u);
-      r->SetToDataPipe(std::move(data_pipe_getter));
+      *r = network::DataElement(
+          network::DataElementDataPipe(std::move(data_pipe_getter)));
+      DCHECK_EQ(static_cast<int>(r->type()), type);
       return true;
     }
-    case network::mojom::DataElementType::kChunkedDataPipe: {
+    case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: {
       mojo::MessagePipeHandle message_pipe;
       if (!ReadParam(m, iter, &message_pipe))
         return false;
+      if (!message_pipe) {
+        return false;
+      }
       mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
           chunked_data_pipe_getter(mojo::ScopedMessagePipeHandle(message_pipe),
                                    0u);
 
-      r->SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
+      *r = network::DataElement(network::DataElementChunkedDataPipe(
+          std::move(chunked_data_pipe_getter),
+          network::DataElementChunkedDataPipe::ReadOnlyOnce(false)));
+      DCHECK_EQ(static_cast<int>(r->type()), type);
       return true;
     }
-    case network::mojom::DataElementType::kReadOnceStream:
-    case network::mojom::DataElementType::kUnknown: {
-      NOTREACHED();
-      return false;
-    }
   }
   return false;
 }
@@ -140,8 +152,9 @@
   // A chunked element is only allowed if it's the only one element.
   if (elements.size() > 1) {
     for (const auto& element : elements) {
-      if (element.type() == network::mojom::DataElementType::kChunkedDataPipe)
+      if (element.type() == network::DataElement::Tag::kChunkedDataPipe) {
         return false;
+      }
     }
   }
   int64_t identifier;
diff --git a/services/network/public/cpp/resource_request_body.cc b/services/network/public/cpp/resource_request_body.cc
index 59c1b356..c8e7b4e 100644
--- a/services/network/public/cpp/resource_request_body.cc
+++ b/services/network/public/cpp/resource_request_body.cc
@@ -24,16 +24,14 @@
 bool ResourceRequestBody::EnableToAppendElement() const {
   return elements_.empty() ||
          (elements_.front().type() !=
-              mojom::DataElementType::kChunkedDataPipe &&
-          elements_.front().type() != mojom::DataElementType::kReadOnceStream);
+          mojom::DataElementDataView::Tag::kChunkedDataPipe);
 }
 
 void ResourceRequestBody::AppendBytes(std::vector<uint8_t> bytes) {
   DCHECK(EnableToAppendElement());
 
   if (bytes.size() > 0) {
-    elements_.push_back(DataElement());
-    elements_.back().SetToBytes(std::move(bytes));
+    elements_.emplace_back(DataElementBytes(std::move(bytes)));
   }
 }
 
@@ -52,42 +50,34 @@
     const base::Time& expected_modification_time) {
   DCHECK(EnableToAppendElement());
 
-  elements_.push_back(DataElement());
-  elements_.back().SetToFilePathRange(file_path, offset, length,
-                                      expected_modification_time);
+  elements_.emplace_back(
+      DataElementFile(file_path, offset, length, expected_modification_time));
 }
 
 void ResourceRequestBody::AppendDataPipe(
     mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) {
   DCHECK(EnableToAppendElement());
+  DCHECK(data_pipe_getter);
 
-  elements_.push_back(DataElement());
-  elements_.back().SetToDataPipe(std::move(data_pipe_getter));
+  elements_.emplace_back(DataElementDataPipe(std::move(data_pipe_getter)));
 }
 
 void ResourceRequestBody::SetToChunkedDataPipe(
-    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-        chunked_data_pipe_getter) {
+    mojo::PendingRemote<mojom::ChunkedDataPipeGetter> chunked_data_pipe_getter,
+    ReadOnlyOnce read_only_once) {
   DCHECK(elements_.empty());
+  DCHECK(chunked_data_pipe_getter);
 
-  elements_.push_back(DataElement());
-  elements_.back().SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
-}
-
-void ResourceRequestBody::SetToReadOnceStream(
-    mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-        chunked_data_pipe_getter) {
-  DCHECK(elements_.empty());
-
-  elements_.push_back(DataElement());
-  elements_.back().SetToReadOnceStream(std::move(chunked_data_pipe_getter));
+  elements_.emplace_back(DataElementChunkedDataPipe(
+      std::move(chunked_data_pipe_getter), read_only_once));
 }
 
 std::vector<base::FilePath> ResourceRequestBody::GetReferencedFiles() const {
   std::vector<base::FilePath> result;
   for (const auto& element : *elements()) {
-    if (element.type() == mojom::DataElementType::kFile)
-      result.push_back(element.path());
+    if (element.type() == mojom::DataElementDataView::Tag::kFile) {
+      result.push_back(element.As<DataElementFile>().path());
+    }
   }
   return result;
 }
diff --git a/services/network/public/cpp/resource_request_body.h b/services/network/public/cpp/resource_request_body.h
index 8c851736..410e83c1 100644
--- a/services/network/public/cpp/resource_request_body.h
+++ b/services/network/public/cpp/resource_request_body.h
@@ -32,6 +32,8 @@
 class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
     : public base::RefCountedThreadSafe<ResourceRequestBody> {
  public:
+  using ReadOnlyOnce = DataElementChunkedDataPipe::ReadOnlyOnce;
+
   ResourceRequestBody();
 
   // Creates ResourceRequestBody that holds a copy of |bytes|.
@@ -59,7 +61,8 @@
   // method should only be used when talking to servers that are are known to
   // support chunked uploads.
   void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
-                                chunked_data_pipe_getter);
+                                chunked_data_pipe_getter,
+                            ReadOnlyOnce read_only_once);
   // Almost same as above except |chunked_data_pipe_getter| is read only once
   // and you must talk with a server supporting chunked upload.
   void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
@@ -84,7 +87,7 @@
   int64_t identifier() const { return identifier_; }
 
   // Returns paths referred to by |elements| of type
-  // network::mojom::DataElementType::kFile.
+  // network::mojom::DataElementDataView::Tag::kFile.
   std::vector<base::FilePath> GetReferencedFiles() const;
 
   // Sets the flag which indicates whether the post data contains sensitive
diff --git a/services/network/public/cpp/simple_url_loader.cc b/services/network/public/cpp/simple_url_loader.cc
index 779be1f9..b6d6de5f 100644
--- a/services/network/public/cpp/simple_url_loader.cc
+++ b/services/network/public/cpp/simple_url_loader.cc
@@ -1168,8 +1168,8 @@
 
       // Bytes should be attached with AttachStringForUpload to allow
       // streaming of large byte buffers to the network process when uploading.
-      DCHECK(element.type() != mojom::DataElementType::kFile &&
-             element.type() != mojom::DataElementType::kBytes);
+      DCHECK(element.type() != mojom::DataElementDataView::Tag::kFile &&
+             element.type() != mojom::DataElementDataView::Tag::kBytes);
     }
   }
 #endif  // DCHECK_IS_ON()
@@ -1357,7 +1357,7 @@
       // pipe.
       // TODO(mmenke):  Data pipes can be Cloned(), though, so maybe update code
       // to do that?
-      DCHECK(element.type() != mojom::DataElementType::kDataPipe);
+      DCHECK(element.type() != mojom::DataElementDataView::Tag::kDataPipe);
     }
   }
 #endif  // DCHECK_IS_ON()
diff --git a/services/network/public/cpp/simple_url_loader_unittest.cc b/services/network/public/cpp/simple_url_loader_unittest.cc
index 2b9a8a2..1884468f 100644
--- a/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -1966,9 +1966,10 @@
         test_events_(std::move(test_events)) {
     if (request_body && request_body->elements()->size() == 1 &&
         (*request_body->elements())[0].type() ==
-            network::mojom::DataElementType::kDataPipe) {
-      data_pipe_getter_.Bind(
-          (*request_body->elements())[0].CloneDataPipeGetter());
+            network::mojom::DataElementDataView::Tag::kDataPipe) {
+      const auto& element =
+          (*request_body->elements())[0].As<network::DataElementDataPipe>();
+      data_pipe_getter_.Bind(element.CloneDataPipeGetter());
       DCHECK(data_pipe_getter_);
     }
   }
diff --git a/services/network/public/cpp/url_request_mojom_traits.cc b/services/network/public/cpp/url_request_mojom_traits.cc
index b44e8cf..eff7089 100644
--- a/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/services/network/public/cpp/url_request_mojom_traits.cc
@@ -7,6 +7,7 @@
 #include <vector>
 
 #include "base/debug/dump_without_crashing.h"
+#include "base/metrics/histogram_macros.h"
 #include "base/notreached.h"
 #include "mojo/public/cpp/base/file_mojom_traits.h"
 #include "mojo/public/cpp/base/file_path_mojom_traits.h"
@@ -274,35 +275,100 @@
   return true;
 }
 
-bool StructTraits<network::mojom::DataElementDataView, network::DataElement>::
-    Read(network::mojom::DataElementDataView data, network::DataElement* out) {
-  if (!data.ReadPath(&out->path_)) {
-    network::debug::SetDeserializationCrashKeyString("data_element_path");
+bool StructTraits<network::mojom::DataElementBytesDataView,
+                  network::DataElementBytes>::
+    Read(network::mojom::DataElementBytesDataView data,
+         network::DataElementBytes* out) {
+  mojo_base::BigBufferView big_buffer_view;
+  if (!data.ReadData(&big_buffer_view)) {
     return false;
   }
-  if (!data.ReadExpectedModificationTime(&out->expected_modification_time_)) {
-    return false;
-  }
-  if (data.type() == network::mojom::DataElementType::kBytes) {
-    mojo_base::BigBufferView big_buffer;
-    if (!data.ReadBuf(&big_buffer))
-      return false;
-    // TODO(yoichio): Fix DataElementDataView::ReadBuf issue
-    // (crbug.com/1152664).
-    if (data.length() != big_buffer.data().size())
-      return false;
-    out->buf_.clear();
-    out->buf_.insert(out->buf_.end(), big_buffer.data().begin(),
-                     big_buffer.data().end());
-  }
-  out->type_ = data.type();
-  out->data_pipe_getter_ = data.TakeDataPipeGetter<
-      mojo::PendingRemote<network::mojom::DataPipeGetter>>();
-  out->chunked_data_pipe_getter_ = data.TakeChunkedDataPipeGetter<
-      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
-  out->offset_ = data.offset();
-  out->length_ = data.length();
+  *out = network::DataElementBytes(std::vector<uint8_t>(
+      big_buffer_view.data().begin(), big_buffer_view.data().end()));
   return true;
 }
 
+bool StructTraits<network::mojom::DataElementDataPipeDataView,
+                  network::DataElementDataPipe>::
+    Read(network::mojom::DataElementDataPipeDataView data,
+         network::DataElementDataPipe* out) {
+  auto data_pipe_getter = data.TakeDataPipeGetter<
+      mojo::PendingRemote<network::mojom::DataPipeGetter>>();
+  *out = network::DataElementDataPipe(std::move(data_pipe_getter));
+  return true;
+}
+
+bool StructTraits<network::mojom::DataElementChunkedDataPipeDataView,
+                  network::DataElementChunkedDataPipe>::
+    Read(network::mojom::DataElementChunkedDataPipeDataView data,
+         network::DataElementChunkedDataPipe* out) {
+  auto data_pipe_getter = data.TakeDataPipeGetter<
+      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
+  UMA_HISTOGRAM_BOOLEAN("NetworkService.StreamingUploadDataPipeGetterValidity",
+                        data_pipe_getter.is_valid());
+  *out = network::DataElementChunkedDataPipe(
+      std::move(data_pipe_getter),
+      network::DataElementChunkedDataPipe::ReadOnlyOnce(data.read_only_once()));
+  return true;
+}
+
+bool StructTraits<network::mojom::DataElementFileDataView,
+                  network::DataElementFile>::
+    Read(network::mojom::DataElementFileDataView data,
+         network::DataElementFile* out) {
+  base::FilePath path;
+  if (!data.ReadPath(&path)) {
+    return false;
+  }
+  base::Time expected_modification_time;
+  if (!data.ReadExpectedModificationTime(&expected_modification_time)) {
+    return false;
+  }
+  *out = network::DataElementFile(path, data.offset(), data.length(),
+                                  expected_modification_time);
+  return true;
+}
+
+bool UnionTraits<network::mojom::DataElementDataView, network::DataElement>::
+    Read(network::mojom::DataElementDataView data, network::DataElement* out) {
+  using Tag = network::mojom::DataElementDataView::Tag;
+  DCHECK(!data.is_null());
+
+  switch (data.tag()) {
+    case Tag::kBytes: {
+      network::DataElementBytes bytes;
+      if (!data.ReadBytes(&bytes)) {
+        return false;
+      }
+      *out = network::DataElement(std::move(bytes));
+      return true;
+    }
+    case Tag::kDataPipe: {
+      network::DataElementDataPipe data_pipe;
+      if (!data.ReadDataPipe(&data_pipe)) {
+        return false;
+      }
+      *out = network::DataElement(std::move(data_pipe));
+      return true;
+    }
+    case Tag::kChunkedDataPipe: {
+      network::DataElementChunkedDataPipe chunked_data_pipe;
+      if (!data.ReadChunkedDataPipe(&chunked_data_pipe)) {
+        return false;
+      }
+      *out = network::DataElement(std::move(chunked_data_pipe));
+      return true;
+    }
+    case Tag::kFile: {
+      network::DataElementFile file;
+      if (!data.ReadFile(&file)) {
+        return false;
+      }
+      *out = network::DataElement(std::move(file));
+      return true;
+    }
+  }
+  return false;
+}
+
 }  // namespace mojo
diff --git a/services/network/public/cpp/url_request_mojom_traits.h b/services/network/public/cpp/url_request_mojom_traits.h
index 819cab67..5bfc97e1 100644
--- a/services/network/public/cpp/url_request_mojom_traits.h
+++ b/services/network/public/cpp/url_request_mojom_traits.h
@@ -17,6 +17,7 @@
 #include "mojo/public/cpp/bindings/enum_traits.h"
 #include "mojo/public/cpp/bindings/pending_remote.h"
 #include "mojo/public/cpp/bindings/struct_traits.h"
+#include "mojo/public/cpp/bindings/union_traits.h"
 #include "net/base/request_priority.h"
 #include "net/url_request/referrer_policy.h"
 #include "services/network/public/cpp/data_element.h"
@@ -330,40 +331,91 @@
 
 template <>
 struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
-    StructTraits<network::mojom::DataElementDataView, network::DataElement> {
-  static const network::mojom::DataElementType& type(
-      const network::DataElement& element) {
-    return element.type_;
+    StructTraits<network::mojom::DataElementBytesDataView,
+                 network::DataElementBytes> {
+  static mojo_base::BigBufferView data(const network::DataElementBytes& data) {
+    return mojo_base::BigBufferView(data.bytes());
   }
-  static mojo_base::BigBufferView buf(const network::DataElement& element) {
-    return mojo_base::BigBufferView(element.buf_);
-  }
-  static const base::FilePath& path(const network::DataElement& element) {
-    return element.path_;
-  }
+
+  static bool Read(network::mojom::DataElementBytesDataView data,
+                   network::DataElementBytes* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+    StructTraits<network::mojom::DataElementDataPipeDataView,
+                 network::DataElementDataPipe> {
   static mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
-      const network::DataElement& element) {
-    if (element.type_ != network::mojom::DataElementType::kDataPipe)
-      return mojo::NullRemote();
-    return element.CloneDataPipeGetter();
+      const network::DataElementDataPipe& data) {
+    return data.CloneDataPipeGetter();
   }
+
+  static bool Read(network::mojom::DataElementDataPipeDataView data,
+                   network::DataElementDataPipe* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+    StructTraits<network::mojom::DataElementChunkedDataPipeDataView,
+                 network::DataElementChunkedDataPipe> {
   static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
-  chunked_data_pipe_getter(const network::DataElement& element) {
-    if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe &&
-        element.type_ != network::mojom::DataElementType::kReadOnceStream)
-      return mojo::NullRemote();
-    return const_cast<network::DataElement&>(element)
+  data_pipe_getter(const network::DataElementChunkedDataPipe& data) {
+    return const_cast<network::DataElementChunkedDataPipe&>(data)
         .ReleaseChunkedDataPipeGetter();
   }
-  static uint64_t offset(const network::DataElement& element) {
-    return element.offset_;
+  static bool read_only_once(const network::DataElementChunkedDataPipe& data) {
+    return static_cast<bool>(data.read_only_once());
   }
-  static uint64_t length(const network::DataElement& element) {
-    return element.length_;
+
+  static bool Read(network::mojom::DataElementChunkedDataPipeDataView data,
+                   network::DataElementChunkedDataPipe* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+    StructTraits<network::mojom::DataElementFileDataView,
+                 network::DataElementFile> {
+  static base::FilePath path(const network::DataElementFile& data) {
+    return data.path();
   }
-  static const base::Time& expected_modification_time(
-      const network::DataElement& element) {
-    return element.expected_modification_time_;
+  static uint64_t offset(const network::DataElementFile& data) {
+    return data.offset();
+  }
+  static uint64_t length(const network::DataElementFile& data) {
+    return data.length();
+  }
+  static base::Time expected_modification_time(
+      const network::DataElementFile& data) {
+    return data.expected_modification_time();
+  }
+
+  static bool Read(network::mojom::DataElementFileDataView data,
+                   network::DataElementFile* out);
+};
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+    UnionTraits<network::mojom::DataElementDataView, network::DataElement> {
+  static network::mojom::DataElementDataView::Tag GetTag(
+      const network::DataElement& data) {
+    return data.type();
+  }
+
+  static const network::DataElementBytes& bytes(
+      const network::DataElement& data) {
+    return data.As<network::DataElementBytes>();
+  }
+  static const network::DataElementDataPipe& data_pipe(
+      const network::DataElement& data) {
+    return data.As<network::DataElementDataPipe>();
+  }
+  static const network::DataElementChunkedDataPipe& chunked_data_pipe(
+      const network::DataElement& data) {
+    return data.As<network::DataElementChunkedDataPipe>();
+  }
+  static const network::DataElementFile& file(
+      const network::DataElement& data) {
+    return data.As<network::DataElementFile>();
   }
 
   static bool Read(network::mojom::DataElementDataView data,
diff --git a/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/services/network/public/cpp/url_request_mojom_traits_unittest.cc
index f44e8d9..78a064b 100644
--- a/services/network/public/cpp/url_request_mojom_traits_unittest.cc
+++ b/services/network/public/cpp/url_request_mojom_traits_unittest.cc
@@ -6,6 +6,7 @@
 
 #include "base/optional.h"
 #include "base/test/gtest_util.h"
+#include "base/test/task_environment.h"
 #include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
 #include "mojo/public/cpp/test_support/test_utils.h"
 #include "net/base/isolation_info.h"
@@ -113,5 +114,93 @@
   EXPECT_TRUE(original.EqualsForTesting(copied));
 }
 
+class DataElementDeserializationTest : public testing::Test {
+ protected:
+  base::test::TaskEnvironment task_environment_;
+};
+
+TEST_F(DataElementDeserializationTest, DataPipe) {
+  mojo::PendingRemote<mojom::DataPipeGetter> pending_remote;
+  auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
+  DataElement src{DataElementDataPipe(std::move(pending_remote))};
+
+  DataElement dest;
+  ASSERT_TRUE(
+      mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+  ASSERT_EQ(dest.type(), network::DataElement::Tag::kDataPipe);
+
+  mojo::Remote<mojom::DataPipeGetter> remote(
+      dest.As<DataElementDataPipe>().ReleaseDataPipeGetter());
+
+  // Make sure that `remote` and `pending_receiver` is connected to each other.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(remote.is_bound());
+  EXPECT_TRUE(remote.is_connected());
+
+  pending_receiver.reset();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(remote.is_bound());
+  EXPECT_FALSE(remote.is_connected());
+}
+
+TEST_F(DataElementDeserializationTest, ChunkedDataPipe) {
+  mojo::PendingRemote<mojom::ChunkedDataPipeGetter> pending_remote;
+  auto pending_receiver = pending_remote.InitWithNewPipeAndPassReceiver();
+  DataElement src(DataElementChunkedDataPipe(
+      std::move(pending_remote),
+      DataElementChunkedDataPipe::ReadOnlyOnce(true)));
+  DataElement dest;
+  ASSERT_TRUE(
+      mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+  ASSERT_EQ(dest.type(), network::DataElement::Tag::kChunkedDataPipe);
+  EXPECT_TRUE(dest.As<DataElementChunkedDataPipe>().read_only_once());
+  mojo::Remote<mojom::ChunkedDataPipeGetter> remote(
+      dest.As<DataElementChunkedDataPipe>().ReleaseChunkedDataPipeGetter());
+
+  // Make sure that `remote` and `pending_receiver` is connected to each other.
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(remote.is_bound());
+  EXPECT_TRUE(remote.is_connected());
+
+  pending_receiver.reset();
+  base::RunLoop().RunUntilIdle();
+
+  EXPECT_TRUE(remote.is_bound());
+  EXPECT_FALSE(remote.is_connected());
+}
+
+TEST_F(DataElementDeserializationTest, Bytes) {
+  const std::vector<uint8_t> kData = {8, 1, 9};
+  DataElement src{DataElementBytes(kData)};
+  DataElement dest;
+  ASSERT_TRUE(
+      mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+  ASSERT_EQ(mojom::DataElementDataView::Tag::kBytes, dest.type());
+  EXPECT_EQ(kData, dest.As<DataElementBytes>().bytes());
+}
+
+TEST_F(DataElementDeserializationTest, File) {
+  const base::FilePath kPath = base::FilePath::FromUTF8Unsafe("foobar");
+  DataElement src(DataElementFile(
+      kPath, /*offset=*/3, /*length=*/8,
+      base::Time::UnixEpoch() + base::TimeDelta::FromMinutes(2)));
+  DataElement dest;
+  ASSERT_TRUE(
+      mojo::test::SerializeAndDeserialize<mojom::DataElement>(src, dest));
+  ASSERT_EQ(mojom::DataElementDataView::Tag::kFile, dest.type());
+
+  const auto& src_file = src.As<DataElementFile>();
+  const auto& dest_file = dest.As<DataElementFile>();
+
+  EXPECT_EQ(src_file.path(), dest_file.path());
+  EXPECT_EQ(src_file.offset(), dest_file.offset());
+  EXPECT_EQ(src_file.length(), dest_file.length());
+  EXPECT_EQ(src_file.expected_modification_time(),
+            dest_file.expected_modification_time());
+}
+
 }  // namespace
 }  // namespace network
diff --git a/services/network/public/mojom/BUILD.gn b/services/network/public/mojom/BUILD.gn
index 02fb8a0..e51b87b 100644
--- a/services/network/public/mojom/BUILD.gn
+++ b/services/network/public/mojom/BUILD.gn
@@ -607,6 +607,26 @@
           cpp = "::net::RequestPriority"
         },
         {
+          mojom = "network.mojom.DataElementBytes"
+          cpp = "::network::DataElementBytes"
+          move_only = true
+        },
+        {
+          mojom = "network.mojom.DataElementDataPipe"
+          cpp = "::network::DataElementDataPipe"
+          move_only = true
+        },
+        {
+          mojom = "network.mojom.DataElementChunkedDataPipe"
+          cpp = "::network::DataElementChunkedDataPipe"
+          move_only = true
+        },
+        {
+          mojom = "network.mojom.DataElementFile"
+          cpp = "::network::DataElementFile"
+          move_only = true
+        },
+        {
           mojom = "network.mojom.DataElement"
           cpp = "::network::DataElement"
           move_only = true
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
index fc39ed2..294b044 100644
--- a/services/network/public/mojom/network_context.mojom
+++ b/services/network/public/mojom/network_context.mojom
@@ -945,6 +945,10 @@
   // A null |filter| indicates that all Trust Tokens data should be cleared.
   ClearTrustTokenData(ClearDataFilter? filter) => ();
 
+  // Returns the number of signed-but-not-spent Trust Tokens.
+  GetStoredTrustTokenCounts()
+      => (array<StoredTrustTokensForIssuer> tokens);
+
   // Clears network objects with implicit URL history information. Data related
   // to events that happened prior to |start_time| and after |end_time| may be
   // retained. Only applies to network objects without more specific methods
diff --git a/services/network/public/mojom/trust_tokens.mojom b/services/network/public/mojom/trust_tokens.mojom
index 2928c095..9e98ddf 100644
--- a/services/network/public/mojom/trust_tokens.mojom
+++ b/services/network/public/mojom/trust_tokens.mojom
@@ -279,3 +279,10 @@
   // In case of TrustTokenOperationType::kIssuance.
   int32 issued_token_count = 0;
 };
+
+// Struct StoredTrustTokensForIssuer is used by DevTools to inspect
+// the current state of the Trust Token store.
+struct StoredTrustTokensForIssuer {
+  url.mojom.Origin issuer;
+  int32 count;
+};
diff --git a/services/network/public/mojom/url_loader.mojom b/services/network/public/mojom/url_loader.mojom
index 4d6a1ecb..d9ef64d 100644
--- a/services/network/public/mojom/url_loader.mojom
+++ b/services/network/public/mojom/url_loader.mojom
@@ -55,20 +55,6 @@
   kNoReferrer
 };
 
-// Used for represents the type of the internal contents of
-// network::DataElement.
-enum DataElementType {
-  kUnknown = -1,
-
-  kDataPipe,
-  kChunkedDataPipe,
-  kReadOnceStream,
-  kBytes,
-
-  // TODO(https://crbug.com/1132362):  Remove this.
-  kFile,
-};
-
 // Options that may only be set on URLRequests passed to a URLLoaderFactory
 // created with |is_trusted| set to true.
 struct TrustedUrlRequestParams {
@@ -418,7 +404,8 @@
 // URLRequestBody represents body (i.e. upload data) of a HTTP request.
 // Typemapped to network::ResourceRequestBody
 struct URLRequestBody {
-  // Store upload bodies
+  // The body contents. DataElementChunkedDataPipe can be used in `elements`
+  // only if `elements` consists of one element.
   array<DataElement> elements;
 
   // Identifies a particular upload instance, which is used by the cache to
@@ -434,26 +421,42 @@
   bool allow_http1_for_streaming_upload;
 };
 
-// Represents part of an upload body. This could be either one of bytes, file or
-// a data pipe.
-// Typemapped to network::DataElement
-struct DataElement {
-  DataElementType type;
+// Represents part of an upload body consisting of bytes.
+struct DataElementBytes {
+  mojo_base.mojom.BigBuffer data;
+};
 
-  // For kBytes.
-  mojo_base.mojom.BigBuffer buf;
-  // For kFile
+// Represents part of an upload body consisting of (part of) a file.
+struct DataElementFile {
   mojo_base.mojom.FilePath path;
-  // For kDataPipe
-  pending_remote<network.mojom.DataPipeGetter>? data_pipe_getter;
-  // For kChunkedDataPipe
-  pending_remote<network.mojom.ChunkedDataPipeGetter>? chunked_data_pipe_getter;
-
   uint64 offset;
   uint64 length;
   mojo_base.mojom.Time expected_modification_time;
 };
 
+// Represents part of an upload body consisting of a data pipe with a known
+// size.
+struct DataElementDataPipe {
+  pending_remote<network.mojom.DataPipeGetter> data_pipe_getter;
+};
+
+// Represents part of an upload body consisting of a data pipe without a known
+// size.
+struct DataElementChunkedDataPipe {
+  pending_remote<network.mojom.ChunkedDataPipeGetter> data_pipe_getter;
+  // When true, a data pipe can be gotten from `chunked_data_pipe_getter` only
+  // once.
+  bool read_only_once;
+};
+
+// Represents part of an upload body.
+union DataElement {
+  DataElementBytes bytes;
+  DataElementFile file;
+  DataElementDataPipe data_pipe;
+  DataElementChunkedDataPipe chunked_data_pipe;
+};
+
 // URLLoader is an interface for performing a single request to a URL.
 //
 // Destroying a URLLoader will cancel the associated request.
diff --git a/services/network/test/test_network_context.h b/services/network/test/test_network_context.h
index 9b6f5af..799165ed 100644
--- a/services/network/test/test_network_context.h
+++ b/services/network/test/test_network_context.h
@@ -64,6 +64,8 @@
   void GetHasTrustTokensAnswerer(
       mojo::PendingReceiver<mojom::HasTrustTokensAnswerer> receiver,
       const url::Origin& top_frame_origin) override {}
+  void GetStoredTrustTokenCounts(
+      GetStoredTrustTokenCountsCallback callback) override {}
   void ClearNetworkingHistoryBetween(
       base::Time start_time,
       base::Time end_time,
diff --git a/services/network/test/test_utils.cc b/services/network/test/test_utils.cc
index a25eef121..a5b6c087 100644
--- a/services/network/test/test_utils.cc
+++ b/services/network/test/test_utils.cc
@@ -19,8 +19,8 @@
 
   CHECK_EQ(1u, body->elements()->size());
   const auto& element = body->elements()->at(0);
-  CHECK_EQ(mojom::DataElementType::kBytes, element.type());
-  return std::string(element.bytes(), element.length());
+  CHECK_EQ(mojom::DataElementDataView::Tag::kBytes, element.type());
+  return std::string(element.As<DataElementBytes>().AsStringPiece());
 }
 
 mojom::URLResponseHeadPtr CreateURLResponseHead(net::HttpStatusCode http_status,
diff --git a/services/network/trust_tokens/in_memory_trust_token_persister.cc b/services/network/trust_tokens/in_memory_trust_token_persister.cc
index c220f0b..3c056d5 100644
--- a/services/network/trust_tokens/in_memory_trust_token_persister.cc
+++ b/services/network/trust_tokens/in_memory_trust_token_persister.cc
@@ -80,4 +80,13 @@
   return deleted_any_data;
 }
 
+base::flat_map<SuitableTrustTokenOrigin, int>
+InMemoryTrustTokenPersister::GetStoredTrustTokenCounts() {
+  base::flat_map<SuitableTrustTokenOrigin, int> result;
+  for (const auto& kv : issuer_configs_) {
+    result.emplace(kv.first, kv.second->tokens_size());
+  }
+  return result;
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/in_memory_trust_token_persister.h b/services/network/trust_tokens/in_memory_trust_token_persister.h
index 30203d9..400c1ed 100644
--- a/services/network/trust_tokens/in_memory_trust_token_persister.h
+++ b/services/network/trust_tokens/in_memory_trust_token_persister.h
@@ -49,6 +49,9 @@
       base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher)
       override;
 
+  base::flat_map<SuitableTrustTokenOrigin, int> GetStoredTrustTokenCounts()
+      override;
+
  private:
   std::map<SuitableTrustTokenOrigin, std::unique_ptr<TrustTokenToplevelConfig>>
       toplevel_configs_;
diff --git a/services/network/trust_tokens/sqlite_trust_token_persister.cc b/services/network/trust_tokens/sqlite_trust_token_persister.cc
index f759397..e10844c 100644
--- a/services/network/trust_tokens/sqlite_trust_token_persister.cc
+++ b/services/network/trust_tokens/sqlite_trust_token_persister.cc
@@ -8,9 +8,11 @@
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/memory/scoped_refptr.h"
+#include "base/optional.h"
 #include "base/sequenced_task_runner.h"
 #include "base/strings/string_split.h"
 #include "components/sqlite_proto/key_value_data.h"
+#include "services/network/public/mojom/trust_tokens.mojom.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
 #include "services/network/trust_tokens/trust_token_database_owner.h"
 #include "url/gurl.h"
@@ -236,4 +238,22 @@
   return any_data_was_deleted;
 }
 
+base::flat_map<SuitableTrustTokenOrigin, int>
+SQLiteTrustTokenPersister::GetStoredTrustTokenCounts() {
+  base::flat_map<SuitableTrustTokenOrigin, int> result;
+  sqlite_proto::KeyValueData<TrustTokenIssuerConfig>* data =
+      database_owner_->IssuerData();
+
+  for (const auto& kv : data->GetAllCached()) {
+    base::Optional<SuitableTrustTokenOrigin> origin =
+        SuitableTrustTokenOrigin::Create(GURL(kv.first));
+    // The Create call can fail when the SQLite data was corrupted on the disk.
+    if (origin) {
+      result.emplace(std::move(*origin), kv.second.tokens_size());
+    }
+  }
+
+  return result;
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/sqlite_trust_token_persister.h b/services/network/trust_tokens/sqlite_trust_token_persister.h
index 2081479..eab4517 100644
--- a/services/network/trust_tokens/sqlite_trust_token_persister.h
+++ b/services/network/trust_tokens/sqlite_trust_token_persister.h
@@ -83,6 +83,9 @@
       base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)> matcher)
       override;
 
+  base::flat_map<SuitableTrustTokenOrigin, int> GetStoredTrustTokenCounts()
+      override;
+
  private:
   // Manages the underlying database.
   std::unique_ptr<TrustTokenDatabaseOwner> database_owner_;
diff --git a/services/network/trust_tokens/trust_token_persister.h b/services/network/trust_tokens/trust_token_persister.h
index 1109ff5..7494b85 100644
--- a/services/network/trust_tokens/trust_token_persister.h
+++ b/services/network/trust_tokens/trust_token_persister.h
@@ -8,6 +8,7 @@
 #include <memory>
 
 #include "base/callback_forward.h"
+#include "base/containers/flat_map.h"
 #include "services/network/trust_tokens/suitable_trust_token_origin.h"
 
 namespace network {
@@ -52,6 +53,9 @@
   virtual bool DeleteForOrigins(
       base::RepeatingCallback<bool(const SuitableTrustTokenOrigin&)>
           matcher) = 0;
+
+  virtual base::flat_map<SuitableTrustTokenOrigin, int>
+  GetStoredTrustTokenCounts() = 0;
 };
 
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_persister_unittest.cc b/services/network/trust_tokens/trust_token_persister_unittest.cc
index a13ae55..b5ea873e 100644
--- a/services/network/trust_tokens/trust_token_persister_unittest.cc
+++ b/services/network/trust_tokens/trust_token_persister_unittest.cc
@@ -11,6 +11,7 @@
 #include "base/test/bind.h"
 #include "base/test/task_environment.h"
 #include "base/threading/thread_task_runner_handle.h"
+#include "services/network/public/mojom/trust_tokens.mojom.h"
 #include "services/network/trust_tokens/in_memory_trust_token_persister.h"
 #include "services/network/trust_tokens/proto/public.pb.h"
 #include "services/network/trust_tokens/proto/storage.pb.h"
@@ -343,4 +344,38 @@
   env.RunUntilIdle();
 }
 
+TYPED_TEST(TrustTokenPersisterTest, RetrievesAvailableTrustTokens) {
+  base::test::TaskEnvironment env;
+  std::unique_ptr<TrustTokenPersister> persister = TypeParam::Create();
+  env.RunUntilIdle();  // Give implementations with asynchronous initialization
+                       // time to initialize.
+
+  auto result = persister->GetStoredTrustTokenCounts();
+  EXPECT_EQ(result.size(), 0ul);
+
+  TrustTokenIssuerConfig config;
+  TrustToken my_token;
+  my_token.set_body("token token token");
+  *config.add_tokens() = my_token;
+
+  auto config_to_store = std::make_unique<TrustTokenIssuerConfig>(config);
+  auto origin = *SuitableTrustTokenOrigin::Create(GURL("https://a.com/"));
+  persister->SetIssuerConfig(origin, std::move(config_to_store));
+
+  env.RunUntilIdle();  // Give implementations with asynchronous write
+                       // operations time to complete the operation.
+
+  result = persister->GetStoredTrustTokenCounts();
+
+  EXPECT_EQ(result.size(), 1ul);
+  EXPECT_EQ(result.begin()->first, origin);
+  EXPECT_EQ(result.begin()->second, 1);
+
+  // Some implementations of TrustTokenPersister may release resources
+  // asynchronously at destruction time; manually free the persister and allow
+  // this asynchronous release to occur, if any.
+  persister.reset();
+  env.RunUntilIdle();
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_store.cc b/services/network/trust_tokens/trust_token_store.cc
index 615cb2e..792c37f 100644
--- a/services/network/trust_tokens/trust_token_store.cc
+++ b/services/network/trust_tokens/trust_token_store.cc
@@ -311,4 +311,9 @@
   return persister_->DeleteForOrigins(std::move(matcher));
 }
 
+base::flat_map<SuitableTrustTokenOrigin, int>
+TrustTokenStore::GetStoredTrustTokenCounts() {
+  return persister_->GetStoredTrustTokenCounts();
+}
+
 }  // namespace network
diff --git a/services/network/trust_tokens/trust_token_store.h b/services/network/trust_tokens/trust_token_store.h
index 407c135..c6e0f321 100644
--- a/services/network/trust_tokens/trust_token_store.h
+++ b/services/network/trust_tokens/trust_token_store.h
@@ -153,6 +153,10 @@
   WARN_UNUSED_RESULT virtual int CountTokens(
       const SuitableTrustTokenOrigin& issuer);
 
+  // Returns the number of stored tokens per issuer.
+  WARN_UNUSED_RESULT virtual base::flat_map<SuitableTrustTokenOrigin, int>
+  GetStoredTrustTokenCounts();
+
   // Returns all signed tokens from |issuer| signed by keys matching
   // the given predicate.
   WARN_UNUSED_RESULT virtual std::vector<TrustToken> RetrieveMatchingTokens(
diff --git a/services/network/trust_tokens/trust_token_store_unittest.cc b/services/network/trust_tokens/trust_token_store_unittest.cc
index 0f698a7..00a59bd 100644
--- a/services/network/trust_tokens/trust_token_store_unittest.cc
+++ b/services/network/trust_tokens/trust_token_store_unittest.cc
@@ -284,6 +284,32 @@
   EXPECT_EQ(my_store->CountTokens(issuer), 3);
 }
 
+TEST(TrustTokenStore, GetsAllStoredTokens) {
+  auto my_store = TrustTokenStore::CreateForTesting(
+      std::make_unique<InMemoryTrustTokenPersister>());
+
+  // A freshly initialized store should be storing zero tokens.
+  EXPECT_TRUE(my_store->GetStoredTrustTokenCounts().empty());
+
+  // Add a token; the count should increase.
+  SuitableTrustTokenOrigin issuer_a =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer-a.com"));
+  my_store->AddTokens(issuer_a, std::vector<std::string>(1),
+                      /*issuing_key=*/"");
+  auto result = my_store->GetStoredTrustTokenCounts();
+  EXPECT_TRUE(result.contains(issuer_a));
+  EXPECT_EQ(result.find(issuer_a)->second, 1);
+
+  // Add two tokens for a different issuer.
+  SuitableTrustTokenOrigin issuer_b =
+      *SuitableTrustTokenOrigin::Create(GURL("https://issuer-b.com"));
+  my_store->AddTokens(issuer_b, std::vector<std::string>(2),
+                      /*issuing_key=*/"");
+  result = my_store->GetStoredTrustTokenCounts();
+  EXPECT_TRUE(result.contains(issuer_b));
+  EXPECT_EQ(result.find(issuer_b)->second, 2);
+}
+
 TEST(TrustTokenStore, PrunesDataAssociatedWithRemovedKeyCommitments) {
   // Test that providing PruneStaleIssuerState a set of key commitments
   // correctly evicts all tokens except those associated with keys in the
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
index ad66e31..c02cabc 100644
--- a/services/network/url_loader.cc
+++ b/services/network/url_loader.cc
@@ -155,11 +155,10 @@
 class BytesElementReader : public net::UploadBytesElementReader {
  public:
   BytesElementReader(ResourceRequestBody* resource_request_body,
-                     const DataElement& element)
-      : net::UploadBytesElementReader(element.bytes(), element.length()),
-        resource_request_body_(resource_request_body) {
-    DCHECK_EQ(network::mojom::DataElementType::kBytes, element.type());
-  }
+                     const DataElementBytes& element)
+      : net::UploadBytesElementReader(element.AsStringPiece().data(),
+                                      element.AsStringPiece().size()),
+        resource_request_body_(resource_request_body) {}
 
   ~BytesElementReader() override {}
 
@@ -177,7 +176,7 @@
  public:
   FileElementReader(ResourceRequestBody* resource_request_body,
                     base::TaskRunner* task_runner,
-                    const DataElement& element,
+                    const DataElementFile& element,
                     base::File&& file)
       : net::UploadFileElementReader(task_runner,
                                      std::move(file),
@@ -185,9 +184,7 @@
                                      element.offset(),
                                      element.length(),
                                      element.expected_modification_time()),
-        resource_request_body_(resource_request_body) {
-    DCHECK_EQ(network::mojom::DataElementType::kFile, element.type());
-  }
+        resource_request_body_(resource_request_body) {}
 
   ~FileElementReader() override {}
 
@@ -203,16 +200,16 @@
     base::SequencedTaskRunner* file_task_runner) {
   // In the case of a chunked upload, there will just be one element.
   if (body->elements()->size() == 1) {
-    network::mojom::DataElementType type = body->elements()->begin()->type();
-    if (type == network::mojom::DataElementType::kChunkedDataPipe ||
-        type == network::mojom::DataElementType::kReadOnceStream) {
+    if (body->elements()->begin()->type() ==
+        network::mojom::DataElementDataView::Tag::kChunkedDataPipe) {
+      auto& element =
+          body->elements_mutable()->at(0).As<DataElementChunkedDataPipe>();
       auto upload_data_stream =
           std::make_unique<ChunkedDataPipeUploadDataStream>(
-              body, body->elements_mutable()
-                        ->begin()
-                        ->ReleaseChunkedDataPipeGetter());
-      if (type == network::mojom::DataElementType::kReadOnceStream)
+              body, element.ReleaseChunkedDataPipeGetter());
+      if (element.read_only_once()) {
         upload_data_stream->EnableCache();
+      }
       return upload_data_stream;
     }
   }
@@ -221,30 +218,28 @@
   std::vector<std::unique_ptr<net::UploadElementReader>> element_readers;
   for (const auto& element : *body->elements()) {
     switch (element.type()) {
-      case network::mojom::DataElementType::kBytes:
-        element_readers.push_back(
-            std::make_unique<BytesElementReader>(body, element));
+      case network::mojom::DataElementDataView::Tag::kBytes:
+        element_readers.push_back(std::make_unique<BytesElementReader>(
+            body, element.As<DataElementBytes>()));
         break;
-      case network::mojom::DataElementType::kFile:
+      case network::mojom::DataElementDataView::Tag::kFile:
         DCHECK(opened_file != opened_files.end());
         element_readers.push_back(std::make_unique<FileElementReader>(
-            body, file_task_runner, element, std::move(*opened_file++)));
+            body, file_task_runner, element.As<network::DataElementFile>(),
+            std::move(*opened_file++)));
         break;
-      case network::mojom::DataElementType::kDataPipe: {
+      case network::mojom::DataElementDataView::Tag::kDataPipe: {
         element_readers.push_back(std::make_unique<DataPipeElementReader>(
-            body, element.CloneDataPipeGetter()));
+            body,
+            element.As<network::DataElementDataPipe>().CloneDataPipeGetter()));
         break;
       }
-      case network::mojom::DataElementType::kChunkedDataPipe:
-      case network::mojom::DataElementType::kReadOnceStream: {
+      case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: {
         // This shouldn't happen, as the traits logic should ensure that if
         // there's a chunked pipe, there's one and only one element.
         NOTREACHED();
         break;
       }
-      case network::mojom::DataElementType::kUnknown:
-        NOTREACHED();
-        break;
     }
   }
   DCHECK(opened_file == opened_files.end());
@@ -652,25 +647,6 @@
 
   // Resolve elements from request_body and prepare upload data.
   if (request.request_body.get()) {
-    const auto& elements = *request.request_body->elements();
-    // TODO(crbug.com/1156550): Move this logic to the deserialization part.
-    if (elements.size() == 1 &&
-        (elements[0].type() == mojom::DataElementType::kChunkedDataPipe ||
-         elements[0].type() == mojom::DataElementType::kReadOnceStream)) {
-      const bool chunked_data_pipe_getter_is_valid =
-          elements[0].chunked_data_pipe_getter().is_valid();
-      UMA_HISTOGRAM_BOOLEAN(
-          "NetworkService.StreamingUploadDataPipeGetterValidity",
-          chunked_data_pipe_getter_is_valid);
-      if (!chunked_data_pipe_getter_is_valid) {
-        base::SequencedTaskRunnerHandle::Get()->PostTask(
-            FROM_HERE,
-            base::BindOnce(&URLLoader::NotifyCompleted, base::Unretained(this),
-                           net::ERR_INVALID_ARGUMENT));
-        return;
-      }
-    }
-
     OpenFilesForUpload(request);
     return;
   }
@@ -783,8 +759,9 @@
 void URLLoader::OpenFilesForUpload(const ResourceRequest& request) {
   std::vector<base::FilePath> paths;
   for (const auto& element : *request.request_body.get()->elements()) {
-    if (element.type() == mojom::DataElementType::kFile)
-      paths.push_back(element.path());
+    if (element.type() == mojom::DataElementDataView::Tag::kFile) {
+      paths.push_back(element.As<network::DataElementFile>().path());
+    }
   }
   if (paths.empty()) {
     SetUpUpload(request, net::OK, std::vector<base::File>());
@@ -1181,7 +1158,9 @@
   const std::vector<DataElement>* elements = request_body->elements();
   if (elements->size() != 1u)
     return false;
-  return elements->front().type() == mojom::DataElementType::kReadOnceStream;
+  const auto& element = elements->front();
+  return element.type() == mojom::DataElementDataView::Tag::kChunkedDataPipe &&
+         element.As<network::DataElementChunkedDataPipe>().read_only_once();
 }
 
 void URLLoader::OnAuthRequired(net::URLRequest* url_request,
diff --git a/services/network/url_loader_unittest.cc b/services/network/url_loader_unittest.cc
index da9ed8f..bab791d 100644
--- a/services/network/url_loader_unittest.cc
+++ b/services/network/url_loader_unittest.cc
@@ -2264,7 +2264,8 @@
       CreateResourceRequest("POST", test_server()->GetURL("/echo"));
   request.request_body = base::MakeRefCounted<ResourceRequestBody>();
   request.request_body->SetToChunkedDataPipe(
-      data_pipe_getter.GetDataPipeGetterRemote());
+      data_pipe_getter.GetDataPipeGetterRemote(),
+      ResourceRequestBody::ReadOnlyOnce(false));
 
   base::RunLoop delete_run_loop;
   mojo::Remote<mojom::URLLoader> loader;
@@ -2308,8 +2309,9 @@
   ResourceRequest request =
       CreateResourceRequest("POST", test_server()->GetURL("/echo"));
   request.request_body = base::MakeRefCounted<ResourceRequestBody>();
-  request.request_body->SetToReadOnceStream(
-      data_pipe_getter.GetDataPipeGetterRemote());
+  request.request_body->SetToChunkedDataPipe(
+      data_pipe_getter.GetDataPipeGetterRemote(),
+      ResourceRequestBody::ReadOnlyOnce(true));
 
   base::HistogramTester tester;
   std::string histogram_allowh1("Net.Fetch.UploadStreamingProtocolAllowH1");
diff --git a/services/video_capture/README.md b/services/video_capture/README.md
new file mode 100644
index 0000000..3a58ab9
--- /dev/null
+++ b/services/video_capture/README.md
@@ -0,0 +1,4 @@
+`services/video_capture` facilitates access to native video capture devices such as webcams and built-in cameras.
+
+See the [service design
+document](https://docs.google.com/document/d/1Qw7rw1AJy0QHXjha36jZNiEuxsxWslJ_X-zpOhijvI8) for more detailed information.
diff --git a/testing/buildbot/chromium.clang.json b/testing/buildbot/chromium.clang.json
index c908836..a696419 100644
--- a/testing/buildbot/chromium.clang.json
+++ b/testing/buildbot/chromium.clang.json
@@ -30754,8 +30754,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30772,8 +30771,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30793,8 +30791,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30812,8 +30809,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30830,8 +30826,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30848,8 +30843,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30866,8 +30860,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30884,8 +30877,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30902,8 +30894,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30920,8 +30911,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30938,8 +30928,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30957,8 +30946,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30975,8 +30963,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -30993,8 +30980,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31011,8 +30997,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31029,8 +31014,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -31051,8 +31035,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31069,8 +31052,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31087,8 +31069,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31105,8 +31086,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31123,8 +31103,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31141,8 +31120,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31159,8 +31137,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31177,8 +31154,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31195,8 +31171,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31213,8 +31188,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31231,8 +31205,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -31250,8 +31223,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31268,8 +31240,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31286,8 +31257,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31304,8 +31274,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31322,8 +31291,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31340,8 +31308,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31358,8 +31325,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31376,8 +31342,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31394,8 +31359,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31412,8 +31376,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31430,8 +31393,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31448,8 +31410,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31466,8 +31427,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31484,8 +31444,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31502,8 +31461,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31520,8 +31478,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31538,8 +31495,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31556,8 +31512,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31574,8 +31529,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31592,8 +31546,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31610,8 +31563,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31628,8 +31580,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31646,8 +31597,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31664,8 +31614,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31683,8 +31632,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "integrity": "high",
-              "os": "Windows-10-18363"
+              "integrity": "high"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31701,8 +31649,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com",
@@ -31720,8 +31667,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31738,8 +31684,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31756,8 +31701,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31774,8 +31718,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31792,8 +31735,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31810,8 +31752,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31828,8 +31769,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31846,8 +31786,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31864,8 +31803,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31882,8 +31820,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31900,8 +31837,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31918,8 +31854,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31936,8 +31871,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31954,8 +31888,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31972,8 +31905,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -31990,8 +31922,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32008,8 +31939,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32026,8 +31956,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32044,8 +31973,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32063,8 +31991,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "integrity": "high",
-              "os": "Windows-10-18363"
+              "integrity": "high"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32081,8 +32008,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32099,8 +32025,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32117,8 +32042,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32135,8 +32059,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32154,8 +32077,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "integrity": "high",
-              "os": "Windows-10-18363"
+              "integrity": "high"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32172,8 +32094,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32190,8 +32111,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32208,8 +32128,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32226,8 +32145,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32244,8 +32162,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32262,8 +32179,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32280,8 +32196,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32298,8 +32213,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32316,8 +32230,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32334,8 +32247,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32352,8 +32264,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32370,8 +32281,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32388,8 +32298,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32406,8 +32315,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32424,8 +32332,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32442,8 +32349,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32460,8 +32366,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32478,8 +32383,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32496,8 +32400,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32514,8 +32417,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32532,8 +32434,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32550,8 +32451,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32573,8 +32473,7 @@
           "dimension_sets": [
             {
               "cpu": "x86-64",
-              "integrity": "high",
-              "os": "Windows-10-18363"
+              "integrity": "high"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
@@ -32593,8 +32492,7 @@
           "can_use_on_swarming_builders": true,
           "dimension_sets": [
             {
-              "cpu": "x86-64",
-              "os": "Windows-10-18363"
+              "cpu": "x86-64"
             }
           ],
           "service_account": "chrome-tester@chops-service-accounts.iam.gserviceaccount.com"
diff --git a/testing/buildbot/waterfalls.pyl b/testing/buildbot/waterfalls.pyl
index dfc93b04..3c708e1 100644
--- a/testing/buildbot/waterfalls.pyl
+++ b/testing/buildbot/waterfalls.pyl
@@ -1944,7 +1944,6 @@
       'ToTWin64': {
         'mixins': [
           'chrome-tester-service-account',
-          'win10',
           'x86-64',
         ],
         'test_suites': {
diff --git a/testing/scripts/run_wpt_tests.py b/testing/scripts/run_wpt_tests.py
index 9401c88..526912c 100755
--- a/testing/scripts/run_wpt_tests.py
+++ b/testing/scripts/run_wpt_tests.py
@@ -39,6 +39,8 @@
 DEFAULT_ISOLATED_SCRIPT_TEST_OUTPUT = "../../out/{}/results.json"
 MOJO_JS_PATH = "../../out/{}/gen/"
 
+TESTS_ROOT_DIR = "../../third_party/blink/web_tests/external/wpt"
+
 class WPTTestAdapter(wpt_common.BaseWptScriptAdapter):
 
     @property
@@ -50,7 +52,7 @@
 
         # Here we add all of the arguments required to run WPT tests on Chrome.
         rest_args.extend([
-            "../../third_party/blink/web_tests/external/wpt/wpt",
+            "../../third_party/blink/tools/blinkpy/third_party/wpt/wpt/wpt",
             "--venv=../../",
             "--skip-venv-setup",
             "run",
@@ -96,6 +98,7 @@
             # from multiprocessing.cpu_count()
             "--processes=" + self.options.child_processes,
             "--mojojs-path=" + MOJO_JS_PATH.format(self.options.target),
+            "--tests=" + TESTS_ROOT_DIR,
         ])
         return rest_args
 
diff --git a/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
index cdc06208..923f3787 100644
--- a/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/third_party/blink/common/fetch/fetch_api_request_body_mojom_traits.cc
@@ -22,27 +22,4 @@
   return true;
 }
 
-bool StructTraits<
-    blink::mojom::FetchAPIDataElementDataView,
-    network::DataElement>::Read(blink::mojom::FetchAPIDataElementDataView data,
-                                network::DataElement* out) {
-  if (!data.ReadPath(&out->path_) ||
-      !data.ReadExpectedModificationTime(&out->expected_modification_time_)) {
-    return false;
-  }
-
-  if (data.type() == network::mojom::DataElementType::kBytes) {
-    if (!data.ReadBuf(&out->buf_))
-      return false;
-  }
-  out->type_ = data.type();
-  out->data_pipe_getter_ = data.TakeDataPipeGetter<
-      mojo::PendingRemote<network::mojom::DataPipeGetter>>();
-  out->chunked_data_pipe_getter_ = data.TakeChunkedDataPipeGetter<
-      mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>>();
-  out->offset_ = data.offset();
-  out->length_ = data.length();
-  return true;
-}
-
 }  // namespace mojo
diff --git a/third_party/blink/common/page_state/page_state_serialization.cc b/third_party/blink/common/page_state/page_state_serialization.cc
index b7de54a..33f3bc9 100644
--- a/third_party/blink/common/page_state/page_state_serialization.cc
+++ b/third_party/blink/common/page_state/page_state_serialization.cc
@@ -61,8 +61,10 @@
     const std::vector<network::DataElement>& elements,
     std::vector<base::Optional<base::string16>>* referenced_files) {
   for (size_t i = 0; i < elements.size(); ++i) {
-    if (elements[i].type() == network::mojom::DataElementType::kFile)
-      referenced_files->emplace_back(elements[i].path().AsUTF16Unsafe());
+    if (elements[i].type() == network::DataElement::Tag::kFile) {
+      referenced_files->emplace_back(
+          elements[i].As<network::DataElementFile>().path().AsUTF16Unsafe());
+    }
   }
 }
 
@@ -391,17 +393,21 @@
   WriteAndValidateVectorSize(*request_body.elements(), obj);
   for (const auto& element : *request_body.elements()) {
     switch (element.type()) {
-      case network::mojom::DataElementType::kBytes:
+      case network::DataElement::Tag::kBytes: {
+        const auto& bytes = element.As<network::DataElementBytes>().bytes();
         WriteInteger(static_cast<int>(HTTPBodyElementType::kTypeData), obj);
-        WriteData(element.bytes(), static_cast<int>(element.length()), obj);
+        WriteData(bytes.data(), static_cast<int>(bytes.size()), obj);
         break;
-      case network::mojom::DataElementType::kFile:
+      }
+      case network::DataElement::Tag::kFile: {
+        const auto& file = element.As<network::DataElementFile>();
         WriteInteger(static_cast<int>(HTTPBodyElementType::kTypeFile), obj);
-        WriteString(element.path().AsUTF16Unsafe(), obj);
-        WriteInteger64(static_cast<int64_t>(element.offset()), obj);
-        WriteInteger64(static_cast<int64_t>(element.length()), obj);
-        WriteReal(element.expected_modification_time().ToDoubleT(), obj);
+        WriteString(file.path().AsUTF16Unsafe(), obj);
+        WriteInteger64(static_cast<int64_t>(file.offset()), obj);
+        WriteInteger64(static_cast<int64_t>(file.length()), obj);
+        WriteReal(file.expected_modification_time().ToDoubleT(), obj);
         break;
+      }
       default:
         NOTREACHED();
         continue;
@@ -663,25 +669,25 @@
   for (const auto& element : *request_body.elements()) {
     mojom::ElementPtr data_element = mojom::Element::New();
     switch (element.type()) {
-      case network::mojom::DataElementType::kBytes: {
-        data_element->set_bytes(std::vector<unsigned char>(
-            reinterpret_cast<const char*>(element.bytes()),
-            element.bytes() + element.length()));
+      case network::DataElement::Tag::kBytes: {
+        const auto& bytes = element.As<network::DataElementBytes>().bytes();
+        const char* data = reinterpret_cast<const char*>(bytes.data());
+        data_element->set_bytes(
+            std::vector<unsigned char>(data, data + bytes.size()));
         break;
       }
-      case network::mojom::DataElementType::kFile: {
+      case network::DataElement::Tag::kFile: {
+        const auto& element_file = element.As<network::DataElementFile>();
         mojom::FilePtr file = mojom::File::New(
-            element.path().AsUTF16Unsafe(), element.offset(), element.length(),
-            element.expected_modification_time());
+            element_file.path().AsUTF16Unsafe(), element_file.offset(),
+            element_file.length(), element_file.expected_modification_time());
         data_element->set_file(std::move(file));
         break;
       }
-      case network::mojom::DataElementType::kDataPipe:
+      case network::DataElement::Tag::kDataPipe:
         NOTIMPLEMENTED();
         break;
-      case network::mojom::DataElementType::kChunkedDataPipe:
-      case network::mojom::DataElementType::kReadOnceStream:
-      case network::mojom::DataElementType::kUnknown:
+      case network::DataElement::Tag::kChunkedDataPipe:
         NOTREACHED();
         continue;
     }
diff --git a/third_party/blink/common/page_state/page_state_serialization_unittest.cc b/third_party/blink/common/page_state/page_state_serialization_unittest.cc
index a9122e4..3b5427e 100644
--- a/third_party/blink/common/page_state/page_state_serialization_unittest.cc
+++ b/third_party/blink/common/page_state/page_state_serialization_unittest.cc
@@ -46,17 +46,24 @@
 template <>
 void ExpectEquality(const network::DataElement& expected,
                     const network::DataElement& actual) {
-  EXPECT_EQ(expected.type(), actual.type());
-  if (expected.type() == network::mojom::DataElementType::kBytes &&
-      actual.type() == network::mojom::DataElementType::kBytes) {
-    EXPECT_EQ(std::string(expected.bytes(), expected.length()),
-              std::string(actual.bytes(), actual.length()));
+  ASSERT_EQ(expected.type(), actual.type());
+  if (expected.type() == network::DataElement::Tag::kBytes) {
+    EXPECT_EQ(expected.As<network::DataElementBytes>().bytes(),
+              actual.As<network::DataElementBytes>().bytes());
+    return;
   }
-  EXPECT_EQ(expected.path(), actual.path());
-  EXPECT_EQ(expected.offset(), actual.offset());
-  EXPECT_EQ(expected.length(), actual.length());
-  EXPECT_EQ(expected.expected_modification_time(),
-            actual.expected_modification_time());
+  if (expected.type() != network::DataElement::Tag::kFile) {
+    ADD_FAILURE() << "Impossible to check equality.";
+    return;
+  }
+
+  const auto& expected_file = expected.As<network::DataElementFile>();
+  const auto& actual_file = actual.As<network::DataElementFile>();
+  EXPECT_EQ(expected_file.path(), actual_file.path());
+  EXPECT_EQ(expected_file.offset(), actual_file.offset());
+  EXPECT_EQ(expected_file.length(), actual_file.length());
+  EXPECT_EQ(expected_file.expected_modification_time(),
+            actual_file.expected_modification_time());
 }
 
 template <>
diff --git a/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
index 667e994..9950d48 100644
--- a/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
+++ b/third_party/blink/public/common/fetch/fetch_api_request_body_mojom_traits.h
@@ -47,48 +47,6 @@
                    scoped_refptr<network::ResourceRequestBody>* out);
 };
 
-template <>
-struct BLINK_COMMON_EXPORT
-    StructTraits<blink::mojom::FetchAPIDataElementDataView,
-                 network::DataElement> {
-  static const network::mojom::DataElementType& type(
-      const network::DataElement& element) {
-    return element.type_;
-  }
-  static const std::vector<uint8_t>& buf(const network::DataElement& element) {
-    return element.buf_;
-  }
-  static const base::FilePath& path(const network::DataElement& element) {
-    return element.path_;
-  }
-  static mojo::PendingRemote<network::mojom::DataPipeGetter> data_pipe_getter(
-      const network::DataElement& element) {
-    if (element.type_ != network::mojom::DataElementType::kDataPipe)
-      return mojo::NullRemote();
-    return element.CloneDataPipeGetter();
-  }
-  static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
-  chunked_data_pipe_getter(const network::DataElement& element) {
-    if (element.type_ != network::mojom::DataElementType::kReadOnceStream)
-      return mojo::NullRemote();
-    return const_cast<network::DataElement&>(element)
-        .ReleaseChunkedDataPipeGetter();
-  }
-  static uint64_t offset(const network::DataElement& element) {
-    return element.offset_;
-  }
-  static uint64_t length(const network::DataElement& element) {
-    return element.length_;
-  }
-  static const base::Time& expected_modification_time(
-      const network::DataElement& element) {
-    return element.expected_modification_time_;
-  }
-
-  static bool Read(blink::mojom::FetchAPIDataElementDataView data,
-                   network::DataElement* out);
-};
-
 }  // namespace mojo
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_COMMON_FETCH_FETCH_API_REQUEST_BODY_MOJOM_TRAITS_H_
diff --git a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
index 5f3396b..a0c0c40c 100644
--- a/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
+++ b/third_party/blink/public/mojom/fetch/fetch_api_request.mojom
@@ -8,7 +8,6 @@
 import "mojo/public/mojom/base/time.mojom";
 import "mojo/public/mojom/base/unguessable_token.mojom";
 import "services/network/public/mojom/chunked_data_pipe_getter.mojom";
-import "services/network/public/mojom/data_pipe_getter.mojom";
 import "services/network/public/mojom/fetch_api.mojom";
 import "services/network/public/mojom/url_loader.mojom";
 import "third_party/blink/public/mojom/blob/serialized_blob.mojom";
@@ -113,25 +112,6 @@
   map<string, string> headers;
 };
 
-// Represents part of an upload body. This could be either one of bytes, file or
-// a data pipe.
-struct FetchAPIDataElement {
-  // The type of the internal contents of network::DataElement.
-  network.mojom.DataElementType type;
-  // For kBytes.
-  array<uint8> buf;
-  // For kFile
-  mojo_base.mojom.FilePath path;
-  // For kDataPipe
-  pending_remote<network.mojom.DataPipeGetter>? data_pipe_getter;
-  // For kChunkedDataPipe
-  pending_remote<network.mojom.ChunkedDataPipeGetter>? chunked_data_pipe_getter;
-
-  uint64 offset;
-  uint64 length;
-  mojo_base.mojom.Time expected_modification_time;
-};
-
 // Struct representing a Body for a Request:
 // https://fetch.spec.whatwg.org/#body
 // This has the same members definition with network.mojom.URLRequestBody, which
@@ -142,8 +122,9 @@
 // scoped_refptr<network::ResourceRequestBody> but this is typemapped to
 // scoped_refptr<blink::EncodedFormData>.
 struct FetchAPIRequestBody {
-  // Store upload bodies
-  array<FetchAPIDataElement> elements;
+  // The body contents. DataElementChunkedDataPipe can be used in `elements`
+  // only if `elements` consists of one element.
+  array<network.mojom.DataElement> elements;
 
   // Identifies a particular upload instance, which is used by the cache to
   // formulate a cache key.
diff --git a/third_party/blink/renderer/core/css/style_engine_test.cc b/third_party/blink/renderer/core/css/style_engine_test.cc
index 0eaf436..26d2267 100644
--- a/third_party/blink/renderer/core/css/style_engine_test.cc
+++ b/third_party/blink/renderer/core/css/style_engine_test.cc
@@ -3732,16 +3732,19 @@
 
 namespace {
 
-void SetDependsOnContainerQueries(HTMLCollection& affected) {
-  for (Element* element : affected) {
-    if (const ComputedStyle* style = element->GetComputedStyle()) {
-      scoped_refptr<ComputedStyle> cloned_style = ComputedStyle::Clone(*style);
-      cloned_style->SetDependsOnContainerQueries(true);
-      element->SetComputedStyle(cloned_style);
-    }
+void SetDependsOnContainerQueries(Element& element) {
+  if (const ComputedStyle* style = element.GetComputedStyle()) {
+    scoped_refptr<ComputedStyle> cloned_style = ComputedStyle::Clone(*style);
+    cloned_style->SetDependsOnContainerQueries(true);
+    element.SetComputedStyle(cloned_style);
   }
 }
 
+void SetDependsOnContainerQueries(HTMLCollection& affected) {
+  for (Element* element : affected)
+    SetDependsOnContainerQueries(*element);
+}
+
 }  // namespace
 
 TEST_F(StyleEngineTest, UpdateStyleAndLayoutTreeForContainer) {
@@ -3850,6 +3853,39 @@
   EXPECT_EQ(7u, GetStyleEngine().StyleForElementCount() - start_count);
 }
 
+TEST_F(StyleEngineTest, PseudoElementContainerQueryRecalc) {
+  GetDocument().body()->setInnerHTML(R"HTML(
+    <style>
+      #container { contain: layout size }
+      #container::before { content: " " }
+      span::before { content: " " }
+    </style>
+    <div id="container">
+      <span id="span"></span>
+    </div>
+  )HTML");
+
+  UpdateAllLifecyclePhases();
+
+  auto* container = GetDocument().getElementById("container");
+  auto* span = GetDocument().getElementById("span");
+  ASSERT_TRUE(container);
+  ASSERT_TRUE(span);
+
+  auto* before = span->GetPseudoElement(kPseudoIdBefore);
+  ASSERT_TRUE(before);
+  SetDependsOnContainerQueries(*before);
+
+  before = container->GetPseudoElement(kPseudoIdBefore);
+  ASSERT_TRUE(before);
+  SetDependsOnContainerQueries(*before);
+
+  unsigned start_count = GetStyleEngine().StyleForElementCount();
+  GetStyleEngine().UpdateStyleAndLayoutTreeForContainer(*container);
+
+  EXPECT_EQ(2u, GetStyleEngine().StyleForElementCount() - start_count);
+}
+
 TEST_F(StyleEngineTest, MarkStyleDirtyFromContainerRecalc) {
   GetDocument().body()->setInnerHTML(R"HTML(
     <div id="container" style="contain: layout size">
diff --git a/third_party/blink/renderer/core/css/style_recalc.cc b/third_party/blink/renderer/core/css/style_recalc.cc
index 6f22ad2..082ba57 100644
--- a/third_party/blink/renderer/core/css/style_recalc.cc
+++ b/third_party/blink/renderer/core/css/style_recalc.cc
@@ -15,7 +15,8 @@
 }
 
 bool StyleRecalcChange::TraversePseudoElements(const Element& element) const {
-  return UpdatePseudoElements() || element.ChildNeedsStyleRecalc();
+  return UpdatePseudoElements() || RecalcContainerQueryDependent() ||
+         element.ChildNeedsStyleRecalc();
 }
 
 bool StyleRecalcChange::TraverseChild(const Node& node) const {
@@ -47,7 +48,12 @@
 
 bool StyleRecalcChange::ShouldUpdatePseudoElement(
     const PseudoElement& pseudo_element) const {
-  return UpdatePseudoElements() || pseudo_element.NeedsStyleRecalc();
+  if (UpdatePseudoElements())
+    return true;
+  if (pseudo_element.NeedsStyleRecalc())
+    return true;
+  return RecalcContainerQueryDependent() &&
+         pseudo_element.ComputedStyleRef().DependsOnContainerQueries();
 }
 
 bool StyleRecalcChange::RecalcContainerQueryDependentChildren(
diff --git a/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc b/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
index 47a6a6b..f6a1367 100644
--- a/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
+++ b/third_party/blink/renderer/core/editing/ime/cached_text_input_info.cc
@@ -108,16 +108,21 @@
     const EphemeralRange& range) const {
   if (range.IsNull())
     return PlainTextRange();
-  const unsigned start_offset = RangeLength(
-      EphemeralRange(Position(*container_, 0), range.StartPosition()));
+  const Position container_start = Position(*container_, 0);
+  // When selection is moved to another editable during IME composition,
+  // |range| may not in |container|. See http://crbug.com/1161562
+  if (container_start > range.StartPosition())
+    return PlainTextRange();
+  const unsigned start_offset =
+      RangeLength(EphemeralRange(container_start, range.StartPosition()));
   const unsigned end_offset =
-      range.IsCollapsed() ? start_offset
-                          : RangeLength(EphemeralRange(Position(*container_, 0),
-                                                       range.EndPosition()));
-  DCHECK_EQ(static_cast<unsigned>(TextIterator::RangeLength(
-                EphemeralRange(Position(*container_, 0), range.EndPosition()),
-                Behavior())),
-            end_offset);
+      range.IsCollapsed()
+          ? start_offset
+          : RangeLength(EphemeralRange(container_start, range.EndPosition()));
+  DCHECK_EQ(
+      static_cast<unsigned>(TextIterator::RangeLength(
+          EphemeralRange(container_start, range.EndPosition()), Behavior())),
+      end_offset);
   return PlainTextRange(start_offset, end_offset);
 }
 
diff --git a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
index 261f4b7..5bba416 100644
--- a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
+++ b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.cc
@@ -112,6 +112,14 @@
     return Result::kDone;
 
   if (pending_buffer_) {
+    // The UInt8Array has become detached due to, for example, the site
+    // transferring it away via postMessage().  Since we were in the middle
+    // of reading the array we must error out.
+    if (pending_buffer_->IsDetached()) {
+      SetErrored();
+      return Result::kError;
+    }
+
     DCHECK_LE(pending_offset_, pending_buffer_->length());
     *buffer = reinterpret_cast<const char*>(pending_buffer_->Data()) +
               pending_offset_;
@@ -141,6 +149,15 @@
 
 BytesConsumer::Result ReadableStreamBytesConsumer::EndRead(size_t read_size) {
   DCHECK(pending_buffer_);
+
+  // While the buffer size is immutable once constructed, the buffer can be
+  // detached if the site does something like transfer it away using
+  // postMessage().  Since we were in the middle of a read we must error out.
+  if (pending_buffer_->IsDetached()) {
+    SetErrored();
+    return Result::kError;
+  }
+
   DCHECK_LE(pending_offset_ + read_size, pending_buffer_->length());
   pending_offset_ += read_size;
   if (pending_offset_ >= pending_buffer_->length()) {
@@ -220,12 +237,18 @@
   if (state_ == PublicState::kClosed)
     return;
   DCHECK_EQ(state_, PublicState::kReadableOrWaiting);
-  state_ = PublicState::kErrored;
-  reader_ = nullptr;
   Client* client = client_;
-  ClearClient();
+  SetErrored();
   if (client)
     client->OnStateChange();
 }
 
+void ReadableStreamBytesConsumer::SetErrored() {
+  DCHECK_NE(state_, PublicState::kClosed);
+  DCHECK_NE(state_, PublicState::kErrored);
+  state_ = PublicState::kErrored;
+  ClearClient();
+  reader_ = nullptr;
+}
+
 }  // namespace blink
diff --git a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
index 860933e7..c33c32b 100644
--- a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
+++ b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer.h
@@ -47,6 +47,7 @@
   void OnRead(DOMUint8Array*);
   void OnReadDone();
   void OnRejected();
+  void SetErrored();
   void Notify();
 
   Member<ReadableStreamDefaultReader> reader_;
diff --git a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
index e309feee..5fe5edb9 100644
--- a/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
+++ b/third_party/blink/renderer/core/fetch/readable_stream_bytes_consumer_test.cc
@@ -239,6 +239,109 @@
   EXPECT_EQ(Result::kDone, consumer->BeginRead(&buffer, &available));
 }
 
+TEST(ReadableStreamBytesConsumerTest, TwoPhaseReadDetachedDuringRead) {
+  V8TestingScope scope;
+  ScriptState* script_state = scope.GetScriptState();
+
+  auto* underlying_source =
+      MakeGarbageCollected<TestUnderlyingSource>(script_state);
+  auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+      script_state, underlying_source, 0);
+
+  auto* chunk = DOMUint8Array::Create(4);
+  chunk->Data()[0] = 0x43;
+  chunk->Data()[1] = 0x44;
+  chunk->Data()[2] = 0x45;
+  chunk->Data()[3] = 0x46;
+  underlying_source->Enqueue(
+      ScriptValue(script_state->GetIsolate(), ToV8(chunk, script_state)));
+  underlying_source->Close();
+
+  Persistent<BytesConsumer> consumer =
+      MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
+  Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
+  consumer->SetClient(client);
+  Checkpoint checkpoint;
+
+  InSequence s;
+  EXPECT_CALL(checkpoint, Call(1));
+  EXPECT_CALL(checkpoint, Call(2));
+  EXPECT_CALL(checkpoint, Call(3));
+  EXPECT_CALL(*client, OnStateChange());
+  EXPECT_CALL(checkpoint, Call(4));
+
+  const char* buffer = nullptr;
+  size_t available = 0;
+  checkpoint.Call(1);
+  test::RunPendingTasks();
+  checkpoint.Call(2);
+  EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
+  checkpoint.Call(3);
+  test::RunPendingTasks();
+  checkpoint.Call(4);
+  EXPECT_EQ(Result::kOk, consumer->BeginRead(&buffer, &available));
+  ASSERT_EQ(4u, available);
+  EXPECT_EQ(0x43, buffer[0]);
+  EXPECT_EQ(0x44, buffer[1]);
+  EXPECT_EQ(0x45, buffer[2]);
+  EXPECT_EQ(0x46, buffer[3]);
+  chunk->DetachForTesting();
+  EXPECT_EQ(Result::kError, consumer->EndRead(4));
+  EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
+}
+
+TEST(ReadableStreamBytesConsumerTest, TwoPhaseReadDetachedBetweenReads) {
+  V8TestingScope scope;
+  ScriptState* script_state = scope.GetScriptState();
+
+  auto* underlying_source =
+      MakeGarbageCollected<TestUnderlyingSource>(script_state);
+  auto* stream = ReadableStream::CreateWithCountQueueingStrategy(
+      script_state, underlying_source, 0);
+
+  auto* chunk = DOMUint8Array::Create(4);
+  chunk->Data()[0] = 0x43;
+  chunk->Data()[1] = 0x44;
+  chunk->Data()[2] = 0x45;
+  chunk->Data()[3] = 0x46;
+  underlying_source->Enqueue(
+      ScriptValue(script_state->GetIsolate(), ToV8(chunk, script_state)));
+  underlying_source->Close();
+
+  Persistent<BytesConsumer> consumer =
+      MakeGarbageCollected<ReadableStreamBytesConsumer>(script_state, stream);
+  Persistent<MockClient> client = MakeGarbageCollected<MockClient>();
+  consumer->SetClient(client);
+  Checkpoint checkpoint;
+
+  InSequence s;
+  EXPECT_CALL(checkpoint, Call(1));
+  EXPECT_CALL(checkpoint, Call(2));
+  EXPECT_CALL(checkpoint, Call(3));
+  EXPECT_CALL(*client, OnStateChange());
+  EXPECT_CALL(checkpoint, Call(4));
+
+  const char* buffer = nullptr;
+  size_t available = 0;
+  checkpoint.Call(1);
+  test::RunPendingTasks();
+  checkpoint.Call(2);
+  EXPECT_EQ(Result::kShouldWait, consumer->BeginRead(&buffer, &available));
+  checkpoint.Call(3);
+  test::RunPendingTasks();
+  checkpoint.Call(4);
+  EXPECT_EQ(Result::kOk, consumer->BeginRead(&buffer, &available));
+  ASSERT_EQ(4u, available);
+  EXPECT_EQ(0x43, buffer[0]);
+  EXPECT_EQ(0x44, buffer[1]);
+  EXPECT_EQ(0x45, buffer[2]);
+  EXPECT_EQ(0x46, buffer[3]);
+  EXPECT_EQ(Result::kOk, consumer->EndRead(1));
+  chunk->DetachForTesting();
+  EXPECT_EQ(Result::kError, consumer->BeginRead(&buffer, &available));
+  EXPECT_EQ(PublicState::kErrored, consumer->GetPublicState());
+}
+
 TEST(ReadableStreamBytesConsumerTest, EnqueueUndefined) {
   V8TestingScope scope;
   ScriptState* script_state = scope.GetScriptState();
diff --git a/third_party/blink/renderer/core/style/data_equivalency.h b/third_party/blink/renderer/core/style/data_equivalency.h
index c5aa44e7..6cdd579 100644
--- a/third_party/blink/renderer/core/style/data_equivalency.h
+++ b/third_party/blink/renderer/core/style/data_equivalency.h
@@ -7,15 +7,11 @@
 
 #include <memory>
 #include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
 
 namespace blink {
 
 template <typename T>
-class Persistent;
-template <typename T>
-class Member;
-
-template <typename T>
 bool DataEquivalent(const T* a, const T* b) {
   if (a == b)
     return true;
diff --git a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
index 7012927..cbc031a 100644
--- a/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
+++ b/third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h
@@ -122,6 +122,10 @@
     ScriptWrappable::Trace(visitor);
   }
 
+  void DetachForTesting() { dom_array_buffer_->Detach(); }
+
+  bool IsDetached() const { return dom_array_buffer_->IsDetached(); }
+
  protected:
   DOMArrayBufferView(DOMArrayBufferBase* dom_array_buffer, size_t byte_offset)
       : raw_byte_offset_(byte_offset), dom_array_buffer_(dom_array_buffer) {
@@ -130,8 +134,6 @@
         static_cast<char*>(dom_array_buffer_->DataMaybeShared()) + byte_offset;
   }
 
-  bool IsDetached() const { return dom_array_buffer_->IsDetached(); }
-
  private:
   // The raw_* fields may be stale after Detach. Use getters instead.
   // This is the address of the ArrayBuffer's storage, plus the byte offset.
diff --git a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
index 27acf41..992ea1b 100644
--- a/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
+++ b/third_party/blink/renderer/modules/webaudio/offline_audio_context.cc
@@ -108,21 +108,6 @@
   fprintf(stderr, "[%16p]: OfflineAudioContext::OfflineAudioContext()\n",
           audio_context);
 #endif
-  base::UmaHistogramSparse("WebAudio.OfflineAudioContext.ChannelCount",
-                           number_of_channels);
-  // Arbitrarly limit the maximum length to 1 million frames (about 20 sec
-  // at 48kHz).  The number of buckets is fairly arbitrary.
-  base::UmaHistogramCounts1M("WebAudio.OfflineAudioContext.Length",
-                             number_of_frames);
-  // The limits are the min and max AudioBuffer sample rates currently
-  // supported.  We use explicit values here instead of
-  // audio_utilities::minAudioBufferSampleRate() and
-  // audio_utilities::maxAudioBufferSampleRate().  The number of buckets is
-  // fairly arbitrary.
-  base::UmaHistogramCustomCounts(
-      "WebAudio.OfflineAudioContext.SampleRate384kHz", sample_rate, 3000,
-      384000, 50);
-
   return audio_context;
 }
 
diff --git a/third_party/blink/renderer/platform/BUILD.gn b/third_party/blink/renderer/platform/BUILD.gn
index 9c75ef6..f20480e 100644
--- a/third_party/blink/renderer/platform/BUILD.gn
+++ b/third_party/blink/renderer/platform/BUILD.gn
@@ -659,6 +659,8 @@
     "fonts/shaping/caching_word_shaper.h",
     "fonts/shaping/case_mapping_harfbuzz_buffer_filler.cc",
     "fonts/shaping/case_mapping_harfbuzz_buffer_filler.h",
+    "fonts/shaping/font_features.cc",
+    "fonts/shaping/font_features.h",
     "fonts/shaping/glyph_bounds_accumulator.h",
     "fonts/shaping/harfbuzz_face.cc",
     "fonts/shaping/harfbuzz_face.h",
diff --git a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
index 371a8a4..542b3d2 100644
--- a/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
+++ b/third_party/blink/renderer/platform/bindings/active_script_wrappable_base.h
@@ -46,7 +46,7 @@
 #if BUILDFLAG(USE_V8_OILPAN)
 
 namespace cppgc {
-template <typename T, typename = void>
+template <typename T, typename Unused>
 struct PostConstructionCallbackTrait;
 
 template <typename T>
diff --git a/third_party/blink/renderer/platform/fonts/shaping/font_features.cc b/third_party/blink/renderer/platform/fonts/shaping/font_features.cc
new file mode 100644
index 0000000..71244ca
--- /dev/null
+++ b/third_party/blink/renderer/platform/fonts/shaping/font_features.cc
@@ -0,0 +1,201 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/platform/fonts/shaping/font_features.h"
+
+#include "third_party/blink/renderer/platform/fonts/font.h"
+
+namespace blink {
+
+namespace {
+
+constexpr hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) {
+  return {tag, value, 0 /* start */, static_cast<unsigned>(-1) /* end */};
+}
+
+constexpr hb_feature_t CreateFeature(char c1,
+                                     char c2,
+                                     char c3,
+                                     char c4,
+                                     uint32_t value = 0) {
+  return CreateFeature(HB_TAG(c1, c2, c3, c4), value);
+}
+
+}  // namespace
+
+void FontFeatures::Initialize(const Font& font) {
+  DCHECK(IsEmpty());
+  const FontDescription& description = font.GetFontDescription();
+
+  constexpr hb_feature_t no_kern = CreateFeature('k', 'e', 'r', 'n');
+  constexpr hb_feature_t no_vkrn = CreateFeature('v', 'k', 'r', 'n');
+  switch (description.GetKerning()) {
+    case FontDescription::kNormalKerning:
+      // kern/vkrn are enabled by default in HarfBuzz
+      break;
+    case FontDescription::kNoneKerning:
+      Append(description.IsVerticalAnyUpright() ? no_vkrn : no_kern);
+      break;
+    case FontDescription::kAutoKerning:
+      break;
+  }
+
+  {
+    bool default_is_off = description.TextRendering() == blink::kOptimizeSpeed;
+    bool letter_spacing = description.LetterSpacing() != 0;
+    constexpr auto normal = FontDescription::kNormalLigaturesState;
+    constexpr auto enabled = FontDescription::kEnabledLigaturesState;
+    constexpr auto disabled = FontDescription::kDisabledLigaturesState;
+
+    // clig and liga are on by default in HarfBuzz
+    constexpr hb_feature_t no_clig = CreateFeature('c', 'l', 'i', 'g');
+    constexpr hb_feature_t no_liga = CreateFeature('l', 'i', 'g', 'a');
+    auto common = description.CommonLigaturesState();
+    if (letter_spacing ||
+        (common == disabled || (common == normal && default_is_off))) {
+      Append(no_liga);
+      Append(no_clig);
+    }
+    // dlig is off by default in HarfBuzz
+    constexpr hb_feature_t dlig = CreateFeature('d', 'l', 'i', 'g', 1);
+    auto discretionary = description.DiscretionaryLigaturesState();
+    if (!letter_spacing && discretionary == enabled) {
+      Append(dlig);
+    }
+    // hlig is off by default in HarfBuzz
+    constexpr hb_feature_t hlig = CreateFeature('h', 'l', 'i', 'g', 1);
+    auto historical = description.HistoricalLigaturesState();
+    if (!letter_spacing && historical == enabled) {
+      Append(hlig);
+    }
+    // calt is on by default in HarfBuzz
+    constexpr hb_feature_t no_calt = CreateFeature('c', 'a', 'l', 't');
+    auto contextual = description.ContextualLigaturesState();
+    if (letter_spacing ||
+        (contextual == disabled || (contextual == normal && default_is_off))) {
+      Append(no_calt);
+    }
+  }
+
+  static constexpr hb_feature_t hwid = CreateFeature('h', 'w', 'i', 'd', 1);
+  static constexpr hb_feature_t twid = CreateFeature('t', 'w', 'i', 'd', 1);
+  static constexpr hb_feature_t qwid = CreateFeature('q', 'w', 'i', 'd', 1);
+  switch (description.WidthVariant()) {
+    case kHalfWidth:
+      Append(hwid);
+      break;
+    case kThirdWidth:
+      Append(twid);
+      break;
+    case kQuarterWidth:
+      Append(qwid);
+      break;
+    case kRegularWidth:
+      break;
+  }
+
+  // font-variant-east-asian:
+  const FontVariantEastAsian east_asian = description.VariantEastAsian();
+  if (UNLIKELY(!east_asian.IsAllNormal())) {
+    static constexpr hb_feature_t jp78 = CreateFeature('j', 'p', '7', '8', 1);
+    static constexpr hb_feature_t jp83 = CreateFeature('j', 'p', '8', '3', 1);
+    static constexpr hb_feature_t jp90 = CreateFeature('j', 'p', '9', '0', 1);
+    static constexpr hb_feature_t jp04 = CreateFeature('j', 'p', '0', '4', 1);
+    static constexpr hb_feature_t smpl = CreateFeature('s', 'm', 'p', 'l', 1);
+    static constexpr hb_feature_t trad = CreateFeature('t', 'r', 'a', 'd', 1);
+    switch (east_asian.Form()) {
+      case FontVariantEastAsian::kNormalForm:
+        break;
+      case FontVariantEastAsian::kJis78:
+        Append(jp78);
+        break;
+      case FontVariantEastAsian::kJis83:
+        Append(jp83);
+        break;
+      case FontVariantEastAsian::kJis90:
+        Append(jp90);
+        break;
+      case FontVariantEastAsian::kJis04:
+        Append(jp04);
+        break;
+      case FontVariantEastAsian::kSimplified:
+        Append(smpl);
+        break;
+      case FontVariantEastAsian::kTraditional:
+        Append(trad);
+        break;
+      default:
+        NOTREACHED();
+    }
+    static constexpr hb_feature_t fwid = CreateFeature('f', 'w', 'i', 'd', 1);
+    static constexpr hb_feature_t pwid = CreateFeature('p', 'w', 'i', 'd', 1);
+    switch (east_asian.Width()) {
+      case FontVariantEastAsian::kNormalWidth:
+        break;
+      case FontVariantEastAsian::kFullWidth:
+        Append(fwid);
+        break;
+      case FontVariantEastAsian::kProportionalWidth:
+        Append(pwid);
+        break;
+      default:
+        NOTREACHED();
+    }
+    static constexpr hb_feature_t ruby = CreateFeature('r', 'u', 'b', 'y', 1);
+    if (east_asian.Ruby())
+      Append(ruby);
+  }
+
+  // font-variant-numeric:
+  static constexpr hb_feature_t lnum = CreateFeature('l', 'n', 'u', 'm', 1);
+  if (description.VariantNumeric().NumericFigureValue() ==
+      FontVariantNumeric::kLiningNums)
+    Append(lnum);
+
+  static constexpr hb_feature_t onum = CreateFeature('o', 'n', 'u', 'm', 1);
+  if (description.VariantNumeric().NumericFigureValue() ==
+      FontVariantNumeric::kOldstyleNums)
+    Append(onum);
+
+  static constexpr hb_feature_t pnum = CreateFeature('p', 'n', 'u', 'm', 1);
+  if (description.VariantNumeric().NumericSpacingValue() ==
+      FontVariantNumeric::kProportionalNums)
+    Append(pnum);
+  static constexpr hb_feature_t tnum = CreateFeature('t', 'n', 'u', 'm', 1);
+  if (description.VariantNumeric().NumericSpacingValue() ==
+      FontVariantNumeric::kTabularNums)
+    Append(tnum);
+
+  static constexpr hb_feature_t afrc = CreateFeature('a', 'f', 'r', 'c', 1);
+  if (description.VariantNumeric().NumericFractionValue() ==
+      FontVariantNumeric::kStackedFractions)
+    Append(afrc);
+  static constexpr hb_feature_t frac = CreateFeature('f', 'r', 'a', 'c', 1);
+  if (description.VariantNumeric().NumericFractionValue() ==
+      FontVariantNumeric::kDiagonalFractions)
+    Append(frac);
+
+  static constexpr hb_feature_t ordn = CreateFeature('o', 'r', 'd', 'n', 1);
+  if (description.VariantNumeric().OrdinalValue() ==
+      FontVariantNumeric::kOrdinalOn)
+    Append(ordn);
+
+  static constexpr hb_feature_t zero = CreateFeature('z', 'e', 'r', 'o', 1);
+  if (description.VariantNumeric().SlashedZeroValue() ==
+      FontVariantNumeric::kSlashedZeroOn)
+    Append(zero);
+
+  FontFeatureSettings* settings = description.FeatureSettings();
+  if (!settings)
+    return;
+
+  // TODO(drott): crbug.com/450619 Implement feature resolution instead of
+  // just appending the font-feature-settings.
+  for (const FontFeature& setting : *settings) {
+    const hb_feature_t feature = CreateFeature(setting.Tag(), setting.Value());
+    Append(feature);
+  }
+}
+
+}  // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/shaping/font_features.h b/third_party/blink/renderer/platform/fonts/shaping/font_features.h
new file mode 100644
index 0000000..e67b7b1
--- /dev/null
+++ b/third_party/blink/renderer/platform/fonts/shaping/font_features.h
@@ -0,0 +1,43 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_FONT_FEATURES_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_FONT_FEATURES_H_
+
+#include <hb.h>
+
+#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
+#include "third_party/blink/renderer/platform/wtf/vector.h"
+
+namespace blink {
+
+class Font;
+
+// Represents a list of OpenType font feature settings.
+class FontFeatures {
+  STACK_ALLOCATED();
+
+ public:
+  // Initialize the list from |Font|.
+  void Initialize(const Font&);
+
+  wtf_size_t size() const { return features_.size(); }
+  bool IsEmpty() const { return features_.IsEmpty(); }
+
+  const hb_feature_t* data() const { return features_.data(); }
+
+  void Append(const hb_feature_t& feature) { features_.push_back(feature); }
+  void Insert(const hb_feature_t& feature) { features_.push_front(feature); }
+
+  void EraseAt(wtf_size_t position, wtf_size_t length) {
+    features_.EraseAt(position, length);
+  }
+
+ private:
+  Vector<hb_feature_t, 6> features_;
+};
+
+}  // namespace blink
+
+#endif  // THIRD_PARTY_BLINK_RENDERER_PLATFORM_FONTS_SHAPING_FONT_FEATURES_H_
diff --git a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
index babb8dfb..04f4bfd 100644
--- a/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
+++ b/third_party/blink/renderer/platform/fonts/shaping/harfbuzz_shaper.cc
@@ -45,6 +45,7 @@
 #include "third_party/blink/renderer/platform/fonts/font_fallback_iterator.h"
 #include "third_party/blink/renderer/platform/fonts/opentype/open_type_caps_support.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/case_mapping_harfbuzz_buffer_filler.h"
+#include "third_party/blink/renderer/platform/fonts/shaping/font_features.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/harfbuzz_face.h"
 #include "third_party/blink/renderer/platform/fonts/shaping/shape_result_inline_headers.h"
 #include "third_party/blink/renderer/platform/fonts/small_caps_iterator.h"
@@ -59,6 +60,15 @@
 
 namespace {
 
+constexpr hb_feature_t CreateFeature(char c1,
+                                     char c2,
+                                     char c3,
+                                     char c4,
+                                     uint32_t value = 0) {
+  return {HB_TAG(c1, c2, c3, c4), value, 0 /* start */,
+          static_cast<unsigned>(-1) /* end */};
+}
+
 #if DCHECK_IS_ON()
 // Check if the ShapeResult has the specified range.
 // |text| and |font| are only for logging.
@@ -148,14 +158,16 @@
   DISALLOW_COPY_AND_ASSIGN(HarfBuzzScopedPtr);
 };
 
-using FeaturesVector = Vector<hb_feature_t, 6>;
 struct RangeData {
+  STACK_ALLOCATED();
+
+ public:
   hb_buffer_t* buffer;
   const Font* font;
   TextDirection text_direction;
   unsigned start;
   unsigned end;
-  FeaturesVector font_features;
+  FontFeatures font_features;
   Deque<ReshapeQueueItem> reshape_queue;
 
   hb_direction_t HarfBuzzDirection(CanvasRotationInVertical canvas_rotation) {
@@ -212,7 +224,7 @@
 }
 
 inline bool ShapeRange(hb_buffer_t* buffer,
-                       hb_feature_t* font_features,
+                       const hb_feature_t* font_features,
                        unsigned font_features_size,
                        const SimpleFontData* current_font,
                        scoped_refptr<UnicodeRangeSet> current_font_range_set,
@@ -566,211 +578,6 @@
   }
 }
 
-constexpr hb_feature_t CreateFeature(hb_tag_t tag, uint32_t value = 0) {
-  return {tag, value, 0 /* start */, static_cast<unsigned>(-1) /* end */};
-}
-
-// TODO(kojii): crbug.com/762493 This list is getting long enough to extract out
-// of HarfBuzzShaper.cpp.
-void SetFontFeatures(const Font* font, FeaturesVector* features) {
-  const FontDescription& description = font->GetFontDescription();
-
-  constexpr hb_feature_t no_kern = CreateFeature(HB_TAG('k', 'e', 'r', 'n'));
-  constexpr hb_feature_t no_vkrn = CreateFeature(HB_TAG('v', 'k', 'r', 'n'));
-  switch (description.GetKerning()) {
-    case FontDescription::kNormalKerning:
-      // kern/vkrn are enabled by default in HarfBuzz
-      break;
-    case FontDescription::kNoneKerning:
-      features->push_back(description.IsVerticalAnyUpright() ? no_vkrn
-                                                             : no_kern);
-      break;
-    case FontDescription::kAutoKerning:
-      break;
-  }
-
-  {
-    bool default_is_off = description.TextRendering() == blink::kOptimizeSpeed;
-    bool letter_spacing = description.LetterSpacing() != 0;
-    constexpr auto normal = FontDescription::kNormalLigaturesState;
-    constexpr auto enabled = FontDescription::kEnabledLigaturesState;
-    constexpr auto disabled = FontDescription::kDisabledLigaturesState;
-
-    // clig and liga are on by default in HarfBuzz
-    constexpr hb_feature_t no_clig = CreateFeature(HB_TAG('c', 'l', 'i', 'g'));
-    constexpr hb_feature_t no_liga = CreateFeature(HB_TAG('l', 'i', 'g', 'a'));
-    auto common = description.CommonLigaturesState();
-    if (letter_spacing ||
-        (common == disabled || (common == normal && default_is_off))) {
-      features->push_back(no_liga);
-      features->push_back(no_clig);
-    }
-    // dlig is off by default in HarfBuzz
-    constexpr hb_feature_t dlig = CreateFeature(HB_TAG('d', 'l', 'i', 'g'), 1);
-    auto discretionary = description.DiscretionaryLigaturesState();
-    if (!letter_spacing && discretionary == enabled) {
-      features->push_back(dlig);
-    }
-    // hlig is off by default in HarfBuzz
-    constexpr hb_feature_t hlig = CreateFeature(HB_TAG('h', 'l', 'i', 'g'), 1);
-    auto historical = description.HistoricalLigaturesState();
-    if (!letter_spacing && historical == enabled) {
-      features->push_back(hlig);
-    }
-    // calt is on by default in HarfBuzz
-    constexpr hb_feature_t no_calt = CreateFeature(HB_TAG('c', 'a', 'l', 't'));
-    auto contextual = description.ContextualLigaturesState();
-    if (letter_spacing ||
-        (contextual == disabled || (contextual == normal && default_is_off))) {
-      features->push_back(no_calt);
-    }
-  }
-
-  static constexpr hb_feature_t hwid =
-      CreateFeature(HB_TAG('h', 'w', 'i', 'd'), 1);
-  static constexpr hb_feature_t twid =
-      CreateFeature(HB_TAG('t', 'w', 'i', 'd'), 1);
-  static constexpr hb_feature_t qwid =
-      CreateFeature(HB_TAG('q', 'w', 'i', 'd'), 1);
-  switch (description.WidthVariant()) {
-    case kHalfWidth:
-      features->push_back(hwid);
-      break;
-    case kThirdWidth:
-      features->push_back(twid);
-      break;
-    case kQuarterWidth:
-      features->push_back(qwid);
-      break;
-    case kRegularWidth:
-      break;
-  }
-
-  // font-variant-east-asian:
-  const FontVariantEastAsian east_asian = description.VariantEastAsian();
-  if (UNLIKELY(!east_asian.IsAllNormal())) {
-    static constexpr hb_feature_t jp78 =
-        CreateFeature(HB_TAG('j', 'p', '7', '8'), 1);
-    static constexpr hb_feature_t jp83 =
-        CreateFeature(HB_TAG('j', 'p', '8', '3'), 1);
-    static constexpr hb_feature_t jp90 =
-        CreateFeature(HB_TAG('j', 'p', '9', '0'), 1);
-    static constexpr hb_feature_t jp04 =
-        CreateFeature(HB_TAG('j', 'p', '0', '4'), 1);
-    static constexpr hb_feature_t smpl =
-        CreateFeature(HB_TAG('s', 'm', 'p', 'l'), 1);
-    static constexpr hb_feature_t trad =
-        CreateFeature(HB_TAG('t', 'r', 'a', 'd'), 1);
-    switch (east_asian.Form()) {
-      case FontVariantEastAsian::kNormalForm:
-        break;
-      case FontVariantEastAsian::kJis78:
-        features->push_back(jp78);
-        break;
-      case FontVariantEastAsian::kJis83:
-        features->push_back(jp83);
-        break;
-      case FontVariantEastAsian::kJis90:
-        features->push_back(jp90);
-        break;
-      case FontVariantEastAsian::kJis04:
-        features->push_back(jp04);
-        break;
-      case FontVariantEastAsian::kSimplified:
-        features->push_back(smpl);
-        break;
-      case FontVariantEastAsian::kTraditional:
-        features->push_back(trad);
-        break;
-      default:
-        NOTREACHED();
-    }
-    static constexpr hb_feature_t fwid =
-        CreateFeature(HB_TAG('f', 'w', 'i', 'd'), 1);
-    static constexpr hb_feature_t pwid =
-        CreateFeature(HB_TAG('p', 'w', 'i', 'd'), 1);
-    switch (east_asian.Width()) {
-      case FontVariantEastAsian::kNormalWidth:
-        break;
-      case FontVariantEastAsian::kFullWidth:
-        features->push_back(fwid);
-        break;
-      case FontVariantEastAsian::kProportionalWidth:
-        features->push_back(pwid);
-        break;
-      default:
-        NOTREACHED();
-    }
-    static constexpr hb_feature_t ruby =
-        CreateFeature(HB_TAG('r', 'u', 'b', 'y'), 1);
-    if (east_asian.Ruby())
-      features->push_back(ruby);
-  }
-
-  // font-variant-numeric:
-  static constexpr hb_feature_t lnum =
-      CreateFeature(HB_TAG('l', 'n', 'u', 'm'), 1);
-  if (description.VariantNumeric().NumericFigureValue() ==
-      FontVariantNumeric::kLiningNums)
-    features->push_back(lnum);
-
-  static constexpr hb_feature_t onum =
-      CreateFeature(HB_TAG('o', 'n', 'u', 'm'), 1);
-  if (description.VariantNumeric().NumericFigureValue() ==
-      FontVariantNumeric::kOldstyleNums)
-    features->push_back(onum);
-
-  static constexpr hb_feature_t pnum =
-      CreateFeature(HB_TAG('p', 'n', 'u', 'm'), 1);
-  if (description.VariantNumeric().NumericSpacingValue() ==
-      FontVariantNumeric::kProportionalNums)
-    features->push_back(pnum);
-  static constexpr hb_feature_t tnum =
-      CreateFeature(HB_TAG('t', 'n', 'u', 'm'), 1);
-  if (description.VariantNumeric().NumericSpacingValue() ==
-      FontVariantNumeric::kTabularNums)
-    features->push_back(tnum);
-
-  static constexpr hb_feature_t afrc =
-      CreateFeature(HB_TAG('a', 'f', 'r', 'c'), 1);
-  if (description.VariantNumeric().NumericFractionValue() ==
-      FontVariantNumeric::kStackedFractions)
-    features->push_back(afrc);
-  static constexpr hb_feature_t frac =
-      CreateFeature(HB_TAG('f', 'r', 'a', 'c'), 1);
-  if (description.VariantNumeric().NumericFractionValue() ==
-      FontVariantNumeric::kDiagonalFractions)
-    features->push_back(frac);
-
-  static constexpr hb_feature_t ordn =
-      CreateFeature(HB_TAG('o', 'r', 'd', 'n'), 1);
-  if (description.VariantNumeric().OrdinalValue() ==
-      FontVariantNumeric::kOrdinalOn)
-    features->push_back(ordn);
-
-  static constexpr hb_feature_t zero =
-      CreateFeature(HB_TAG('z', 'e', 'r', 'o'), 1);
-  if (description.VariantNumeric().SlashedZeroValue() ==
-      FontVariantNumeric::kSlashedZeroOn)
-    features->push_back(zero);
-
-  FontFeatureSettings* settings = description.FeatureSettings();
-  if (!settings)
-    return;
-
-  // TODO(drott): crbug.com/450619 Implement feature resolution instead of
-  // just appending the font-feature-settings.
-  unsigned num_features = settings->size();
-  for (unsigned i = 0; i < num_features; ++i) {
-    hb_feature_t feature;
-    feature.tag = settings->at(i).Tag();
-    feature.value = settings->at(i).Value();
-    feature.start = 0;
-    feature.end = static_cast<unsigned>(-1);
-    features->push_back(feature);
-  }
-}
-
 inline RangeData CreateRangeData(const Font* font,
                                  TextDirection direction,
                                  hb_buffer_t* buffer) {
@@ -778,7 +585,7 @@
   range_data.buffer = buffer;
   range_data.font = font;
   range_data.text_direction = direction;
-  SetFontFeatures(font, &range_data.font_features);
+  range_data.font_features.Initialize(*font);
   return range_data;
 }
 
@@ -786,7 +593,7 @@
   STACK_ALLOCATED();
 
  public:
-  CapsFeatureSettingsScopedOverlay(FeaturesVector*,
+  CapsFeatureSettingsScopedOverlay(FontFeatures*,
                                    FontDescription::FontVariantCaps);
   CapsFeatureSettingsScopedOverlay() = delete;
   ~CapsFeatureSettingsScopedOverlay();
@@ -794,12 +601,12 @@
  private:
   void OverlayCapsFeatures(FontDescription::FontVariantCaps);
   void PrependCounting(const hb_feature_t&);
-  FeaturesVector* features_;
+  FontFeatures* features_;
   wtf_size_t count_features_;
 };
 
 CapsFeatureSettingsScopedOverlay::CapsFeatureSettingsScopedOverlay(
-    FeaturesVector* features,
+    FontFeatures* features,
     FontDescription::FontVariantCaps variant_caps)
     : features_(features), count_features_(0) {
   OverlayCapsFeatures(variant_caps);
@@ -807,18 +614,12 @@
 
 void CapsFeatureSettingsScopedOverlay::OverlayCapsFeatures(
     FontDescription::FontVariantCaps variant_caps) {
-  static constexpr hb_feature_t smcp =
-      CreateFeature(HB_TAG('s', 'm', 'c', 'p'), 1);
-  static constexpr hb_feature_t pcap =
-      CreateFeature(HB_TAG('p', 'c', 'a', 'p'), 1);
-  static constexpr hb_feature_t c2sc =
-      CreateFeature(HB_TAG('c', '2', 's', 'c'), 1);
-  static constexpr hb_feature_t c2pc =
-      CreateFeature(HB_TAG('c', '2', 'p', 'c'), 1);
-  static constexpr hb_feature_t unic =
-      CreateFeature(HB_TAG('u', 'n', 'i', 'c'), 1);
-  static constexpr hb_feature_t titl =
-      CreateFeature(HB_TAG('t', 'i', 't', 'l'), 1);
+  static constexpr hb_feature_t smcp = CreateFeature('s', 'm', 'c', 'p', 1);
+  static constexpr hb_feature_t pcap = CreateFeature('p', 'c', 'a', 'p', 1);
+  static constexpr hb_feature_t c2sc = CreateFeature('c', '2', 's', 'c', 1);
+  static constexpr hb_feature_t c2pc = CreateFeature('c', '2', 'p', 'c', 1);
+  static constexpr hb_feature_t unic = CreateFeature('u', 'n', 'i', 'c', 1);
+  static constexpr hb_feature_t titl = CreateFeature('t', 'i', 't', 'l', 1);
   if (variant_caps == FontDescription::kSmallCaps ||
       variant_caps == FontDescription::kAllSmallCaps) {
     PrependCounting(smcp);
@@ -843,7 +644,7 @@
 
 void CapsFeatureSettingsScopedOverlay::PrependCounting(
     const hb_feature_t& feature) {
-  features_->push_front(feature);
+  features_->Insert(feature);
   count_features_++;
 }
 
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc b/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
index c053f18..a12b2b81 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.cc
@@ -8,70 +8,40 @@
 #include "mojo/public/cpp/base/file_path_mojom_traits.h"
 #include "mojo/public/cpp/bindings/array_traits_wtf_vector.h"
 #include "third_party/blink/public/mojom/fetch/fetch_api_request.mojom-blink.h"
+#include "third_party/blink/public/platform/cross_variant_mojo_util.h"
 #include "third_party/blink/public/platform/file_path_conversion.h"
 #include "third_party/blink/renderer/platform/blob/blob_data.h"
+#include "third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h"
 #include "third_party/blink/renderer/platform/network/form_data_encoder.h"
 #include "third_party/blink/renderer/platform/network/wrapped_data_pipe_getter.h"
 
 namespace mojo {
 
 // static
-WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr>
+WTF::Vector<network::DataElement>
 StructTraits<blink::mojom::FetchAPIRequestBodyDataView,
              blink::ResourceRequestBody>::elements(blink::ResourceRequestBody&
                                                        mutable_body) {
-  WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr> out_elements;
-  const auto& body = mutable_body;
-  if (body.IsEmpty()) {
-    return out_elements;
+  scoped_refptr<network::ResourceRequestBody> network_body;
+  if (auto form_body = mutable_body.FormBody()) {
+    // Here we need to keep the original body, because other members such as
+    // `identifier` are on the form body.
+    network_body = NetworkResourceRequestBodyFor(
+        blink::ResourceRequestBody(form_body),
+        /*allow_http1_for_streaming_upload=*/false);
+  } else if (mutable_body.StreamBody()) {
+    // Here we don't need to keep the original body (and it's impossible to do
+    // so, because the streaming body is not copyable).
+    network_body = NetworkResourceRequestBodyFor(
+        std::move(mutable_body), /*allow_http1_for_streaming_upload=*/false);
   }
-
-  if (mutable_body.StreamBody()) {
-    auto out = blink::mojom::blink::FetchAPIDataElement::New();
-    out->type = network::mojom::DataElementType::kReadOnceStream;
-    out->chunked_data_pipe_getter = mutable_body.TakeStreamBody();
-    out_elements.push_back(std::move(out));
-    return out_elements;
+  if (!network_body) {
+    return WTF::Vector<network::DataElement>();
   }
-
-  DCHECK(body.FormBody());
-  for (const auto& element : body.FormBody()->elements_) {
-    auto out = blink::mojom::blink::FetchAPIDataElement::New();
-    switch (element.type_) {
-      case blink::FormDataElement::kData:
-        out->type = network::mojom::DataElementType::kBytes;
-        out->buf.ReserveCapacity(element.data_.size());
-        for (const char c : element.data_) {
-          out->buf.push_back(static_cast<uint8_t>(c));
-        }
-        break;
-      case blink::FormDataElement::kEncodedFile:
-        out->type = network::mojom::DataElementType::kFile;
-        out->path = base::FilePath::FromUTF8Unsafe(element.filename_.Utf8());
-        out->offset = element.file_start_;
-        out->length = element.file_length_;
-        out->expected_modification_time =
-            element.expected_file_modification_time_.value_or(base::Time());
-        break;
-      case blink::FormDataElement::kEncodedBlob: {
-        out->type = network::mojom::DataElementType::kDataPipe;
-        out->length = element.optional_blob_data_handle_->size();
-
-        mojo::Remote<blink::mojom::blink::Blob> blob_remote(
-            element.optional_blob_data_handle_->CloneBlobRemote());
-        blob_remote->AsDataPipeGetter(
-            out->data_pipe_getter.InitWithNewPipeAndPassReceiver());
-        break;
-      }
-      case blink::FormDataElement::kDataPipe:
-        out->type = network::mojom::DataElementType::kDataPipe;
-        if (element.data_pipe_getter_) {
-          element.data_pipe_getter_->GetDataPipeGetter()->Clone(
-              out->data_pipe_getter.InitWithNewPipeAndPassReceiver());
-        }
-        break;
-    }
-    out_elements.push_back(std::move(out));
+  WTF::Vector<network::DataElement> out_elements;
+  DCHECK(network_body->elements_mutable());
+  for (auto& element : *network_body->elements_mutable()) {
+    out_elements.emplace_back(std::move(element));
   }
   return out_elements;
 }
@@ -86,73 +56,58 @@
     return true;
   }
 
-  mojo::ArrayDataView<blink::mojom::FetchAPIDataElementDataView> elements_view;
+  mojo::ArrayDataView<network::mojom::DataElementDataView> elements_view;
   in.GetElementsDataView(&elements_view);
   if (elements_view.size() == 1) {
-    blink::mojom::FetchAPIDataElementDataView view;
+    network::mojom::DataElementDataView view;
     elements_view.GetDataView(0, &view);
 
-    network::mojom::DataElementType type;
-    if (!view.ReadType(&type)) {
-      return false;
-    }
-    if (type == network::mojom::DataElementType::kReadOnceStream) {
-      auto chunked_data_pipe_getter = view.TakeChunkedDataPipeGetter<
-          mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>>();
-      *out = blink::ResourceRequestBody(std::move(chunked_data_pipe_getter));
+    DCHECK(!view.is_null());
+    if (view.tag() == network::DataElement::Tag::kChunkedDataPipe) {
+      network::DataElement element;
+      if (!elements_view.Read(0, &element)) {
+        return false;
+      }
+      auto& chunked_data_pipe =
+          element.As<network::DataElementChunkedDataPipe>();
+      *out = blink::ResourceRequestBody(blink::ToCrossVariantMojoType(
+          chunked_data_pipe.ReleaseChunkedDataPipeGetter()));
       return true;
     }
   }
   auto form_data = blink::EncodedFormData::Create();
   for (size_t i = 0; i < elements_view.size(); ++i) {
-    blink::mojom::FetchAPIDataElementDataView view;
-    elements_view.GetDataView(i, &view);
-
-    network::mojom::DataElementType type;
-    if (!view.ReadType(&type)) {
+    network::DataElement element;
+    if (!elements_view.Read(i, &element)) {
       return false;
     }
-    switch (type) {
-      case network::mojom::DataElementType::kBytes: {
-        // TODO(richard.li): Delete this workaround when type of
-        // blink::FormDataElement::data_ is changed to WTF::Vector<uint8_t>
-        WTF::Vector<uint8_t> buf;
-        if (!view.ReadBuf(&buf)) {
-          return false;
-        }
-        form_data->AppendData(buf.data(), buf.size());
-        break;
-      }
-      case network::mojom::DataElementType::kFile: {
-        base::FilePath file_path;
-        base::Time expected_time;
-        if (!view.ReadPath(&file_path) ||
-            !view.ReadExpectedModificationTime(&expected_time)) {
-          return false;
-        }
-        base::Optional<base::Time> expected_file_modification_time;
-        if (!expected_time.is_null()) {
-          expected_file_modification_time = expected_time;
-        }
-        form_data->AppendFileRange(blink::FilePathToString(file_path),
-                                   view.offset(), view.length(),
-                                   expected_file_modification_time);
-        break;
-      }
-      case network::mojom::DataElementType::kDataPipe: {
-        auto data_pipe_ptr_remote = view.TakeDataPipeGetter<
-            mojo::PendingRemote<network::mojom::blink::DataPipeGetter>>();
-        DCHECK(data_pipe_ptr_remote.is_valid());
 
+    switch (element.type()) {
+      case network::DataElement::Tag::kBytes: {
+        const auto& bytes = element.As<network::DataElementBytes>();
+        form_data->AppendData(bytes.bytes().data(), bytes.bytes().size());
+        break;
+      }
+      case network::DataElement::Tag::kFile: {
+        const auto& file = element.As<network::DataElementFile>();
+        base::Optional<base::Time> expected_modification_time;
+        if (!file.expected_modification_time().is_null()) {
+          expected_modification_time = file.expected_modification_time();
+        }
+        form_data->AppendFileRange(blink::FilePathToString(file.path()),
+                                   file.offset(), file.length(),
+                                   expected_modification_time);
+        break;
+      }
+      case network::DataElement::Tag::kDataPipe: {
+        auto& datapipe = element.As<network::DataElementDataPipe>();
         form_data->AppendDataPipe(
             base::MakeRefCounted<blink::WrappedDataPipeGetter>(
-                std::move(data_pipe_ptr_remote)));
-
+                blink::ToCrossVariantMojoType(
+                    datapipe.ReleaseDataPipeGetter())));
         break;
       }
-      case network::mojom::DataElementType::kUnknown:
-      case network::mojom::DataElementType::kChunkedDataPipe:
-      case network::mojom::DataElementType::kReadOnceStream:
+      case network::DataElement::Tag::kChunkedDataPipe:
         NOTREACHED();
         return false;
     }
diff --git a/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h b/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
index f85aee2..4576e3ab 100644
--- a/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
+++ b/third_party/blink/renderer/platform/loader/fetch/fetch_api_request_body_mojom_traits.h
@@ -21,7 +21,7 @@
   static void SetToNull(blink::ResourceRequestBody* out) {
     *out = blink::ResourceRequestBody();
   }
-  static WTF::Vector<blink::mojom::blink::FetchAPIDataElementPtr> elements(
+  static WTF::Vector<network::DataElement> elements(
       blink::ResourceRequestBody& mutable_body);
   static int64_t identifier(const blink::ResourceRequestBody& body) {
     return body.FormBody() ? body.FormBody()->Identifier() : 0;
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
index 25086dd..6544486a 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.cc
@@ -242,6 +242,27 @@
 
 }  // namespace
 
+scoped_refptr<network::ResourceRequestBody> NetworkResourceRequestBodyFor(
+    ResourceRequestBody src_body,
+    bool allow_http1_for_streaming_upload) {
+  scoped_refptr<network::ResourceRequestBody> dest_body;
+  if (const EncodedFormData* form_body = src_body.FormBody().get()) {
+    dest_body = base::MakeRefCounted<network::ResourceRequestBody>();
+
+    PopulateResourceRequestBody(*form_body, dest_body.get());
+  } else if (src_body.StreamBody().is_valid()) {
+    mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
+        stream_body = src_body.TakeStreamBody();
+    dest_body = base::MakeRefCounted<network::ResourceRequestBody>();
+    dest_body->SetToChunkedDataPipe(
+        ToCrossVariantMojoType(std::move(stream_body)),
+        network::ResourceRequestBody::ReadOnlyOnce(true));
+    dest_body->SetAllowHTTP1ForStreamingUpload(
+        allow_http1_for_streaming_upload);
+  }
+  return dest_body;
+}
+
 void PopulateResourceRequest(const ResourceRequestHead& src,
                              ResourceRequestBody src_body,
                              network::ResourceRequest* dest) {
@@ -355,22 +376,11 @@
 
   dest->is_fetch_like_api = src.IsFetchLikeAPI();
 
-  if (const EncodedFormData* body = src_body.FormBody().get()) {
+  dest->request_body = NetworkResourceRequestBodyFor(
+      std::move(src_body), src.AllowHTTP1ForStreamingUpload());
+  if (dest->request_body) {
     DCHECK_NE(dest->method, net::HttpRequestHeaders::kGetMethod);
     DCHECK_NE(dest->method, net::HttpRequestHeaders::kHeadMethod);
-    dest->request_body = base::MakeRefCounted<network::ResourceRequestBody>();
-
-    PopulateResourceRequestBody(*body, dest->request_body.get());
-  } else if (src_body.StreamBody().is_valid()) {
-    DCHECK_NE(dest->method, net::HttpRequestHeaders::kGetMethod);
-    DCHECK_NE(dest->method, net::HttpRequestHeaders::kHeadMethod);
-    mojo::PendingRemote<network::mojom::blink::ChunkedDataPipeGetter>
-        stream_body = src_body.TakeStreamBody();
-    dest->request_body = base::MakeRefCounted<network::ResourceRequestBody>();
-    dest->request_body->SetToReadOnceStream(
-        ToCrossVariantMojoType(std::move(stream_body)));
-    dest->request_body->SetAllowHTTP1ForStreamingUpload(
-        src.AllowHTTP1ForStreamingUpload());
   }
 
   if (resource_type == mojom::ResourceType::kStylesheet) {
diff --git a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
index f80cd23..f2c119f7 100644
--- a/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
+++ b/third_party/blink/renderer/platform/loader/fetch/url_loader/request_conversion.h
@@ -7,9 +7,11 @@
 
 // This file consists of request conversion functions between blink and network.
 
+#include "base/memory/ref_counted.h"
 #include "third_party/blink/renderer/platform/platform_export.h"
 
 namespace network {
+class ResourceRequestBody;
 struct ResourceRequest;
 }  // namespace network
 
@@ -20,6 +22,10 @@
 class ResourceRequestHead;
 class ResourceRequestBody;
 
+scoped_refptr<network::ResourceRequestBody> NetworkResourceRequestBodyFor(
+    const ResourceRequestBody src_body,
+    bool allow_http1_for_streaming_upload);
+
 void PopulateResourceRequest(const ResourceRequestHead& src,
                              ResourceRequestBody src_body,
                              network::ResourceRequest* dest);
diff --git a/third_party/blink/renderer/platform/loader/web_url_request_util.cc b/third_party/blink/renderer/platform/loader/web_url_request_util.cc
index 1aedbbac..464b7de 100644
--- a/third_party/blink/renderer/platform/loader/web_url_request_util.cc
+++ b/third_party/blink/renderer/platform/loader/web_url_request_util.cc
@@ -76,29 +76,31 @@
   http_body.SetContainsPasswordData(input.contains_sensitive_info());
   for (auto& element : *input.elements()) {
     switch (element.type()) {
-      case network::mojom::blink::DataElementType::kBytes:
+      case network::DataElement::Tag::kBytes: {
+        const auto& bytes = element.As<network::DataElementBytes>().bytes();
         http_body.AppendData(
-            WebData(element.bytes(), SafeCast<size_t>(element.length())));
+            WebData(reinterpret_cast<const char*>(bytes.data()), bytes.size()));
         break;
-      case network::mojom::blink::DataElementType::kFile: {
+      }
+      case network::DataElement::Tag::kFile: {
+        const auto& file = element.As<network::DataElementFile>();
         base::Optional<base::Time> modification_time;
-        if (!element.expected_modification_time().is_null())
-          modification_time = element.expected_modification_time();
+        if (!file.expected_modification_time().is_null())
+          modification_time = file.expected_modification_time();
         http_body.AppendFileRange(
-            FilePathToWebString(element.path()), element.offset(),
-            (element.length() != std::numeric_limits<uint64_t>::max())
-                ? element.length()
+            FilePathToWebString(file.path()), file.offset(),
+            (file.length() != std::numeric_limits<uint64_t>::max())
+                ? file.length()
                 : -1,
             modification_time);
         break;
       }
-      case network::mojom::blink::DataElementType::kDataPipe: {
-        http_body.AppendDataPipe(element.CloneDataPipeGetter());
+      case network::DataElement::Tag::kDataPipe: {
+        http_body.AppendDataPipe(
+            element.As<network::DataElementDataPipe>().CloneDataPipeGetter());
         break;
       }
-      case network::mojom::blink::DataElementType::kUnknown:
-      case network::mojom::blink::DataElementType::kChunkedDataPipe:
-      case network::mojom::blink::DataElementType::kReadOnceStream:
+      case network::DataElement::Tag::kChunkedDataPipe:
         NOTREACHED();
         break;
     }
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/WPTIncludeList b/third_party/blink/tools/blinkpy/third_party/wpt/WPTIncludeList
index ca0b1119..0d381c4 100644
--- a/third_party/blink/tools/blinkpy/third_party/wpt/WPTIncludeList
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/WPTIncludeList
@@ -2,8 +2,31 @@
 ./CONTRIBUTING.md
 ./docs/commands.json
 ./LICENSE.md
+./resources/testdriver-actions.js
+./resources/testdriver.js
+./resources/testdriver.js.headers
+./resources/testdriver-vendor.js
+./resources/testdriver-vendor.js.headers
 ./serve.py
 ./tools/__init__.py
+./tools/certs/README.md
+./tools/certs/01A389.pem
+./tools/certs/01A38A.pem
+./tools/certs/045C7F.pem
+./tools/certs/045C80.pem
+./tools/certs/09DDE0.pem
+./tools/certs/09DDE1.pem
+./tools/certs/serial.old
+./tools/certs/serial
+./tools/certs/index.txt.old
+./tools/certs/index.txt
+./tools/certs/index.txt.attr.old
+./tools/certs/index.txt.attr
+./tools/certs/config.json
+./tools/certs/cacert.key
+./tools/certs/cacert.pem
+./tools/certs/web-platform.test.key
+./tools/certs/web-platform.test.pem
 ./tools/ci/__init__.py
 ./tools/ci/commands.json
 ./tools/ci/tc/__init__.py
@@ -111,8 +134,12 @@
 ./tools/third_party/hyperframe/hyperframe/exceptions.py
 ./tools/third_party/hyperframe/hyperframe/flags.py
 ./tools/third_party/hyperframe/hyperframe/frame.py
+./tools/third_party/pdf_js/LICENSE
+./tools/third_party/pdf_js/pdf.js
+./tools/third_party/pdf_js/pdf.worker.js
 ./tools/third_party/pywebsocket3/LICENSE
 ./tools/third_party/pywebsocket3/mod_pywebsocket/__init__.py
+./tools/third_party/pywebsocket3/mod_pywebsocket/_stream_exceptions.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/common.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/dispatch.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/extensions.py
@@ -126,10 +153,12 @@
 ./tools/third_party/pywebsocket3/mod_pywebsocket/request_handler.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/server_util.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/standalone.py
-./tools/third_party/pywebsocket3/mod_pywebsocket/_stream_exceptions.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/stream.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/util.py
 ./tools/third_party/pywebsocket3/mod_pywebsocket/websocket_server.py
+./tools/third_party/pywebsocket3/README.md
+./tools/third_party/pywebsocket3/setup.py
+./tools/third_party/pywebsocket3/MANIFEST.in
 ./tools/third_party/six/LICENSE
 ./tools/third_party/six/six.py
 ./tools/third_party/webencodings/PKG-INFO
@@ -165,6 +194,129 @@
 ./tools/wpt/utils.py
 ./tools/wpt/virtualenv.py
 ./tools/wpt/wpt.py
+./tools/wptrunner/requirements_firefox.txt
+./tools/wptrunner/requirements_epiphany.txt
+./tools/wptrunner/tox.ini
+./tools/wptrunner/requirements_chrome_android.txt
+./tools/wptrunner/wptrunner.default.ini
+./tools/wptrunner/requirements.txt
+./tools/wptrunner/requirements_chrome.txt
+./tools/wptrunner/wptrunner/expectedtree.py
+./tools/wptrunner/wptrunner/testdriver-vendor.js
+./tools/wptrunner/wptrunner/config.py
+./tools/wptrunner/wptrunner/testharnessreport-servodriver.js
+./tools/wptrunner/wptrunner/testharness_runner.html
+./tools/wptrunner/wptrunner/executors/executorselenium.py
+./tools/wptrunner/wptrunner/executors/test-wait.js
+./tools/wptrunner/wptrunner/executors/executoropera.py
+./tools/wptrunner/wptrunner/executors/window-loaded.js
+./tools/wptrunner/wptrunner/executors/executoredge.py
+./tools/wptrunner/wptrunner/executors/protocol.py
+./tools/wptrunner/wptrunner/executors/executorservo.py
+./tools/wptrunner/wptrunner/executors/testharness_servodriver.js
+./tools/wptrunner/wptrunner/executors/base.py
+./tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py
+./tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
+./tools/wptrunner/wptrunner/executors/executoredgechromium.py
+./tools/wptrunner/wptrunner/executors/runner.js
+./tools/wptrunner/wptrunner/executors/actions.py
+./tools/wptrunner/wptrunner/executors/__init__.py
+./tools/wptrunner/wptrunner/executors/executorwebkit.py
+./tools/wptrunner/wptrunner/executors/executorinternetexplorer.py
+./tools/wptrunner/wptrunner/executors/executorchrome.py
+./tools/wptrunner/wptrunner/executors/executormarionette.py
+./tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
+./tools/wptrunner/wptrunner/executors/reftest.js
+./tools/wptrunner/wptrunner/executors/executorwebdriver.py
+./tools/wptrunner/wptrunner/executors/executorservodriver.py
+./tools/wptrunner/wptrunner/executors/process.py
+./tools/wptrunner/wptrunner/executors/executorsafari.py
+./tools/wptrunner/wptrunner/print_reftest_runner.html
+./tools/wptrunner/wptrunner/metadata.py
+./tools/wptrunner/wptrunner/wptlogging.py
+./tools/wptrunner/wptrunner/vcs.py
+./tools/wptrunner/wptrunner/wpttest.py
+./tools/wptrunner/wptrunner/wptcommandline.py
+./tools/wptrunner/wptrunner/font.py
+./tools/wptrunner/wptrunner/manifestinclude.py
+./tools/wptrunner/wptrunner/mpcontext.py
+./tools/wptrunner/wptrunner/webdriver_server.py
+./tools/wptrunner/wptrunner/products.py
+./tools/wptrunner/wptrunner/expected.py
+./tools/wptrunner/wptrunner/formatters/chromium.py
+./tools/wptrunner/wptrunner/formatters/__init__.py
+./tools/wptrunner/wptrunner/formatters/wptscreenshot.py
+./tools/wptrunner/wptrunner/formatters/wptreport.py
+./tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
+./tools/wptrunner/wptrunner/manifestupdate.py
+./tools/wptrunner/wptrunner/testharnessreport-servo.js
+./tools/wptrunner/wptrunner/manifestexpected.py
+./tools/wptrunner/wptrunner/stability.py
+./tools/wptrunner/wptrunner/browsers/edgechromium.py
+./tools/wptrunner/wptrunner/browsers/servodriver.py
+./tools/wptrunner/wptrunner/browsers/ie.py
+./tools/wptrunner/wptrunner/browsers/sauce.py
+./tools/wptrunner/wptrunner/browsers/firefox.py
+./tools/wptrunner/wptrunner/browsers/android_weblayer.py
+./tools/wptrunner/wptrunner/browsers/android_webview.py
+./tools/wptrunner/wptrunner/browsers/chrome_android.py
+./tools/wptrunner/wptrunner/browsers/webkit.py
+./tools/wptrunner/wptrunner/browsers/chrome_ios.py
+./tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
+./tools/wptrunner/wptrunner/browsers/chrome.py
+./tools/wptrunner/wptrunner/browsers/base.py
+./tools/wptrunner/wptrunner/browsers/firefox_android.py
+./tools/wptrunner/wptrunner/browsers/epiphany.py
+./tools/wptrunner/wptrunner/browsers/edge.py
+./tools/wptrunner/wptrunner/browsers/__init__.py
+./tools/wptrunner/wptrunner/browsers/opera.py
+./tools/wptrunner/wptrunner/browsers/servo.py
+./tools/wptrunner/wptrunner/browsers/safari.py
+./tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
+./tools/wptrunner/wptrunner/browsers/edge_webdriver.py
+./tools/wptrunner/wptrunner/wptmanifest/node.py
+./tools/wptrunner/wptrunner/wptmanifest/backends/static.py
+./tools/wptrunner/wptrunner/wptmanifest/backends/base.py
+./tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py
+./tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py
+./tools/wptrunner/wptrunner/wptmanifest/serializer.py
+./tools/wptrunner/wptrunner/wptmanifest/__init__.py
+./tools/wptrunner/wptrunner/wptmanifest/parser.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py
+./tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py
+./tools/wptrunner/wptrunner/__init__.py
+./tools/wptrunner/wptrunner/testrunner.py
+./tools/wptrunner/wptrunner/environment.py
+./tools/wptrunner/wptrunner/testdriver-extra.js
+./tools/wptrunner/wptrunner/testharnessreport.js
+./tools/wptrunner/wptrunner/instruments.py
+./tools/wptrunner/wptrunner/wptrunner.py
+./tools/wptrunner/wptrunner/testloader.py
+./tools/wptrunner/wptrunner/update/sync.py
+./tools/wptrunner/wptrunner/update/state.py
+./tools/wptrunner/wptrunner/update/metadata.py
+./tools/wptrunner/wptrunner/update/tree.py
+./tools/wptrunner/wptrunner/update/base.py
+./tools/wptrunner/wptrunner/update/__init__.py
+./tools/wptrunner/wptrunner/update/update.py
+./tools/wptrunner/wptrunner/process.py
+./tools/wptrunner/requirements_opera.txt
+./tools/wptrunner/requirements_android_webview.txt
+./tools/wptrunner/requirements_ie.txt
+./tools/wptrunner/requirements_edge_chromium.txt
+./tools/wptrunner/requirements_chrome_ios.txt
+./tools/wptrunner/requirements_webkit.txt
+./tools/wptrunner/requirements_sauce.txt
+./tools/wptrunner/setup.py
+./tools/wptrunner/README.rst
+./tools/wptrunner/MANIFEST.in
+./tools/wptrunner/requirements_safari.txt
+./tools/wptrunner/requirements_servo.txt
+./tools/wptrunner/requirements_edge.txt
 ./tools/wptserve/LICENSE
 ./tools/wptserve/README.md
 ./tools/wptserve/wptserve/__init__.py
@@ -187,5 +339,35 @@
 ./tools/wptserve/wptserve/utils.py
 ./tools/wptserve/wptserve/wptserve.py
 ./tools/wptserve/wptserve/ws_h2_handshake.py
+./websockets/handlers/basic_auth_wsh.py
+./websockets/handlers/delayed-passive-close_wsh.py
+./websockets/handlers/echo_close_data_wsh.py
+./websockets/handlers/echo-cookie_wsh.py
+./websockets/handlers/echo_exit_wsh.py
+./websockets/handlers/echo-query_v13_wsh.py
+./websockets/handlers/echo-query_wsh.py
+./websockets/handlers/echo_raw_wsh.py
+./websockets/handlers/echo_wsh.py
+./websockets/handlers/empty-message_wsh.py
+./websockets/handlers/handshake_no_extensions_wsh.py
+./websockets/handlers/handshake_no_protocol_wsh.py
+./websockets/handlers/handshake_protocol_wsh.py
+./websockets/handlers/handshake_sleep_2_wsh.py
+./websockets/handlers/invalid_wsh.py
+./websockets/handlers/origin_wsh.py
+./websockets/handlers/protocol_array_wsh.py
+./websockets/handlers/protocol_wsh.py
+./websockets/handlers/receive-backpressure_wsh.py
+./websockets/handlers/referrer_wsh.py
+./websockets/handlers/send-backpressure_wsh.py
+./websockets/handlers/set-cookie_http_wsh.py
+./websockets/handlers/set-cookie-secure_wsh.py
+./websockets/handlers/set-cookies-samesite_wsh.py
+./websockets/handlers/set-cookie_wsh.py
+./websockets/handlers/simple_handshake_wsh.py
+./websockets/handlers/sleep_10_v13_wsh.py
+./websockets/handlers/stash_responder_blocking_wsh.py
+./websockets/handlers/stash_responder_wsh.py
+./websockets/handlers/wrong_accept_key_wsh.py
 ./wpt
 ./wpt.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-actions.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-actions.js
new file mode 100644
index 0000000..4dafa0c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-actions.js
@@ -0,0 +1,570 @@
+(function() {
+  let sourceNameIdx = 0;
+
+  /**
+   * Builder for creating a sequence of actions
+   * The default tick duration is set to 16ms, which is one frame time based on
+   * 60Hz display.
+   */
+  function Actions(defaultTickDuration=16) {
+    this.sourceTypes = new Map([["key", KeySource],
+                                ["pointer", PointerSource],
+                                ["wheel", WheelSource],
+                                ["none", GeneralSource]]);
+    this.sources = new Map();
+    this.sourceOrder = [];
+    for (let sourceType of this.sourceTypes.keys()) {
+      this.sources.set(sourceType, new Map());
+    }
+    this.currentSources = new Map();
+    for (let sourceType of this.sourceTypes.keys()) {
+      this.currentSources.set(sourceType, null);
+    }
+    this.createSource("none");
+    this.tickIdx = 0;
+    this.defaultTickDuration = defaultTickDuration;
+    this.context = null;
+  }
+
+  Actions.prototype = {
+    ButtonType: {
+      LEFT: 0,
+      MIDDLE: 1,
+      RIGHT: 2,
+      BACK: 3,
+      FORWARD: 4,
+    },
+
+    /**
+     * Generate the action sequence suitable for passing to
+     * test_driver.action_sequence
+     *
+     * @returns {Array} Array of WebDriver-compatible actions sequences
+     */
+    serialize: function() {
+      let actions = [];
+      for (let [sourceType, sourceName] of this.sourceOrder) {
+        let source = this.sources.get(sourceType).get(sourceName);
+        let serialized = source.serialize(this.tickIdx + 1, this.defaultTickDuration);
+        if (serialized) {
+          serialized.id = sourceName;
+          actions.push(serialized);
+        }
+      }
+      return actions;
+    },
+
+    /**
+     * Generate and send the action sequence
+     *
+     * @returns {Promise} fulfilled after the sequence is executed,
+     *                    rejected if any actions fail.
+     */
+    send: function() {
+      let actions;
+      try {
+        actions = this.serialize();
+      } catch(e) {
+        return Promise.reject(e);
+      }
+      return test_driver.action_sequence(actions, this.context);
+    },
+
+    /**
+     * Set the context for the actions
+     *
+     * @param {WindowProxy} context - Context in which to run the action sequence
+     */
+    setContext: function(context) {
+      this.context = context;
+      return this;
+    },
+
+    /**
+     * Get the action source with a particular source type and name.
+     * If no name is passed, a new source with the given type is
+     * created.
+     *
+     * @param {String} type - Source type ('none', 'key', 'pointer', or 'wheel')
+     * @param {String?} name - Name of the source
+     * @returns {Source} Source object for that source.
+     */
+    getSource: function(type, name) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      if (name === null || name === undefined) {
+        name = this.currentSources.get(type);
+      }
+      if (name === null || name === undefined) {
+        return this.createSource(type, null);
+      }
+      return this.sources.get(type).get(name);
+    },
+
+    setSource: function(type, name) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      if (!this.sources.get(type).has(name)) {
+        throw new Error(`${name} is not a valid source for ${type}`);
+      }
+      this.currentSources.set(type, name);
+      return this;
+    },
+
+    /**
+     * Add a new key input source with the given name
+     *
+     * @param {String} name - Name of the key source
+     * @param {Bool} set - Set source as the default key source
+     * @returns {Actions}
+     */
+    addKeyboard: function(name, set=true) {
+      this.createSource("key", name);
+      if (set) {
+        this.setKeyboard(name);
+      }
+      return this;
+    },
+
+    /**
+     * Set the current default key source
+     *
+     * @param {String} name - Name of the key source
+     * @returns {Actions}
+     */
+    setKeyboard: function(name) {
+      this.setSource("key", name);
+      return this;
+    },
+
+    /**
+     * Add a new pointer input source with the given name
+     *
+     * @param {String} type - Name of the pointer source
+     * @param {String} pointerType - Type of pointing device
+     * @param {Bool} set - Set source as the default pointer source
+     * @returns {Actions}
+     */
+    addPointer: function(name, pointerType="mouse", set=true) {
+      this.createSource("pointer", name, {pointerType: pointerType});
+      if (set) {
+        this.setPointer(name);
+      }
+      return this;
+    },
+
+    /**
+     * Set the current default pointer source
+     *
+     * @param {String} name - Name of the pointer source
+     * @returns {Actions}
+     */
+    setPointer: function(name) {
+      this.setSource("pointer", name);
+      return this;
+    },
+
+    /**
+     * Add a new wheel input source with the given name
+     *
+     * @param {String} type - Name of the wheel source
+     * @param {Bool} set - Set source as the default wheel source
+     * @returns {Actions}
+     */
+    addWheel: function(name, set=true) {
+      this.createSource("wheel", name);
+      if (set) {
+        this.setWheel(name);
+      }
+      return this;
+    },
+
+    /**
+     * Set the current default wheel source
+     *
+     * @param {String} name - Name of the wheel source
+     * @returns {Actions}
+     */
+    setWheel: function(name) {
+      this.setSource("wheel", name);
+      return this;
+    },
+
+    createSource: function(type, name, parameters={}) {
+      if (!this.sources.has(type)) {
+        throw new Error(`${type} is not a valid action type`);
+      }
+      let sourceNames = new Set();
+      for (let [_, name] of this.sourceOrder) {
+        sourceNames.add(name);
+      }
+      if (!name) {
+        do {
+          name = "" + sourceNameIdx++;
+        } while (sourceNames.has(name))
+      } else {
+        if (sourceNames.has(name)) {
+          throw new Error(`Alreay have a source of type ${type} named ${name}.`);
+        }
+      }
+      this.sources.get(type).set(name, new (this.sourceTypes.get(type))(parameters));
+      this.currentSources.set(type, name);
+      this.sourceOrder.push([type, name]);
+      return this.sources.get(type).get(name);
+    },
+
+    /**
+     * Insert a new actions tick
+     *
+     * @param {Number?} duration - Minimum length of the tick in ms.
+     * @returns {Actions}
+     */
+    addTick: function(duration) {
+      this.tickIdx += 1;
+      if (duration) {
+        this.pause(duration);
+      }
+      return this;
+    },
+
+    /**
+     * Add a pause to the current tick
+     *
+     * @param {Number?} duration - Minimum length of the tick in ms.
+     * @param {String} sourceType - source type
+     * @param {String?} sourceName - Named key, pointer or wheel source to use
+     *                               or null for the default key, pointer or
+     *                               wheel source
+     * @returns {Actions}
+     */
+    pause: function(duration=0, sourceType="none", {sourceName=null}={}) {
+      if (sourceType=="none")
+        this.getSource("none").addPause(this, duration);
+      else
+        this.getSource(sourceType, sourceName).addPause(this, duration);
+      return this;
+    },
+
+    /**
+     * Create a keyDown event for the current default key source
+     *
+     * @param {String} key - Key to press
+     * @param {String?} sourceName - Named key source to use or null for the default key source
+     * @returns {Actions}
+     */
+    keyDown: function(key, {sourceName=null}={}) {
+      let source = this.getSource("key", sourceName);
+      source.keyDown(this, key);
+      return this;
+    },
+
+    /**
+     * Create a keyDown event for the current default key source
+     *
+     * @param {String} key - Key to release
+     * @param {String?} sourceName - Named key source to use or null for the default key source
+     * @returns {Actions}
+     */
+    keyUp: function(key, {sourceName=null}={}) {
+      let source = this.getSource("key", sourceName);
+      source.keyUp(this, key);
+      return this;
+    },
+
+    /**
+     * Create a pointerDown event for the current default pointer source
+     *
+     * @param {String} button - Button to press
+     * @param {String?} sourceName - Named pointer source to use or null for the default
+     *                               pointer source
+     * @returns {Actions}
+     */
+    pointerDown: function({button=this.ButtonType.LEFT, sourceName=null,
+                           width, height, pressure, tangentialPressure,
+                           tiltX, tiltY, twist, altitudeAngle, azimuthAngle}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerDown(this, button, width, height, pressure, tangentialPressure,
+                         tiltX, tiltY, twist, altitudeAngle, azimuthAngle);
+      return this;
+    },
+
+    /**
+     * Create a pointerUp event for the current default pointer source
+     *
+     * @param {String} button - Button to release
+     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
+     *                               source
+     * @returns {Actions}
+     */
+    pointerUp: function({button=this.ButtonType.LEFT, sourceName=null}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerUp(this, button);
+      return this;
+    },
+
+    /**
+     * Create a move event for the current default pointer source
+     *
+     * @param {Number} x - Destination x coordinate
+     * @param {Number} y - Destination y coordinate
+     * @param {String|Element} origin - Origin of the coordinate system.
+     *                                  Either "pointer", "viewport" or an Element
+     * @param {Number?} duration - Time in ms for the move
+     * @param {String?} sourceName - Named pointer source to use or null for the default pointer
+     *                               source
+     * @returns {Actions}
+     */
+    pointerMove: function(x, y,
+                          {origin="viewport", duration, sourceName=null,
+                           width, height, pressure, tangentialPressure,
+                           tiltX, tiltY, twist, altitudeAngle, azimuthAngle}={}) {
+      let source = this.getSource("pointer", sourceName);
+      source.pointerMove(this, x, y, duration, origin, width, height, pressure,
+                         tangentialPressure, tiltX, tiltY, twist, altitudeAngle,
+                         azimuthAngle);
+      return this;
+    },
+
+    /**
+     * Create a scroll event for the current default wheel source
+     *
+     * @param {Number} x - mouse cursor x coordinate
+     * @param {Number} y - mouse cursor y coordinate
+     * @param {Number} deltaX - scroll delta value along the x-axis in pixels
+     * @param {Number} deltaY - scroll delta value along the y-axis in pixels
+     * @param {String|Element} origin - Origin of the coordinate system.
+     *                                  Either "viewport" or an Element
+     * @param {Number?} duration - Time in ms for the scroll
+     * @param {String?} sourceName - Named wheel source to use or null for the
+     *                               default wheel source
+     * @returns {Actions}
+     */
+    scroll: function(x, y, deltaX, deltaY,
+                     {origin="viewport", duration, sourceName=null}={}) {
+      let source = this.getSource("wheel", sourceName);
+      source.scroll(this, x, y, deltaX, deltaY, duration, origin);
+      return this;
+    },
+  };
+
+  function GeneralSource() {
+    this.actions = new Map();
+  }
+
+  GeneralSource.prototype = {
+    serialize: function(tickCount, defaultTickDuration) {
+      let actions = [];
+      let data = {"type": "none", "actions": actions};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause", duration: defaultTickDuration});
+        }
+      }
+      return data;
+    },
+
+    addPause: function(actions, duration) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        throw new Error(`Already have a pause action for the current tick`);
+      }
+      this.actions.set(tick, {type: "pause", duration: duration});
+    },
+  };
+
+  function KeySource() {
+    this.actions = new Map();
+  }
+
+  KeySource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "key", "actions": actions};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    keyDown: function(actions, key) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "keyDown", value: key});
+    },
+
+    keyUp: function(actions, key) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "keyUp", value: key});
+    },
+
+    addPause: function(actions, duration) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pause", duration: duration});
+    },
+  };
+
+  function PointerSource(parameters={pointerType: "mouse"}) {
+    let pointerType = parameters.pointerType || "mouse";
+    if (!["mouse", "pen", "touch"].includes(pointerType)) {
+      throw new Error(`Invalid pointerType ${pointerType}`);
+    }
+    this.type = pointerType;
+    this.actions = new Map();
+  }
+
+  function setPointerProperties(action, width, height, pressure, tangentialPressure,
+                                tiltX, tiltY, twist, altitudeAngle, azimuthAngle) {
+    if (width) {
+      action.width = width;
+    }
+    if (height) {
+      action.height = height;
+    }
+    if (pressure) {
+      action.pressure = pressure;
+    }
+    if (tangentialPressure) {
+      action.tangentialPressure = tangentialPressure;
+    }
+    if (tiltX) {
+      action.tiltX = tiltX;
+    }
+    if (tiltY) {
+      action.tiltY = tiltY;
+    }
+    if (twist) {
+      action.twist = twist;
+    }
+    if (altitudeAngle) {
+      action.altitudeAngle = altitudeAngle;
+    }
+    if (azimuthAngle) {
+      action.azimuthAngle = azimuthAngle;
+    }
+    return action;
+  }
+
+  PointerSource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "pointer", "actions": actions, "parameters": {"pointerType": this.type}};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    pointerDown: function(actions, button, width, height, pressure, tangentialPressure,
+                          tiltX, tiltY, twist, altitudeAngle, azimuthAngle) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      let actionProperties = setPointerProperties({type: "pointerDown", button}, width, height,
+                                                  pressure, tangentialPressure, tiltX, tiltY,
+                                                  twist, altitudeAngle, azimuthAngle);
+      this.actions.set(tick, actionProperties);
+    },
+
+    pointerUp: function(actions, button) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pointerUp", button});
+    },
+
+    pointerMove: function(actions, x, y, duration, origin, width, height, pressure,
+                          tangentialPressure, tiltX, tiltY, twist, altitudeAngle, azimuthAngle) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      let moveAction = {type: "pointerMove", x, y, origin};
+      if (duration) {
+        moveAction.duration = duration;
+      }
+      let actionProperties = setPointerProperties(moveAction, width, height, pressure,
+                                                  tangentialPressure, tiltX, tiltY, twist,
+                                                  altitudeAngle, azimuthAngle);
+      this.actions.set(tick, actionProperties);
+    },
+
+    addPause: function(actions, duration) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pause", duration: duration});
+    },
+  };
+
+  function WheelSource() {
+    this.actions = new Map();
+  }
+
+  WheelSource.prototype = {
+    serialize: function(tickCount) {
+      if (!this.actions.size) {
+        return undefined;
+      }
+      let actions = [];
+      let data = {"type": "wheel", "actions": actions};
+      for (let i=0; i<tickCount; i++) {
+        if (this.actions.has(i)) {
+          actions.push(this.actions.get(i));
+        } else {
+          actions.push({"type": "pause"});
+        }
+      }
+      return data;
+    },
+
+    scroll: function(actions, x, y, deltaX, deltaY, duration, origin) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "scroll", x, y, deltaX, deltaY, origin});
+      if (duration) {
+        this.actions.get(tick).duration = duration;
+      }
+    },
+
+    addPause: function(actions, duration) {
+      let tick = actions.tickIdx;
+      if (this.actions.has(tick)) {
+        tick = actions.addTick().tickIdx;
+      }
+      this.actions.set(tick, {type: "pause", duration: duration});
+    },
+  };
+
+  test_driver.Actions = Actions;
+})();
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js.headers b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js.headers
new file mode 100644
index 0000000..5e8f640
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver-vendor.js.headers
@@ -0,0 +1,2 @@
+Content-Type: text/javascript; charset=utf-8
+Cache-Control: max-age=3600
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js
new file mode 100644
index 0000000..f3cee98
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js
@@ -0,0 +1,564 @@
+(function() {
+    "use strict";
+    var idCounter = 0;
+    let testharness_context = null;
+
+    function getInViewCenterPoint(rect) {
+        var left = Math.max(0, rect.left);
+        var right = Math.min(window.innerWidth, rect.right);
+        var top = Math.max(0, rect.top);
+        var bottom = Math.min(window.innerHeight, rect.bottom);
+
+        var x = 0.5 * (left + right);
+        var y = 0.5 * (top + bottom);
+
+        return [x, y];
+    }
+
+    function getPointerInteractablePaintTree(element) {
+        let elementDocument = element.ownerDocument;
+        if (!elementDocument.contains(element)) {
+            return [];
+        }
+
+        var rectangles = element.getClientRects();
+
+        if (rectangles.length === 0) {
+            return [];
+        }
+
+        var centerPoint = getInViewCenterPoint(rectangles[0]);
+
+        if ("elementsFromPoint" in elementDocument) {
+            return elementDocument.elementsFromPoint(centerPoint[0], centerPoint[1]);
+        } else if ("msElementsFromPoint" in elementDocument) {
+            var rv = elementDocument.msElementsFromPoint(centerPoint[0], centerPoint[1]);
+            return Array.prototype.slice.call(rv ? rv : []);
+        } else {
+            throw new Error("document.elementsFromPoint unsupported");
+        }
+    }
+
+    function inView(element) {
+        var pointerInteractablePaintTree = getPointerInteractablePaintTree(element);
+        return pointerInteractablePaintTree.indexOf(element) !== -1;
+    }
+
+
+    /**
+     * @namespace
+     */
+    window.test_driver = {
+        /**
+         * Set the context in which testharness.js is loaded
+         *
+         * @param {WindowProxy} context - the window containing testharness.js
+         **/
+        set_test_context: function(context) {
+          if (window.test_driver_internal.set_test_context) {
+            window.test_driver_internal.set_test_context(context);
+          }
+          testharness_context = context;
+        },
+
+        /**
+         * postMessage to the context containing testharness.js
+         *
+         * @param {Object} msg - the data to POST
+         **/
+        message_test: function(msg) {
+            let target = testharness_context;
+            if (testharness_context === null) {
+                target = window;
+            }
+            target.postMessage(msg, "*");
+        },
+
+        /**
+         * Trigger user interaction in order to grant additional privileges to
+         * a provided function.
+         *
+         * https://html.spec.whatwg.org/#triggered-by-user-activation
+         *
+         * @param {String} intent - a description of the action which much be
+         *                          triggered by user interaction
+         * @param {Function} action - code requiring escalated privileges
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled following user interaction and
+         *                    execution of the provided `action` function;
+         *                    rejected if interaction fails or the provided
+         *                    function throws an error
+         */
+        bless: function(intent, action, context=null) {
+            let contextDocument = context ? context.document : document;
+            var button = contextDocument.createElement("button");
+            button.innerHTML = "This test requires user interaction.<br />" +
+                "Please click here to allow " + intent + ".";
+            button.id = "wpt-test-driver-bless-" + (idCounter += 1);
+            const elem = contextDocument.body || contextDocument.documentElement;
+            elem.appendChild(button);
+
+            let wait_click = new Promise(resolve => button.addEventListener("click", resolve));
+
+            return test_driver.click(button)
+                .then(wait_click)
+                .then(function() {
+                    button.remove();
+
+                    if (typeof action === "function") {
+                        return action();
+                    }
+                    return null;
+                });
+        },
+
+        /**
+         * Triggers a user-initiated click
+         *
+         * This matches the behaviour of the {@link
+         * https://w3c.github.io/webdriver/#element-click|WebDriver
+         * Element Click command}.
+         *
+         * @param {Element} element - element to be clicked
+         * @returns {Promise} fulfilled after click occurs, or rejected in
+         *                    the cases the WebDriver command errors
+         */
+        click: function(element) {
+            if (!inView(element)) {
+                element.scrollIntoView({behavior: "instant",
+                                        block: "end",
+                                        inline: "nearest"});
+            }
+
+            var pointerInteractablePaintTree = getPointerInteractablePaintTree(element);
+            if (pointerInteractablePaintTree.length === 0 ||
+                !element.contains(pointerInteractablePaintTree[0])) {
+                return Promise.reject(new Error("element click intercepted error"));
+            }
+
+            var rect = element.getClientRects()[0];
+            var centerPoint = getInViewCenterPoint(rect);
+            return window.test_driver_internal.click(element,
+                                                     {x: centerPoint[0],
+                                                      y: centerPoint[1]});
+        },
+
+        /**
+         * Deletes all cookies.
+         *
+         * This matches the behaviour of the {@link
+         * https://w3c.github.io/webdriver/#delete-all-cookies|WebDriver
+         * Delete All Cookies command}.
+         *
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after cookies are deleted, or rejected in
+         *                    the cases the WebDriver command errors
+         */
+        delete_all_cookies: function(context=null) {
+            return window.test_driver_internal.delete_all_cookies(context);
+        },
+
+        /**
+         * Send keys to an element
+         *
+         * This matches the behaviour of the {@link
+         * https://w3c.github.io/webdriver/#element-send-keys|WebDriver
+         * Send Keys command}.
+         *
+         * @param {Element} element - element to send keys to
+         * @param {String} keys - keys to send to the element
+         * @returns {Promise} fulfilled after keys are sent, or rejected in
+         *                    the cases the WebDriver command errors
+         */
+        send_keys: function(element, keys) {
+            if (!inView(element)) {
+                element.scrollIntoView({behavior: "instant",
+                                        block: "end",
+                                        inline: "nearest"});
+            }
+
+            var pointerInteractablePaintTree = getPointerInteractablePaintTree(element);
+            if (pointerInteractablePaintTree.length === 0 ||
+                !element.contains(pointerInteractablePaintTree[0])) {
+                return Promise.reject(new Error("element send_keys intercepted error"));
+            }
+
+            return window.test_driver_internal.send_keys(element, keys);
+        },
+
+        /**
+         * Freeze the current page
+         *
+         * The freeze function transitions the page from the HIDDEN state to
+         * the FROZEN state as described in {@link
+         * https://github.com/WICG/page-lifecycle/blob/master/README.md|Lifecycle API
+         * for Web Pages}
+         *
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the freeze request is sent, or rejected
+         *                    in case the WebDriver command errors
+         */
+        freeze: function(context=null) {
+            return window.test_driver_internal.freeze();
+        },
+
+        /**
+         * Send a sequence of actions
+         *
+         * This function sends a sequence of actions
+         * to perform. It is modeled after the behaviour of {@link
+         * https://w3c.github.io/webdriver/#actions|WebDriver Actions Command}
+         *
+         * @param {Array} actions - an array of actions. The format is the same as the actions
+         *                          property of the WebDriver command {@link
+         *                          https://w3c.github.io/webdriver/#perform-actions|Perform
+         *                          Actions} command. Each element is an object representing an
+         *                          input source and each input source itself has an actions
+         *                          property detailing the behaviour of that source at each timestep
+         *                          (or tick). Authors are not expected to construct the actions
+         *                          sequence by hand, but to use the builder api provided in
+         *                          testdriver-actions.js
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fufiled after the actions are performed, or rejected in
+         *                    the cases the WebDriver command errors
+         */
+        action_sequence: function(actions, context=null) {
+            return window.test_driver_internal.action_sequence(actions, context);
+        },
+
+        /**
+         * Generates a test report on the current page
+         *
+         * The generate_test_report function generates a report (to be observed
+         * by ReportingObserver) for testing purposes, as described in
+         * {@link https://w3c.github.io/reporting/#generate-test-report-command}
+         *
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the report is generated, or
+         *                    rejected if the report generation fails
+         */
+        generate_test_report: function(message, context=null) {
+            return window.test_driver_internal.generate_test_report(message, context);
+        },
+
+        /**
+         * Sets the state of a permission
+         *
+         * This function simulates a user setting a permission into a particular state as described
+         * in {@link https://w3c.github.io/permissions/#set-permission-command}
+         *
+         * @param {Object} descriptor - a [PermissionDescriptor]{@link
+         *                              https://w3c.github.io/permissions/#dictdef-permissiondescriptor}
+         *                              object
+         * @param {String} state - the state of the permission
+         * @param {boolean} one_realm - Optional. Whether the permission applies to only one realm
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * The above params are used to create a [PermissionSetParameters]{@link
+         * https://w3c.github.io/permissions/#dictdef-permissionsetparameters} object
+         *
+         * @returns {Promise} fulfilled after the permission is set, or rejected if setting the
+         *                    permission fails
+         */
+        set_permission: function(descriptor, state, one_realm, context=null) {
+            let permission_params = {
+              descriptor,
+              state,
+              oneRealm: one_realm,
+            };
+            return window.test_driver_internal.set_permission(permission_params, context);
+        },
+
+        /**
+         * Creates a virtual authenticator
+         *
+         * This function creates a virtual authenticator for use with the U2F
+         * and WebAuthn APIs as described in {@link
+         * https://w3c.github.io/webauthn/#sctn-automation-add-virtual-authenticator}
+         *
+         * @param {Object} config - an [Authenticator Configuration]{@link
+         *                          https://w3c.github.io/webauthn/#authenticator-configuration}
+         *                          object
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the authenticator is added, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors. Returns the ID of the authenticator
+         */
+        add_virtual_authenticator: function(config, context=null) {
+            return window.test_driver_internal.add_virtual_authenticator(config, context);
+        },
+
+        /**
+         * Removes a virtual authenticator
+         *
+         * This function removes a virtual authenticator that has been created
+         * by add_virtual_authenticator
+         * https://w3c.github.io/webauthn/#sctn-automation-remove-virtual-authenticator
+         *
+         * @param {String} authenticator_id - the ID of the authenticator to be
+         *                                    removed.
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the authenticator is removed, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors
+         */
+        remove_virtual_authenticator: function(authenticator_id, context=null) {
+            return window.test_driver_internal.remove_virtual_authenticator(authenticator_id, context);
+        },
+
+        /**
+         * Adds a credential to a virtual authenticator
+         *
+         * https://w3c.github.io/webauthn/#sctn-automation-add-credential
+         *
+         * @param {String} authenticator_id - the ID of the authenticator
+         * @param {Object} credential - A [Credential Parameters]{@link
+         *                              https://w3c.github.io/webauthn/#credential-parameters}
+         *                              object
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the credential is added, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors
+         */
+        add_credential: function(authenticator_id, credential, context=null) {
+            return window.test_driver_internal.add_credential(authenticator_id, credential, context);
+        },
+
+        /**
+         * Gets all the credentials stored in an authenticator
+         *
+         * This function retrieves all the credentials (added via the U2F API,
+         * WebAuthn, or the add_credential function) stored in a virtual
+         * authenticator
+         * https://w3c.github.io/webauthn/#sctn-automation-get-credentials
+         *
+         * @param {String} authenticator_id - the ID of the authenticator
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the credentials are returned, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors. Returns an array of [Credential
+         *                    Parameters]{@link
+         *                    https://w3c.github.io/webauthn/#credential-parameters}
+         */
+        get_credentials: function(authenticator_id, context=null) {
+            return window.test_driver_internal.get_credentials(authenticator_id, context=null);
+        },
+
+        /**
+         * Remove a credential stored in an authenticator
+         *
+         * https://w3c.github.io/webauthn/#sctn-automation-remove-credential
+         *
+         * @param {String} authenticator_id - the ID of the authenticator
+         * @param {String} credential_id - the ID of the credential
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the credential is removed, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors.
+         */
+        remove_credential: function(authenticator_id, credential_id, context=null) {
+            return window.test_driver_internal.remove_credential(authenticator_id, credential_id, context);
+        },
+
+        /**
+         * Removes all the credentials stored in a virtual authenticator
+         *
+         * https://w3c.github.io/webauthn/#sctn-automation-remove-all-credentials
+         *
+         * @param {String} authenticator_id - the ID of the authenticator
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} fulfilled after the credentials are removed, or
+         *                    rejected in the cases the WebDriver command
+         *                    errors.
+         */
+        remove_all_credentials: function(authenticator_id, context=null) {
+            return window.test_driver_internal.remove_all_credentials(authenticator_id, context);
+        },
+
+        /**
+         * Sets the User Verified flag on an authenticator
+         *
+         * Sets whether requests requiring user verification will succeed or
+         * fail on a given virtual authenticator
+         * https://w3c.github.io/webauthn/#sctn-automation-set-user-verified
+         *
+         * @param {String} authenticator_id - the ID of the authenticator
+         * @param {boolean} uv - the User Verified flag
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         */
+        set_user_verified: function(authenticator_id, uv, context=null) {
+            return window.test_driver_internal.set_user_verified(authenticator_id, uv, context);
+        },
+
+        /**
+         * Sets the storage access rule for an origin when embedded
+         * in a third-party context.
+         *
+         * {@link https://privacycg.github.io/storage-access/#set-storage-access-command}
+         *
+         * @param {String} origin - A third-party origin to block or allow.
+         *                          May be "*" to indicate all origins.
+         * @param {String} embedding_origin - an embedding (first-party) origin
+         *                                    on which {origin}'s access should
+         *                                    be blocked or allowed.
+         *                                    May be "*" to indicate all origins.
+         * @param {String} state - The storage access setting.
+         *                         Must be either "allowed" or "blocked".
+         * @param {WindowProxy} context - Browsing context in which
+         *                                to run the call, or null for the current
+         *                                browsing context.
+         *
+         * @returns {Promise} Fulfilled after the storage access rule has been
+         *                    set, or rejected if setting the rule fails.
+         */
+        set_storage_access: function(origin, embedding_origin, state, context=null) {
+            if (state !== "allowed" && state !== "blocked") {
+                throw new Error("storage access status must be 'allowed' or 'blocked'");
+            }
+            const blocked = state === "blocked";
+            return window.test_driver_internal.set_storage_access(origin, embedding_origin, blocked, context);
+        },
+    };
+
+    window.test_driver_internal = {
+        /**
+         * This flag should be set to `true` by any code which implements the
+         * internal methods defined below for automation purposes. Doing so
+         * allows the library to signal failure immediately when an automated
+         * implementation of one of the methods is not available.
+         */
+        in_automation: false,
+
+        click: function(element, coords) {
+            if (this.in_automation) {
+                return Promise.reject(new Error('Not implemented'));
+            }
+
+            return new Promise(function(resolve, reject) {
+                element.addEventListener("click", resolve);
+            });
+        },
+
+        delete_all_cookies: function(context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        send_keys: function(element, keys) {
+            if (this.in_automation) {
+                return Promise.reject(new Error('Not implemented'));
+            }
+
+            return new Promise(function(resolve, reject) {
+                var seen = "";
+
+                function remove() {
+                    element.removeEventListener("keydown", onKeyDown);
+                }
+
+                function onKeyDown(event) {
+                    if (event.key.length > 1) {
+                        return;
+                    }
+
+                    seen += event.key;
+
+                    if (keys.indexOf(seen) !== 0) {
+                        reject(new Error("Unexpected key sequence: " + seen));
+                        remove();
+                    } else if (seen === keys) {
+                        resolve();
+                        remove();
+                    }
+                }
+
+                element.addEventListener("keydown", onKeyDown);
+            });
+        },
+
+        freeze: function(context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        action_sequence: function(actions, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        generate_test_report: function(message, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+
+        set_permission: function(permission_params, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        add_virtual_authenticator: function(config, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        remove_virtual_authenticator: function(authenticator_id, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        add_credential: function(authenticator_id, credential, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        get_credentials: function(authenticator_id, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        remove_credential: function(authenticator_id, credential_id, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        remove_all_credentials: function(authenticator_id, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        set_user_verified: function(authenticator_id, uv, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+
+        set_storage_access: function(origin, embedding_origin, blocked, context=null) {
+            return Promise.reject(new Error("unimplemented"));
+        },
+    };
+})();
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js.headers b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js.headers
new file mode 100644
index 0000000..5e8f640
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/resources/testdriver.js.headers
@@ -0,0 +1,2 @@
+Content-Type: text/javascript; charset=utf-8
+Cache-Control: max-age=3600
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/README.md b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/README.md
new file mode 100644
index 0000000..fd75c22
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/README.md
@@ -0,0 +1,81 @@
+# WPT Test Certificates
+
+The web-platform-tests project maintains a set of SSL certificates to allow
+contributors to execute tests requiring HTTPS locally.
+
+## Trusting Root CA
+
+To prevent browser SSL warnings when running HTTPS tests locally, the
+web-platform-tests Root CA file `cacert.pem` in the `tools/certs/` directory
+must be added as a trusted certificate in your OS/browser.
+
+For Firefox, go to about:preferences and search for "certificates".
+
+For browsers that use the Certificate Authorities of the underlying OS, such as
+Chrome and Safari, you need to adjust the OS. For macOS, go to Keychain Access
+and add the certificate under **login**.
+
+**NOTE**: The CA should not be installed in any browser profile used
+outside of tests, since it may be used to generate fake
+certificates. For browsers that use the OS certificate store, tests
+should therefore not be run manually outside a dedicated OS instance
+(e.g. a VM). To avoid this problem when running tests in Chrome or
+Firefox, use `wpt run`, which disables certificate checks and therefore
+doesn't require the root CA to be trusted.
+
+## Regenerating certificates
+
+If you wish to generate new certificates for any reason, it's possible to use
+OpenSSL when starting the server, or starting a test run, by providing the
+`--ssl-type=openssl` argument to the `wpt serve` or `wpt run` commands.
+
+If you installed OpenSSL in such a way that running `openssl` at a
+command line doesn't work, you also need to adjust the path to the
+OpenSSL binary. This can be done by adding a section to `config.json`
+like:
+
+```
+"ssl": {"openssl": {"binary": "/path/to/openssl"}}
+```
+
+On Windows using OpenSSL typically requires installing an OpenSSL distribution.
+[Shining Light](https://slproweb.com/products/Win32OpenSSL.html)
+provide a convenient installer that is known to work, but requires a
+little extra setup, i.e.:
+
+Run the installer for Win32_OpenSSL_v1.1.0b (30MB). During installation,
+change the default location for where to Copy OpenSSL Dlls from the
+System directory to the /bin directory.
+
+After installation, ensure that the path to OpenSSL (typically,
+this will be `C:\OpenSSL-Win32\bin`) is in your `%Path%`
+[Environment Variable](http://www.computerhope.com/issues/ch000549.htm).
+If you forget to do this part, you will most likely see a 'File Not Found'
+error when you start wptserve.
+
+Finally, set the path value in the server configuration file to the
+default OpenSSL configuration file location. To do this, create a file
+called `config.json`.  Then add the OpenSSL configuration below,
+ensuring that the key `ssl/openssl/base_conf_path` has a value that is
+the path to the OpenSSL config file (typically this will be
+`C:\\OpenSSL-Win32\\bin\\openssl.cfg`):
+
+```
+{
+  "ssl": {
+    "type": "openssl",
+    "encrypt_after_connect": false,
+    "openssl": {
+      "openssl_binary": "openssl",
+      "base_path: "_certs",
+      "force_regenerate": false,
+      "base_conf_path": "C:\\OpenSSL-Win32\\bin\\openssl.cfg"
+    },
+  },
+}
+```
+
+### Regenerating the pregenerated certificates
+
+From the root, run `./wpt serve --config tools/certs/config.json` and terminate
+it after it has started up.
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.key b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.key
new file mode 100644
index 0000000..1df8d73
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.key
@@ -0,0 +1,30 @@
+-----BEGIN ENCRYPTED PRIVATE KEY-----
+MIIFHDBOBgkqhkiG9w0BBQ0wQTApBgkqhkiG9w0BBQwwHAQILrnX+IA5B7wCAggA
+MAwGCCqGSIb3DQIJBQAwFAYIKoZIhvcNAwcECEtP+3jaoEqkBIIEyAkS32MWcijR
+TWp8Y1SEM5Gos2WvaSVMZy8vURNeE23+YR2lD1zJbYy3c1vHWheK6VKHaH9NGkvK
+2D6rIsQwnE/O6gfZRxWb2hDRMXQDksAVH7igGfX+WkHoBwHyxrDb8juG/xWsFIr5
+W63AH6N8XR+N+m97uWIATpbcbhAkRaBOxELmHhDaMvQdvFqwhjewUqS3RrC947Kb
+4NcvG9kKGxI6UPWMErw0WWmVYsBc/8+gn1866Qef0IlxDqJdqRFhKspCZGBCj2EX
+CLrvM8+6NbI/5miTmjRsaBj7iTX9hvL46vVQt401E6V0V2vLI+oYuNrmD1fV75a6
+l8I9xhzaEjSIZ1t40yry8DukZN3EwM0oPzfP8WdKenof0rObaDiBYCqmyO+Re+n0
+QklgCK+pYfdGaEYhbIkyktfgZvWEw1+8t3jXEEG96lTIosl0WznD/teSpGnCtyme
+/KsLGCOYpUqyiKLgM3+aLiP0hVWAvFVT015gwQfdzyd0nXc4x8Q/Xz8jYL/t2TFM
+7tT9diQoaiJ12/ug8UZ3NQVgm8Ibk0Bu3pNUv1StFgyrY5XdP3FIMQWgU4p6+oj0
+cY5b62Wrw5XQoIrnkTG//lqAOeMTSFxvlu62RoC4y7ji7u1PQnzRjbMd7j42tqVA
+Xn+l9EJvqkynefYytIMsWw+uYAtUeBw8783R9j+Ldy6lvnk/CdnSqymZ7E+WF6bp
+54nWYsM6bv1y+T6gK6dYm9RUqfrgggsdNHC0GxsTwUmpHVERSAKdZb81xt5KCuM2
+waOxUYAY1Mp5OzvAGfeSstagdWQ0ExsAGw5BAZvuiS9b3x0RqnFoEyQwAv90ON1H
+Eb3E4w/eQsAu+SA5aUD/Yr1lt+hcKJ5EdvXHrLIl8ck4NYwxk0spZsbSceq0JekG
+obscmp5xyiA0/v9PJHVrmoNWFyy6GO8J/ZZztU/kTGajcXIO8P4ygLbh+Gr0gI5c
+sE0sIR/3Q61tiLMbWKxx+rwsptfYBdQyGCgvDbg3fNUxYmblFj6MyM8T3q7A1mcX
+0y7dGHr8n+a2IdJ8+ZTqZXuJh1AwHyUht1YzccXy6TvGPVuJgDuRp6zvs0w+D4Oe
+ddPUVs1P8wj4QhRes1dnuyTBUNokfoznHvKsGX8AH9eN+UOQ3TkwjDRe5pxtJ2XX
+HL3XeCVXt3Bxu3unZ6nisUHHt1a4jckS7gwkChWObyfGEq34J95W771Kw2cxeyDU
+pWz6Rt1jYGTioT1sIL2Z8m0Ru5n8SsMOysQkF1BXM9bmc8iB+lDNoi83G2Kgk6DN
+/vDMPhI894TL58BH/wx3PSMiiUA4eR+PjDltT5UC+qlhDiC6WEoSt/hhtrg7DgFb
+mPes42/B8T7CdmUD2HUUR+XsChBQhAQrcuzqMcS6Zq6KARgMaCzT3cYFA5C/LiUZ
+TyGmYpCBggkcpoKCVgUC9EmQ3FRC9nXCWnlDUJRM0sd3kluYGrQBo+wVzb+6JMvV
+JOESa/7t827YRvlYS8RCDihSgX1G4T/4napL3YCxPrFOmdCQYDovVaUA3qdlpxP+
+MQHsGiF9joIMKdfFjCKa2ryInMaR0lmv7y/Zs9EMWg8O6BQF+NQobJuwU5sKlegx
+8Lo4YqfmCdNAzsSJ6rhC1A==
+-----END ENCRYPTED PRIVATE KEY-----
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.pem b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.pem
new file mode 100644
index 0000000..b30adfa
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/cacert.pem
@@ -0,0 +1,347 @@
+-----BEGIN CERTIFICATE-----
+MIJAhzCCP2+gAwIBAgIDBPWrMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMDEyMTIwMDI4MjdaFw0yMTEyMTIwMDI4Mjda
+MB0xGzAZBgNVBAMMEndlYi1wbGF0Zm9ybS10ZXN0czCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBALyIJvebVlTCq1p3h+cow7sp3qjhVJQASg+v7huHucEG
+eoq11qbpaJ9WkeHxYO6PjpIHegpogvqKXmkV02BMqt+5ULEWIYpaz4VHiEH4E8Wc
+zZXYSDFDC40zDLjrzt1+BZYlMpBTeSRj7WLkD/Qhb6ZozAzDJhoJRpEkmQZ0t14s
+55feXzm87ZOiEm2d2B33JPpWhw+tusLufcGoz4D4e9tNOtXPdus/QpXRdsdoy53L
+WI8GRPfJKrhQ1gXnBXTcDJpXDPqk8JMsciYL+63MiVOZ93v4dD3uueK5Lsn/krVV
+Eoivkz1ONiXVgI1oQMJO7eFylka85fikC7r316ZCcJ0CAwEAAaOCPc4wgj3KMAwG
+A1UdEwQFMAMBAf8wHQYDVR0OBBYEFKepXnGpqWQbsgOM0WPj+KHQtRpoMEcGA1Ud
+IwRAMD6AFKepXnGpqWQbsgOM0WPj+KHQtRpooSGkHzAdMRswGQYDVQQDDBJ3ZWIt
+cGxhdGZvcm0tdGVzdHOCAwT1qzALBgNVHQ8EBAMCAgQwgh+bBgNVHR4Egh+SMIIf
+jqCCH4owE4IRd2ViLXBsYXRmb3JtLnRlc3QwF4IVb3A4LndlYi1wbGF0Zm9ybS50
+ZXN0MBeCFW9wNy53ZWItcGxhdGZvcm0udGVzdDAXghVvcDkud2ViLXBsYXRmb3Jt
+LnRlc3QwF4IVb3A0LndlYi1wbGF0Zm9ybS50ZXN0MBeCFW5vdC13ZWItcGxhdGZv
+cm0udGVzdDAXghVvcDYud2ViLXBsYXRmb3JtLnRlc3QwF4IVb3AzLndlYi1wbGF0
+Zm9ybS50ZXN0MBeCFW9wMi53ZWItcGxhdGZvcm0udGVzdDAXghVvcDEud2ViLXBs
+YXRmb3JtLnRlc3QwF4IVd3d3LndlYi1wbGF0Zm9ybS50ZXN0MBeCFW9wNS53ZWIt
+cGxhdGZvcm0udGVzdDAYghZvcDg4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTgu
+d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdDAYghZv
+cDg5LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjYud2ViLXBsYXRmb3JtLnRlc3Qw
+GIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDI0LndlYi1wbGF0Zm9ybS50
+ZXN0MBiCFm9wNDEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A3OS53ZWItcGxhdGZv
+cm0udGVzdDAYghZvcDkxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTkud2ViLXBs
+YXRmb3JtLnRlc3QwGIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDYwLndl
+Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTgud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3Ay
+OC53ZWItcGxhdGZvcm0udGVzdDAYghZ3d3cxLndlYi1wbGF0Zm9ybS50ZXN0MBiC
+Fm9wMTQud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2OS53ZWItcGxhdGZvcm0udGVz
+dDAYghZvcDQwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNzQud2ViLXBsYXRmb3Jt
+LnRlc3QwGIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE4LndlYi1wbGF0
+Zm9ybS50ZXN0MBiCFm9wNzMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A3Ny53ZWIt
+cGxhdGZvcm0udGVzdDAYghZvcDEyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNTQu
+d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2My53ZWItcGxhdGZvcm0udGVzdDAYghZv
+cDcxLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTUud2ViLXBsYXRmb3JtLnRlc3Qw
+GIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM2LndlYi1wbGF0Zm9ybS50
+ZXN0MBiCFm9wMjcud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyOS53ZWItcGxhdGZv
+cm0udGVzdDAYghZvcDk0LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDQud2ViLXBs
+YXRmb3JtLnRlc3QwGIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdDAYghZvcDg0Lndl
+Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2
+MS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDcwLndlYi1wbGF0Zm9ybS50ZXN0MBiC
+Fnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0My53ZWItcGxhdGZvcm0udGVz
+dDAYghZvcDc4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjYud2ViLXBsYXRmb3Jt
+LnRlc3QwGIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdDAYghZvcDUyLndlYi1wbGF0
+Zm9ybS50ZXN0MBiCFm9wOTkud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4Ni53ZWIt
+cGxhdGZvcm0udGVzdDAYghZvcDQ2LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTcu
+d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdDAYghZv
+cDkzLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMTAud2ViLXBsYXRmb3JtLnRlc3Qw
+GIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDQ3LndlYi1wbGF0Zm9ybS50
+ZXN0MBiCFm9wNTEud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A0NS53ZWItcGxhdGZv
+cm0udGVzdDAYghZvcDgwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjgud2ViLXBs
+YXRmb3JtLnRlc3QwGIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdDAYghZvcDU3Lndl
+Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2
+Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDkyLndlYi1wbGF0Zm9ybS50ZXN0MBiC
+Fm9wMTUud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxMy53ZWItcGxhdGZvcm0udGVz
+dDAYghZvcDc1LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNjQud2ViLXBsYXRmb3Jt
+LnRlc3QwGIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDM3LndlYi1wbGF0
+Zm9ybS50ZXN0MBiCFm9wNTYud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A2Mi53ZWIt
+cGxhdGZvcm0udGVzdDAYghZvcDgyLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMjUu
+d2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdDAYghZv
+cDUwLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzgud2ViLXBsYXRmb3JtLnRlc3Qw
+GIIWb3A4My53ZWItcGxhdGZvcm0udGVzdDAYghZvcDgxLndlYi1wbGF0Zm9ybS50
+ZXN0MBiCFm9wMjAud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AyMS53ZWItcGxhdGZv
+cm0udGVzdDAYghZvcDIzLndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wNDIud2ViLXBs
+YXRmb3JtLnRlc3QwGIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdDAYghZvcDY1Lndl
+Yi1wbGF0Zm9ybS50ZXN0MBiCFm9wOTYud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3A4
+Ny53ZWItcGxhdGZvcm0udGVzdDAYghZvcDE5LndlYi1wbGF0Zm9ybS50ZXN0MBiC
+Fm9wNTMud2ViLXBsYXRmb3JtLnRlc3QwGIIWb3AzMC53ZWItcGxhdGZvcm0udGVz
+dDAYghZvcDQ4LndlYi1wbGF0Zm9ybS50ZXN0MBiCFm9wMzQud2ViLXBsYXRmb3Jt
+LnRlc3QwG4IZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghlvcDMubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MBuCGW9wMi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZ
+b3A1Lm5vdC13ZWItcGxhdGZvcm0udGVzdDAbghl3d3cubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MBuCGXd3dy53d3cud2ViLXBsYXRmb3JtLnRlc3QwG4IZb3A3Lm5vdC13
+ZWItcGxhdGZvcm0udGVzdDAbghlvcDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MBuC
+GW9wOC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwG4IZb3A5Lm5vdC13ZWItcGxhdGZv
+cm0udGVzdDAbghlvcDEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzYubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjQubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+OTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODMubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzMubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wNzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+Nzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDAubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjUubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cyLndlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wODAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTIubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wNjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+NDUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzEubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wNzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTAubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNDkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzcubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+ODIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dy53d3cxLndlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzkubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDQubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTgubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wMTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+MzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjIubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wNjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTIubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wOTgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjQubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wMjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+MjIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTQubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzMubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTQubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+NDYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTcubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjAubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDEubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wMzUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+OTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDIubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wNjcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMzcubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDgubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTYubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wODQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+MzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNjkubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTMubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wODYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTMubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+NzYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMjcubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNzUubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTUubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNDcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTgubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wNjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+Mjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNDMubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wNjYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGnd3dzIud3d3
+LndlYi1wbGF0Zm9ybS50ZXN0MByCGm9wOTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0
+MByCGm9wNzQubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wNTkubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0MByCGm9wODgubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9w
+ODcubm90LXdlYi1wbGF0Zm9ybS50ZXN0MByCGm9wMTAubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0MByCGm9wMTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3
+Mi53ZWItcGxhdGZvcm0udGVzdDAdght3d3cyLnd3dzIud2ViLXBsYXRmb3JtLnRl
+c3QwHYIbd3d3Mi53d3cxLndlYi1wbGF0Zm9ybS50ZXN0MB2CG3d3dzEud3d3MS53
+ZWItcGxhdGZvcm0udGVzdDAfgh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dDAggh54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3MS53d3cu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCCCHnd3dy53d3cyLm5vdC13ZWItcGxhdGZv
+cm0udGVzdDAggh53d3cyLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwIIIed3d3
+Lnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzIud3d3Mi5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3QwIYIfd3d3Mi53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVz
+dDAhgh93d3cxLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCGCH3d3dzEud3d3
+Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwJIIieG4tLWx2ZS02bGFkLnd3dy53ZWIt
+cGxhdGZvcm0udGVzdDAkgiJ4bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0MCSCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwJYIjd3d3
+Mi54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFk
+Lnd3dzIud2ViLXBsYXRmb3JtLnRlc3QwJYIjeG4tLWx2ZS02bGFkLnd3dzEud2Vi
+LXBsYXRmb3JtLnRlc3QwJYIjd3d3MS54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3Jt
+LnRlc3QwKIImeG4tLWx2ZS02bGFkLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
+KIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4t
+LWx2ZS02bGFkLnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MCmCJ3d3dzIueG4t
+LWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDApgid3d3cxLnhuLS1sdmUt
+NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwKYIneG4tLWx2ZS02bGFkLnd3dzIu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0MCuCKXhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh
+LndlYi1wbGF0Zm9ybS50ZXN0MC2CK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu
+d2ViLXBsYXRmb3JtLnRlc3QwL4Itd3d3LnhuLS1uOGo2ZHM1M2x3d2tycWh2Mjhh
+LndlYi1wbGF0Zm9ybS50ZXN0MC+CLXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLm5v
+dC13ZWItcGxhdGZvcm0udGVzdDAvgi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
+d3cud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3MS54bi0tbjhqNmRzNTNsd3drcnFo
+djI4YS53ZWItcGxhdGZvcm0udGVzdDAwgi54bi0tbjhqNmRzNTNsd3drcnFodjI4
+YS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0MDCCLnhuLS1uOGo2ZHM1M2x3d2tycWh2
+MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3QwMIIud3d3Mi54bi0tbjhqNmRzNTNs
+d3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDAxgi94bi0tbHZlLTZsYWQueG4t
+LWx2ZS02bGFkLm5vdC13ZWItcGxhdGZvcm0udGVzdDAzgjF3d3cueG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0MDOCMXhuLS1uOGo2
+ZHM1M2x3d2tycWh2MjhhLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwNIIyeG4t
+LW44ajZkczUzbHd3a3JxaHYyOGEud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3Qw
+NIIyd3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3QwNIIyd3d3Mi54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3QwNIIyeG4tLW44ajZkczUzbHd3a3JxaHYyOGEud3d3MS5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3QwOII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4t
+LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0MDiCNnhuLS1sdmUtNmxhZC54bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdDA8gjp4bi0tbjhq
+NmRzNTNsd3drcnFodjI4YS54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0MDyCOnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3QwQ4JBeG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4t
+LW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3QwR4JFeG4tLW44
+ajZkczUzbHd3a3JxaHYyOGEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0MBMGA1UdJQQMMAoGCCsGAQUFBwMBMIIdjwYDVR0RBIId
+hjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVvcDgud2ViLXBsYXRmb3JtLnRlc3SC
+FW9wNy53ZWItcGxhdGZvcm0udGVzdIIVb3A5LndlYi1wbGF0Zm9ybS50ZXN0ghVv
+cDQud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13ZWItcGxhdGZvcm0udGVzdIIVb3A2
+LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDMud2ViLXBsYXRmb3JtLnRlc3SCFW9wMi53
+ZWItcGxhdGZvcm0udGVzdIIVb3AxLndlYi1wbGF0Zm9ybS50ZXN0ghV3d3cud2Vi
+LXBsYXRmb3JtLnRlc3SCFW9wNS53ZWItcGxhdGZvcm0udGVzdIIWb3A4OC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxhdGZvcm0udGVzdIIWb3A4NS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ni53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxhdGZvcm0udGVzdIIWb3A3OS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxhdGZvcm0udGVzdIIWb3A1OS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxhdGZvcm0udGVzdIIWb3A2MC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxhdGZvcm0udGVzdIIWb3AyOC53ZWIt
+cGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxhdGZvcm0udGVzdIIWb3A0MC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AxOC53ZWItcGxhdGZvcm0udGVzdIIWb3A3My53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AxMi53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxhdGZvcm0udGVzdIIWb3A2My53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxhdGZvcm0udGVzdIIWb3A5NS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AxNi53ZWItcGxhdGZvcm0udGVzdIIWb3AzNi53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxhdGZvcm0udGVzdIIWb3AyOS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxhdGZvcm0udGVzdIIWb3A0NC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzMy53ZWItcGxhdGZvcm0udGVzdIIWb3A4NC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2MS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxhdGZvcm0udGVzdIIWd3d3Mi53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A0My53ZWItcGxhdGZvcm0udGVzdIIWb3A3OC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ni53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A5OS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ni53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxhdGZvcm0udGVzdIIWb3A5MC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxhdGZvcm0udGVzdIIWb3AxMC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxhdGZvcm0udGVzdIIWb3A0Ny53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxhdGZvcm0udGVzdIIWb3A0NS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ny53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxhdGZvcm0udGVzdIIWb3A2Ny53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AxNS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxhdGZvcm0udGVzdIIWb3A3NS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A2NC53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ny53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxhdGZvcm0udGVzdIIWb3A1Ni53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A4Mi53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxhdGZvcm0udGVzdIIWb3AzOC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A4My53ZWItcGxhdGZvcm0udGVzdIIWb3A4MS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxhdGZvcm0udGVzdIIWb3AyMS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxhdGZvcm0udGVzdIIWb3A0Mi53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AyMi53ZWItcGxhdGZvcm0udGVzdIIWb3A2NS53ZWIt
+cGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ny53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxhdGZvcm0udGVzdIIWb3A1My53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OC53ZWIt
+cGxhdGZvcm0udGVzdIIWb3AzNC53ZWItcGxhdGZvcm0udGVzdIIZb3A2Lm5vdC13
+ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3Ay
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lnd3dy53ZWItcGxhdGZv
+cm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A0Lm5vdC13ZWIt
+cGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A5Lm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTMubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDUwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNC5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDk1
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4My5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDczLm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3AxOS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzgubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDQwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNS5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wNjUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghp3d3cu
+d3d3Mi53ZWItcGxhdGZvcm0udGVzdIIab3A4MC5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDY4Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3A0NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3A5MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODkubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDQ5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3Ny5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wNzkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgy
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3Lnd3dzEud2ViLXBsYXRmb3JtLnRl
+c3SCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM5Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3A0NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3AxNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzAubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDYyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2MS5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wOTIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI5
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5OC5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wNjQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDI2Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3AyMi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTQubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3AzMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjMubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NC5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wODUubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ2
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Ny5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYwLm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3A5Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTkubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDQyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ny5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wMzcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ4
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1NS5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wNTYubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg0Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3AzNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjkubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDExLm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3A5My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzEud3d3LndlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDg2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxMy5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGm9wMjAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDc2
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyNy5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDc1Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3AxNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNDcubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIa
+b3A2My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjgubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0ghpvcDQzLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A2Ni5ub3Qtd2Vi
+LXBsYXRmb3JtLnRlc3SCGnd3dzIud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghpvcDkx
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3NC5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCGm9wNTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDg4Lm5vdC13ZWItcGxh
+dGZvcm0udGVzdIIab3A4Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTAubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIb
+d3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0ght3d3cyLnd3dzIud2ViLXBsYXRm
+b3JtLnRlc3SCG3d3dzIud3d3MS53ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cx
+LndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gh53d3cxLnd3dy5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCHnd3dy53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gh53d3cud3d3MS5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3MS5u
+b3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEud3d3Mi5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2ViLXBsYXRmb3JtLnRlc3SCInhuLS1s
+dmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInd3dy54bi0tbHZlLTZsYWQu
+d2ViLXBsYXRmb3JtLnRlc3SCI3d3dzIueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9y
+bS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIjeG4t
+LWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzEueG4tLWx2ZS02
+bGFkLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0tbHZlLTZsYWQud3d3Lm5vdC13ZWIt
+cGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIn
+d3d3Mi54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gid3d3cxLnhu
+LS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53
+d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIpeG4tLW44ajZkczUzbHd3a3JxaHYy
+OGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQu
+d2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
+ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cud2Vi
+LXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzIud2Vi
+LXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnd3dzEud2Vi
+LXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2Vi
+LXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxhZC54bi0tbHZlLTZsYWQubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90
+LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cu
+bm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53
+d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIyd3d3MS54bi0tbjhqNmRzNTNsd3dr
+cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCMnd3dzIueG4tLW44ajZkczUz
+bHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0tbjhqNmRzNTNs
+d3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxhdGZvcm0udGVzdII2eG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0gjZ4
+bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3Jt
+LnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1sdmUtNmxhZC5ub3Qt
+d2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1sdmUtNmxhZC54bi0tbjhqNmRzNTNsd3dr
+cnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCQXhuLS1uOGo2ZHM1M2x3d2ty
+cWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLndlYi1wbGF0Zm9ybS50ZXN0
+gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54bi0tbjhqNmRzNTNsd3drcnFodjI4
+YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJKoZIhvcNAQELBQADggEBAHRhJQlg
+uwzvgj4WGzomthrmeYpP9hELJzW8jPDyTZosUeX63zmctP46cFlcFPSZJn5UGUrP
+hpwdC5RJx9cGjYUjqqgahM+R5bpo0NqJJZfiO0a+yndxUwYRawW/fGDnyFwcXl7p
+QYD1dpw+u5b1m9+B4GW3hXqzBLwBKJ8mH62E4RZQwSBMsSNiDLRsPFAdc/IIHKUS
+B8zI53byoNLzjGSDjaw77n2arGS3CuoBbYyiMxVVmdRgZ8pbHewfKkwKNdsnGGgr
+0YHlg2WQ/lBSOvPovAti89vkWzPJYhJbPS2ybaHOAzVJxmqP3dpBoL2vw8yTIM6G
+kGxP4JsY0GYmQ+U=
+-----END CERTIFICATE-----
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/config.json b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/config.json
new file mode 100644
index 0000000..df93c6f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/config.json
@@ -0,0 +1,17 @@
+{
+    "ports": {
+        "http": [],
+        "https": [],
+        "ws": [],
+        "wss": []
+    },
+    "check_subdomains": false,
+    "ssl": {
+        "type": "openssl",
+        "openssl": {
+            "duration": 365,
+            "force_regenerate": true,
+            "base_path": "tools/certs"
+        }
+    }
+}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.key b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.key
new file mode 100644
index 0000000..492fa9f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDE3iJ5ETr7Gylm
++Pano4qjJBd/vBVx81OvGhdDdoD0U6fVZxYosFvZPwiq7+J4vM0Pv16Z+TaMKZiQ
+nQwABKBIUlufArAuRVtivsoxYdmuOFJ0e/KNaeL9zjfgK1mYK1zK/xNNIt/OpWJ/
+GPMSCkywZ9ozBJ4+0vfb+ddDZruKfOMqTURL4zclukld5egdvT+1xF11yvYtPncY
+A4c8u4g4ry3nN8b3DEBgr0aWM3f9uXLVhddSqt0Qy7IpaqWI1cAwT9Dq1VAJK2ZB
+Hn9VQULSnVc+unmK8WU0Rgqs5s012B9oB6NfpQht6FIc+PQRNldNimxYkb2uneO6
+r/CjiVlfAgMBAAECggEAN/gPROwpIIqwUp4lQbO1DnyMUbxfPG45NGbuhjeCofPG
+m10bZ6X79t98z1wzvq+ufPOjKZM4dtC8lyCO8NJf3y/K7IIPJJiDSqeDRFbVVDqe
+9o7mfl3EMvQV3p10c1agovWxvxRTHKTYQ9oMAOz8sIpV9nsxohrIbLmzAW6Lkus+
+YmCCE0pBdxf9QmQAdcqHFjclFllfRGrlNqRTCsjUaDToat4N0riGr0nbLzEHw7Ml
+YLQVT3OTpKj3kNsA/Po9YFpt4hWv5Q0Ng0T0TKuBBe36qNQOaKje0RAmUS2rfYTS
+XEGsZU9w3uXJAMmcTbOG9+RGkwsern9gEGDfCvpKwQKBgQD1Z2JhQB2xUd3phvPq
+CQDlBWBJ9gPfZAIc9h8YrvzIGlR2iCUDSf04r148LqCf2a4Bm4YGRDtGKpCjmrg5
+hM3eHICnsI+KxsSexQV2yWBxfijI94WxvB9R5/WmebbyGN9Dz14e79cCpIOJNqQJ
+wfvlWf8vQaEZO6D6qW/1dVAI3QKBgQDNXj9aXX3KZewkj5dFSJOB63EATD9DOTaB
+BbtovYGlnS6hZApmrKRHqu8RwTWJtDe5f/9LWNamgSb+X9YevkxUd4IFxZmccSij
+3eQrJfyMgFOSeK/mTOgtGjSXLxCvUmNe0vkzAEt26mM/TS3vJ8UZFxzm0CEXuzsk
+3cuV5I9pawKBgQCzAKJmRZpjCVBRUzr/72lTpMRDrsvMWuqfrXepTZrdazdI7q3w
+5Dts6Z5XT7uiXenrCkKMt6B04f93Fxhh/FkeNrQxnTxXAf3RwezmZKWQo3Gkhchj
+iNFfsU8iC45CsZnJoK0K6+9t4gqAP/cPlwvik+7rzXdxLGmT7ZvY86VZkQKBgEax
+yt0wkby6mS98vnX7JcvzYFLZ7G0XpMuFTZ4gniCEmyizZ2EwzNxe2y0hdWyRvRz+
+EsO9MSbgDqxCEVND7sKk4P1bqCVSTssZ9xFjYix7gElLgkGk98eO3cutR/ESS2K4
+/U+xKkklJkUELGvHJPIeIrTRsJKawSFPuGVA6J1BAoGBANobP7XsZoSkQvsDPEXT
+lYdB9ez11hkQ1ZTbqkHrNUpJQ1IUbUuuK5cgNqK5rMTDySH/zofbh1kDOJxO0R5O
+KrqghC/efrOiDhOmGrxlYH7enTYEfDSav1M1TTTZ7cLd4+q8yeZ97S5b533NfsFF
+oYu93U3AsLggvr23JopNBxSQ
+-----END PRIVATE KEY-----
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.pem b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.pem
new file mode 100644
index 0000000..51df910
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/certs/web-platform.test.pem
@@ -0,0 +1,240 @@
+Certificate:
+    Data:
+        Version: 3 (0x2)
+        Serial Number: 325036 (0x4f5ac)
+        Signature Algorithm: sha256WithRSAEncryption
+        Issuer: CN=web-platform-tests
+        Validity
+            Not Before: Dec 12 00:28:27 2020 GMT
+            Not After : Dec 12 00:28:27 2021 GMT
+        Subject: CN=web-platform.test
+        Subject Public Key Info:
+            Public Key Algorithm: rsaEncryption
+                RSA Public-Key: (2048 bit)
+                Modulus:
+                    00:c4:de:22:79:11:3a:fb:1b:29:66:f8:f6:a7:a3:
+                    8a:a3:24:17:7f:bc:15:71:f3:53:af:1a:17:43:76:
+                    80:f4:53:a7:d5:67:16:28:b0:5b:d9:3f:08:aa:ef:
+                    e2:78:bc:cd:0f:bf:5e:99:f9:36:8c:29:98:90:9d:
+                    0c:00:04:a0:48:52:5b:9f:02:b0:2e:45:5b:62:be:
+                    ca:31:61:d9:ae:38:52:74:7b:f2:8d:69:e2:fd:ce:
+                    37:e0:2b:59:98:2b:5c:ca:ff:13:4d:22:df:ce:a5:
+                    62:7f:18:f3:12:0a:4c:b0:67:da:33:04:9e:3e:d2:
+                    f7:db:f9:d7:43:66:bb:8a:7c:e3:2a:4d:44:4b:e3:
+                    37:25:ba:49:5d:e5:e8:1d:bd:3f:b5:c4:5d:75:ca:
+                    f6:2d:3e:77:18:03:87:3c:bb:88:38:af:2d:e7:37:
+                    c6:f7:0c:40:60:af:46:96:33:77:fd:b9:72:d5:85:
+                    d7:52:aa:dd:10:cb:b2:29:6a:a5:88:d5:c0:30:4f:
+                    d0:ea:d5:50:09:2b:66:41:1e:7f:55:41:42:d2:9d:
+                    57:3e:ba:79:8a:f1:65:34:46:0a:ac:e6:cd:35:d8:
+                    1f:68:07:a3:5f:a5:08:6d:e8:52:1c:f8:f4:11:36:
+                    57:4d:8a:6c:58:91:bd:ae:9d:e3:ba:af:f0:a3:89:
+                    59:5f
+                Exponent: 65537 (0x10001)
+        X509v3 extensions:
+            X509v3 Basic Constraints: 
+                CA:FALSE
+            X509v3 Subject Key Identifier: 
+                F5:4B:78:98:A0:A3:36:E3:6F:B8:3C:19:E2:F7:BE:70:0E:F8:70:73
+            X509v3 Authority Key Identifier: 
+                keyid:A7:A9:5E:71:A9:A9:64:1B:B2:03:8C:D1:63:E3:F8:A1:D0:B5:1A:68
+
+            X509v3 Key Usage: 
+                Digital Signature, Non Repudiation, Key Encipherment
+            X509v3 Extended Key Usage: 
+                TLS Web Server Authentication
+            X509v3 Subject Alternative Name: 
+                DNS:web-platform.test, DNS:op8.web-platform.test, DNS:op7.web-platform.test, DNS:op9.web-platform.test, DNS:op4.web-platform.test, DNS:not-web-platform.test, DNS:op6.web-platform.test, DNS:op3.web-platform.test, DNS:op2.web-platform.test, DNS:op1.web-platform.test, DNS:www.web-platform.test, DNS:op5.web-platform.test, DNS:op88.web-platform.test, DNS:op98.web-platform.test, DNS:op85.web-platform.test, DNS:op89.web-platform.test, DNS:op66.web-platform.test, DNS:op72.web-platform.test, DNS:op24.web-platform.test, DNS:op41.web-platform.test, DNS:op79.web-platform.test, DNS:op91.web-platform.test, DNS:op59.web-platform.test, DNS:op39.web-platform.test, DNS:op60.web-platform.test, DNS:op58.web-platform.test, DNS:op28.web-platform.test, DNS:www1.web-platform.test, DNS:op14.web-platform.test, DNS:op69.web-platform.test, DNS:op40.web-platform.test, DNS:op74.web-platform.test, DNS:op31.web-platform.test, DNS:op18.web-platform.test, DNS:op73.web-platform.test, DNS:op77.web-platform.test, DNS:op12.web-platform.test, DNS:op54.web-platform.test, DNS:op63.web-platform.test, DNS:op71.web-platform.test, DNS:op95.web-platform.test, DNS:op16.web-platform.test, DNS:op36.web-platform.test, DNS:op27.web-platform.test, DNS:op29.web-platform.test, DNS:op94.web-platform.test, DNS:op44.web-platform.test, DNS:op33.web-platform.test, DNS:op84.web-platform.test, DNS:op32.web-platform.test, DNS:op61.web-platform.test, DNS:op70.web-platform.test, DNS:www2.web-platform.test, DNS:op43.web-platform.test, DNS:op78.web-platform.test, DNS:op26.web-platform.test, DNS:op76.web-platform.test, DNS:op52.web-platform.test, DNS:op99.web-platform.test, DNS:op86.web-platform.test, DNS:op46.web-platform.test, DNS:op17.web-platform.test, DNS:op90.web-platform.test, DNS:op93.web-platform.test, DNS:op10.web-platform.test, DNS:op55.web-platform.test, DNS:op47.web-platform.test, DNS:op51.web-platform.test, DNS:op45.web-platform.test, DNS:op80.web-platform.test, DNS:op68.web-platform.test, DNS:op49.web-platform.test, DNS:op57.web-platform.test, DNS:op35.web-platform.test, DNS:op67.web-platform.test, DNS:op92.web-platform.test, DNS:op15.web-platform.test, DNS:op13.web-platform.test, DNS:op75.web-platform.test, DNS:op64.web-platform.test, DNS:op97.web-platform.test, DNS:op37.web-platform.test, DNS:op56.web-platform.test, DNS:op62.web-platform.test, DNS:op82.web-platform.test, DNS:op25.web-platform.test, DNS:op11.web-platform.test, DNS:op50.web-platform.test, DNS:op38.web-platform.test, DNS:op83.web-platform.test, DNS:op81.web-platform.test, DNS:op20.web-platform.test, DNS:op21.web-platform.test, DNS:op23.web-platform.test, DNS:op42.web-platform.test, DNS:op22.web-platform.test, DNS:op65.web-platform.test, DNS:op96.web-platform.test, DNS:op87.web-platform.test, DNS:op19.web-platform.test, DNS:op53.web-platform.test, DNS:op30.web-platform.test, DNS:op48.web-platform.test, DNS:op34.web-platform.test, DNS:op6.not-web-platform.test, DNS:op3.not-web-platform.test, DNS:op2.not-web-platform.test, DNS:op5.not-web-platform.test, DNS:www.not-web-platform.test, DNS:www.www.web-platform.test, DNS:op7.not-web-platform.test, DNS:op4.not-web-platform.test, DNS:op8.not-web-platform.test, DNS:op9.not-web-platform.test, DNS:op1.not-web-platform.test, DNS:op36.not-web-platform.test, DNS:op53.not-web-platform.test, DNS:op50.not-web-platform.test, DNS:op24.not-web-platform.test, DNS:op31.not-web-platform.test, DNS:op95.not-web-platform.test, DNS:op83.not-web-platform.test, DNS:www2.not-web-platform.test, DNS:op73.not-web-platform.test, DNS:op19.not-web-platform.test, DNS:op21.not-web-platform.test, DNS:op81.not-web-platform.test, DNS:op70.not-web-platform.test, DNS:op78.not-web-platform.test, DNS:op40.not-web-platform.test, DNS:op25.not-web-platform.test, DNS:op65.not-web-platform.test, DNS:www.www2.web-platform.test, DNS:op80.not-web-platform.test, DNS:op52.not-web-platform.test, DNS:op68.not-web-platform.test, DNS:op45.not-web-platform.test, DNS:op71.not-web-platform.test, DNS:op72.not-web-platform.test, DNS:op90.not-web-platform.test, DNS:op89.not-web-platform.test, DNS:op49.not-web-platform.test, DNS:op77.not-web-platform.test, DNS:op79.not-web-platform.test, DNS:op82.not-web-platform.test, DNS:www.www1.web-platform.test, DNS:op12.not-web-platform.test, DNS:op39.not-web-platform.test, DNS:op44.not-web-platform.test, DNS:www1.not-web-platform.test, DNS:op58.not-web-platform.test, DNS:op14.not-web-platform.test, DNS:op30.not-web-platform.test, DNS:op62.not-web-platform.test, DNS:op61.not-web-platform.test, DNS:op92.not-web-platform.test, DNS:op29.not-web-platform.test, DNS:op98.not-web-platform.test, DNS:op64.not-web-platform.test, DNS:op26.not-web-platform.test, DNS:op22.not-web-platform.test, DNS:op94.not-web-platform.test, DNS:op38.not-web-platform.test, DNS:op33.not-web-platform.test, DNS:op23.not-web-platform.test, DNS:op57.not-web-platform.test, DNS:op54.not-web-platform.test, DNS:op85.not-web-platform.test, DNS:op46.not-web-platform.test, DNS:op97.not-web-platform.test, DNS:op32.not-web-platform.test, DNS:op60.not-web-platform.test, DNS:op96.not-web-platform.test, DNS:op51.not-web-platform.test, DNS:op41.not-web-platform.test, DNS:op35.not-web-platform.test, DNS:op99.not-web-platform.test, DNS:op42.not-web-platform.test, DNS:op67.not-web-platform.test, DNS:op37.not-web-platform.test, DNS:op48.not-web-platform.test, DNS:op55.not-web-platform.test, DNS:op56.not-web-platform.test, DNS:op84.not-web-platform.test, DNS:op34.not-web-platform.test, DNS:op69.not-web-platform.test, DNS:op11.not-web-platform.test, DNS:op93.not-web-platform.test, DNS:www1.www.web-platform.test, DNS:op86.not-web-platform.test, DNS:op13.not-web-platform.test, DNS:op20.not-web-platform.test, DNS:op76.not-web-platform.test, DNS:op27.not-web-platform.test, DNS:op17.not-web-platform.test, DNS:op75.not-web-platform.test, DNS:op15.not-web-platform.test, DNS:op47.not-web-platform.test, DNS:op18.not-web-platform.test, DNS:op63.not-web-platform.test, DNS:op28.not-web-platform.test, DNS:op43.not-web-platform.test, DNS:op66.not-web-platform.test, DNS:www2.www.web-platform.test, DNS:op91.not-web-platform.test, DNS:op74.not-web-platform.test, DNS:op59.not-web-platform.test, DNS:op88.not-web-platform.test, DNS:op87.not-web-platform.test, DNS:op10.not-web-platform.test, DNS:op16.not-web-platform.test, DNS:www1.www2.web-platform.test, DNS:www2.www2.web-platform.test, DNS:www2.www1.web-platform.test, DNS:www1.www1.web-platform.test, DNS:www.www.not-web-platform.test, DNS:xn--lve-6lad.web-platform.test, DNS:www1.www.not-web-platform.test, DNS:www.www2.not-web-platform.test, DNS:www2.www.not-web-platform.test, DNS:www.www1.not-web-platform.test, DNS:www2.www2.not-web-platform.test, DNS:www2.www1.not-web-platform.test, DNS:www1.www1.not-web-platform.test, DNS:www1.www2.not-web-platform.test, DNS:xn--lve-6lad.www.web-platform.test, DNS:xn--lve-6lad.not-web-platform.test, DNS:www.xn--lve-6lad.web-platform.test, DNS:www2.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www2.web-platform.test, DNS:xn--lve-6lad.www1.web-platform.test, DNS:www1.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.www.not-web-platform.test, DNS:www.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www1.not-web-platform.test, DNS:www2.xn--lve-6lad.not-web-platform.test, DNS:www1.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.www2.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--lve-6lad.xn--lve-6lad.not-web-platform.test, DNS:www.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www2.not-web-platform.test, DNS:www1.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:www2.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.www1.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--lve-6lad.not-web-platform.test, DNS:xn--lve-6lad.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.web-platform.test, DNS:xn--n8j6ds53lwwkrqhv28a.xn--n8j6ds53lwwkrqhv28a.not-web-platform.test
+    Signature Algorithm: sha256WithRSAEncryption
+         69:64:ad:f6:53:84:f8:7e:e2:6d:0a:4a:ff:3f:44:d0:30:4f:
+         aa:db:18:8c:1a:49:28:76:04:19:61:1b:34:4b:d9:63:da:96:
+         e1:73:67:26:cf:b0:71:ef:0f:0a:e8:db:17:00:5b:48:cc:89:
+         6d:a5:c5:41:c5:ea:5e:6f:2a:4f:5e:68:f0:93:69:3c:32:6c:
+         15:7f:f5:bd:9b:f8:ab:82:01:65:42:c2:d5:f5:26:9e:06:2b:
+         84:46:74:99:bd:44:d2:17:3b:28:7b:61:61:a3:55:7c:90:6d:
+         7e:88:6e:3c:ce:73:ac:90:a2:89:72:ee:17:0d:e8:21:2d:9d:
+         f7:b0:86:2f:53:8c:70:84:25:3c:6f:33:f4:12:39:7d:68:28:
+         24:31:44:a5:66:05:29:8e:9d:f3:df:62:df:5b:e0:37:d9:15:
+         44:fc:33:f0:63:8e:93:74:10:db:4f:72:5c:2c:b7:ab:18:58:
+         73:f4:ed:15:04:26:d1:42:67:cf:62:35:ee:9a:31:74:34:5e:
+         62:96:1e:a7:23:25:ec:d8:ff:56:40:34:ee:ba:f3:e1:81:5d:
+         56:ab:a1:2d:65:f5:20:57:0f:60:90:dc:ea:ab:d4:0d:96:5b:
+         b2:b5:39:5f:0b:6d:97:3a:b6:bf:d7:9c:36:60:97:3b:bc:3e:
+         f4:8b:e2:df
+-----BEGIN CERTIFICATE-----
+MIIgvDCCH6SgAwIBAgIDBPWsMA0GCSqGSIb3DQEBCwUAMB0xGzAZBgNVBAMMEndl
+Yi1wbGF0Zm9ybS10ZXN0czAeFw0yMDEyMTIwMDI4MjdaFw0yMTEyMTIwMDI4Mjda
+MBwxGjAYBgNVBAMMEXdlYi1wbGF0Zm9ybS50ZXN0MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAxN4ieRE6+xspZvj2p6OKoyQXf7wVcfNTrxoXQ3aA9FOn
+1WcWKLBb2T8Iqu/ieLzND79emfk2jCmYkJ0MAASgSFJbnwKwLkVbYr7KMWHZrjhS
+dHvyjWni/c434CtZmCtcyv8TTSLfzqVifxjzEgpMsGfaMwSePtL32/nXQ2a7inzj
+Kk1ES+M3JbpJXeXoHb0/tcRddcr2LT53GAOHPLuIOK8t5zfG9wxAYK9GljN3/bly
+1YXXUqrdEMuyKWqliNXAME/Q6tVQCStmQR5/VUFC0p1XPrp5ivFlNEYKrObNNdgf
+aAejX6UIbehSHPj0ETZXTYpsWJG9rp3juq/wo4lZXwIDAQABo4IeBDCCHgAwCQYD
+VR0TBAIwADAdBgNVHQ4EFgQU9Ut4mKCjNuNvuDwZ4ve+cA74cHMwHwYDVR0jBBgw
+FoAUp6lecampZBuyA4zRY+P4odC1GmgwCwYDVR0PBAQDAgXgMBMGA1UdJQQMMAoG
+CCsGAQUFBwMBMIIdjwYDVR0RBIIdhjCCHYKCEXdlYi1wbGF0Zm9ybS50ZXN0ghVv
+cDgud2ViLXBsYXRmb3JtLnRlc3SCFW9wNy53ZWItcGxhdGZvcm0udGVzdIIVb3A5
+LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDQud2ViLXBsYXRmb3JtLnRlc3SCFW5vdC13
+ZWItcGxhdGZvcm0udGVzdIIVb3A2LndlYi1wbGF0Zm9ybS50ZXN0ghVvcDMud2Vi
+LXBsYXRmb3JtLnRlc3SCFW9wMi53ZWItcGxhdGZvcm0udGVzdIIVb3AxLndlYi1w
+bGF0Zm9ybS50ZXN0ghV3d3cud2ViLXBsYXRmb3JtLnRlc3SCFW9wNS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4OC53ZWItcGxhdGZvcm0udGVzdIIWb3A5OC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4NS53ZWItcGxhdGZvcm0udGVzdIIWb3A4OS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A3Mi53ZWItcGxh
+dGZvcm0udGVzdIIWb3AyNC53ZWItcGxhdGZvcm0udGVzdIIWb3A0MS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A3OS53ZWItcGxhdGZvcm0udGVzdIIWb3A5MS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A1OS53ZWItcGxhdGZvcm0udGVzdIIWb3AzOS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2MC53ZWItcGxhdGZvcm0udGVzdIIWb3A1OC53ZWItcGxh
+dGZvcm0udGVzdIIWb3AyOC53ZWItcGxhdGZvcm0udGVzdIIWd3d3MS53ZWItcGxh
+dGZvcm0udGVzdIIWb3AxNC53ZWItcGxhdGZvcm0udGVzdIIWb3A2OS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0MC53ZWItcGxhdGZvcm0udGVzdIIWb3A3NC53ZWItcGxh
+dGZvcm0udGVzdIIWb3AzMS53ZWItcGxhdGZvcm0udGVzdIIWb3AxOC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A3My53ZWItcGxhdGZvcm0udGVzdIIWb3A3Ny53ZWItcGxh
+dGZvcm0udGVzdIIWb3AxMi53ZWItcGxhdGZvcm0udGVzdIIWb3A1NC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2My53ZWItcGxhdGZvcm0udGVzdIIWb3A3MS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A5NS53ZWItcGxhdGZvcm0udGVzdIIWb3AxNi53ZWItcGxh
+dGZvcm0udGVzdIIWb3AzNi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNy53ZWItcGxh
+dGZvcm0udGVzdIIWb3AyOS53ZWItcGxhdGZvcm0udGVzdIIWb3A5NC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMy53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4NC53ZWItcGxhdGZvcm0udGVzdIIWb3AzMi53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2MS53ZWItcGxhdGZvcm0udGVzdIIWb3A3MC53ZWItcGxh
+dGZvcm0udGVzdIIWd3d3Mi53ZWItcGxhdGZvcm0udGVzdIIWb3A0My53ZWItcGxh
+dGZvcm0udGVzdIIWb3A3OC53ZWItcGxhdGZvcm0udGVzdIIWb3AyNi53ZWItcGxh
+dGZvcm0udGVzdIIWb3A3Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A1Mi53ZWItcGxh
+dGZvcm0udGVzdIIWb3A5OS53ZWItcGxhdGZvcm0udGVzdIIWb3A4Ni53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0Ni53ZWItcGxhdGZvcm0udGVzdIIWb3AxNy53ZWItcGxh
+dGZvcm0udGVzdIIWb3A5MC53ZWItcGxhdGZvcm0udGVzdIIWb3A5My53ZWItcGxh
+dGZvcm0udGVzdIIWb3AxMC53ZWItcGxhdGZvcm0udGVzdIIWb3A1NS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A1MS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0NS53ZWItcGxhdGZvcm0udGVzdIIWb3A4MC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2OC53ZWItcGxhdGZvcm0udGVzdIIWb3A0OS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A1Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzNS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2Ny53ZWItcGxhdGZvcm0udGVzdIIWb3A5Mi53ZWItcGxh
+dGZvcm0udGVzdIIWb3AxNS53ZWItcGxhdGZvcm0udGVzdIIWb3AxMy53ZWItcGxh
+dGZvcm0udGVzdIIWb3A3NS53ZWItcGxhdGZvcm0udGVzdIIWb3A2NC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A5Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AzNy53ZWItcGxh
+dGZvcm0udGVzdIIWb3A1Ni53ZWItcGxhdGZvcm0udGVzdIIWb3A2Mi53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyNS53ZWItcGxh
+dGZvcm0udGVzdIIWb3AxMS53ZWItcGxhdGZvcm0udGVzdIIWb3A1MC53ZWItcGxh
+dGZvcm0udGVzdIIWb3AzOC53ZWItcGxhdGZvcm0udGVzdIIWb3A4My53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4MS53ZWItcGxhdGZvcm0udGVzdIIWb3AyMC53ZWItcGxh
+dGZvcm0udGVzdIIWb3AyMS53ZWItcGxhdGZvcm0udGVzdIIWb3AyMy53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0Mi53ZWItcGxhdGZvcm0udGVzdIIWb3AyMi53ZWItcGxh
+dGZvcm0udGVzdIIWb3A2NS53ZWItcGxhdGZvcm0udGVzdIIWb3A5Ni53ZWItcGxh
+dGZvcm0udGVzdIIWb3A4Ny53ZWItcGxhdGZvcm0udGVzdIIWb3AxOS53ZWItcGxh
+dGZvcm0udGVzdIIWb3A1My53ZWItcGxhdGZvcm0udGVzdIIWb3AzMC53ZWItcGxh
+dGZvcm0udGVzdIIWb3A0OC53ZWItcGxhdGZvcm0udGVzdIIWb3AzNC53ZWItcGxh
+dGZvcm0udGVzdIIZb3A2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AzLm5vdC13
+ZWItcGxhdGZvcm0udGVzdIIZb3AyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A1
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZd3d3Lm5vdC13ZWItcGxhdGZvcm0udGVz
+dIIZd3d3Lnd3dy53ZWItcGxhdGZvcm0udGVzdIIZb3A3Lm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIZb3A0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3A4Lm5vdC13ZWIt
+cGxhdGZvcm0udGVzdIIZb3A5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIZb3AxLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wNTMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDUwLm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3AyNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzEubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDk1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4
+My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzIubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDczLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxOS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wMjEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDgxLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3A3MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wNzgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQwLm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3AyNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjUubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghp3d3cud3d3Mi53ZWItcGxhdGZvcm0udGVzdIIab3A4
+MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTIubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDY4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0NS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wNzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDcyLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3A5MC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wODkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQ5Lm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3A3Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNzkubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDgyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIad3d3
+Lnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCGm9wMTIubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDM5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A0NC5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGnd3dzEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU4Lm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3AxNC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wMzAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDYyLm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3A2MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wOTIubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDI5Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5
+OC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNjQubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDI2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AyMi5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wOTQubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDM4Lm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3AzMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wMjMubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDU3Lm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3A1NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wODUubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDQ2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5
+Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzIubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDYwLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A5Ni5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wNTEubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQxLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3AzNS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wOTkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQyLm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3A2Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMzcubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDQ4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A1
+NS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTYubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDg0Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AzNC5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wNjkubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDExLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3A5My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gnd3dzEud3d3LndlYi1wbGF0Zm9ybS50ZXN0ghpvcDg2Lm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3AxMy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMjAubm90LXdl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDc2Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3Ay
+Ny5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wMTcubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDc1Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3AxNS5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wNDcubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE4Lm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIab3A2My5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SC
+Gm9wMjgubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDQzLm5vdC13ZWItcGxhdGZv
+cm0udGVzdIIab3A2Ni5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGnd3dzIud3d3Lndl
+Yi1wbGF0Zm9ybS50ZXN0ghpvcDkxLm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A3
+NC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCGm9wNTkubm90LXdlYi1wbGF0Zm9ybS50
+ZXN0ghpvcDg4Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIab3A4Ny5ub3Qtd2ViLXBs
+YXRmb3JtLnRlc3SCGm9wMTAubm90LXdlYi1wbGF0Zm9ybS50ZXN0ghpvcDE2Lm5v
+dC13ZWItcGxhdGZvcm0udGVzdIIbd3d3MS53d3cyLndlYi1wbGF0Zm9ybS50ZXN0
+ght3d3cyLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCG3d3dzIud3d3MS53ZWItcGxh
+dGZvcm0udGVzdIIbd3d3MS53d3cxLndlYi1wbGF0Zm9ybS50ZXN0gh13d3cud3d3
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIeeG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9y
+bS50ZXN0gh53d3cxLnd3dy5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCHnd3dy53d3cy
+Lm5vdC13ZWItcGxhdGZvcm0udGVzdIIed3d3Mi53d3cubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0gh53d3cud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3
+Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzIud3d3MS5ub3Qtd2ViLXBsYXRm
+b3JtLnRlc3SCH3d3dzEud3d3MS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCH3d3dzEu
+d3d3Mi5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC53d3cud2Vi
+LXBsYXRmb3JtLnRlc3SCInhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCInd3dy54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCI3d3dzIueG4t
+LWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0giN4bi0tbHZlLTZsYWQud3d3Mi53
+ZWItcGxhdGZvcm0udGVzdIIjeG4tLWx2ZS02bGFkLnd3dzEud2ViLXBsYXRmb3Jt
+LnRlc3SCI3d3dzEueG4tLWx2ZS02bGFkLndlYi1wbGF0Zm9ybS50ZXN0giZ4bi0t
+bHZlLTZsYWQud3d3Lm5vdC13ZWItcGxhdGZvcm0udGVzdIImd3d3LnhuLS1sdmUt
+NmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCJ3huLS1sdmUtNmxhZC53d3cxLm5v
+dC13ZWItcGxhdGZvcm0udGVzdIInd3d3Mi54bi0tbHZlLTZsYWQubm90LXdlYi1w
+bGF0Zm9ybS50ZXN0gid3d3cxLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3Jt
+LnRlc3SCJ3huLS1sdmUtNmxhZC53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIp
+eG4tLW44ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCK3huLS1s
+dmUtNmxhZC54bi0tbHZlLTZsYWQud2ViLXBsYXRmb3JtLnRlc3SCLXd3dy54bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS53ZWItcGxhdGZvcm0udGVzdIIteG4tLW44ajZk
+czUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gi14bi0tbjhqNmRz
+NTNsd3drcnFodjI4YS53d3cud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzEueG4tLW44
+ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1
+M2x3d2tycWh2MjhhLnd3dzIud2ViLXBsYXRmb3JtLnRlc3SCLnhuLS1uOGo2ZHM1
+M2x3d2tycWh2MjhhLnd3dzEud2ViLXBsYXRmb3JtLnRlc3SCLnd3dzIueG4tLW44
+ajZkczUzbHd3a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCL3huLS1sdmUtNmxh
+ZC54bi0tbHZlLTZsYWQubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF3d3cueG4tLW44
+ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjF4bi0tbjhq
+NmRzNTNsd3drcnFodjI4YS53d3cubm90LXdlYi1wbGF0Zm9ybS50ZXN0gjJ4bi0t
+bjhqNmRzNTNsd3drcnFodjI4YS53d3cyLm5vdC13ZWItcGxhdGZvcm0udGVzdIIy
+d3d3MS54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCMnd3dzIueG4tLW44ajZkczUzbHd3a3JxaHYyOGEubm90LXdlYi1wbGF0Zm9y
+bS50ZXN0gjJ4bi0tbjhqNmRzNTNsd3drcnFodjI4YS53d3cxLm5vdC13ZWItcGxh
+dGZvcm0udGVzdII2eG4tLW44ajZkczUzbHd3a3JxaHYyOGEueG4tLWx2ZS02bGFk
+LndlYi1wbGF0Zm9ybS50ZXN0gjZ4bi0tbHZlLTZsYWQueG4tLW44ajZkczUzbHd3
+a3JxaHYyOGEud2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1uOGo2ZHM1M2x3d2tycWh2
+MjhhLnhuLS1sdmUtNmxhZC5ub3Qtd2ViLXBsYXRmb3JtLnRlc3SCOnhuLS1sdmUt
+NmxhZC54bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRl
+c3SCQXhuLS1uOGo2ZHM1M2x3d2tycWh2MjhhLnhuLS1uOGo2ZHM1M2x3d2tycWh2
+MjhhLndlYi1wbGF0Zm9ybS50ZXN0gkV4bi0tbjhqNmRzNTNsd3drcnFodjI4YS54
+bi0tbjhqNmRzNTNsd3drcnFodjI4YS5ub3Qtd2ViLXBsYXRmb3JtLnRlc3QwDQYJ
+KoZIhvcNAQELBQADggEBAGlkrfZThPh+4m0KSv8/RNAwT6rbGIwaSSh2BBlhGzRL
+2WPaluFzZybPsHHvDwro2xcAW0jMiW2lxUHF6l5vKk9eaPCTaTwybBV/9b2b+KuC
+AWVCwtX1Jp4GK4RGdJm9RNIXOyh7YWGjVXyQbX6IbjzOc6yQooly7hcN6CEtnfew
+hi9TjHCEJTxvM/QSOX1oKCQxRKVmBSmOnfPfYt9b4DfZFUT8M/BjjpN0ENtPclws
+t6sYWHP07RUEJtFCZ89iNe6aMXQ0XmKWHqcjJezY/1ZANO668+GBXVaroS1l9SBX
+D2CQ3Oqr1A2WW7K1OV8LbZc6tr/XnDZglzu8PvSL4t8=
+-----END CERTIFICATE-----
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/LICENSE b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/LICENSE
new file mode 100644
index 0000000..f433b1a5
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/LICENSE
@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.js
new file mode 100644
index 0000000..dcefe070
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.js
@@ -0,0 +1,24624 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2019 Mozilla Foundation
+ *
+ * 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.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("pdfjs-dist/build/pdf", [], factory);
+	else if(typeof exports === 'object')
+		exports["pdfjs-dist/build/pdf"] = factory();
+	else
+		root["pdfjs-dist/build/pdf"] = root.pdfjsLib = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __w_pdfjs_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__w_pdfjs_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__w_pdfjs_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__w_pdfjs_require__.d = function(exports, name, getter) {
+/******/ 		if(!__w_pdfjs_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__w_pdfjs_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__w_pdfjs_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __w_pdfjs_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__w_pdfjs_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __w_pdfjs_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__w_pdfjs_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__w_pdfjs_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__w_pdfjs_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __w_pdfjs_require__(__w_pdfjs_require__.s = 0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var pdfjsVersion = '2.2.228';
+var pdfjsBuild = 'd7afb74a';
+
+var pdfjsSharedUtil = __w_pdfjs_require__(1);
+
+var pdfjsDisplayAPI = __w_pdfjs_require__(147);
+
+var pdfjsDisplayTextLayer = __w_pdfjs_require__(162);
+
+var pdfjsDisplayAnnotationLayer = __w_pdfjs_require__(163);
+
+var pdfjsDisplayDisplayUtils = __w_pdfjs_require__(151);
+
+var pdfjsDisplaySVG = __w_pdfjs_require__(164);
+
+var pdfjsDisplayWorkerOptions = __w_pdfjs_require__(156);
+
+var pdfjsDisplayAPICompatibility = __w_pdfjs_require__(153);
+
+{
+  var isNodeJS = __w_pdfjs_require__(4);
+
+  if (isNodeJS()) {
+    var PDFNodeStream = __w_pdfjs_require__(165).PDFNodeStream;
+
+    pdfjsDisplayAPI.setPDFNetworkStreamFactory(function (params) {
+      return new PDFNodeStream(params);
+    });
+  } else {
+    var PDFNetworkStream = __w_pdfjs_require__(168).PDFNetworkStream;
+
+    var PDFFetchStream;
+
+    if (pdfjsDisplayDisplayUtils.isFetchSupported()) {
+      PDFFetchStream = __w_pdfjs_require__(169).PDFFetchStream;
+    }
+
+    pdfjsDisplayAPI.setPDFNetworkStreamFactory(function (params) {
+      if (PDFFetchStream && pdfjsDisplayDisplayUtils.isValidFetchUrl(params.url)) {
+        return new PDFFetchStream(params);
+      }
+
+      return new PDFNetworkStream(params);
+    });
+  }
+}
+exports.build = pdfjsDisplayAPI.build;
+exports.version = pdfjsDisplayAPI.version;
+exports.getDocument = pdfjsDisplayAPI.getDocument;
+exports.LoopbackPort = pdfjsDisplayAPI.LoopbackPort;
+exports.PDFDataRangeTransport = pdfjsDisplayAPI.PDFDataRangeTransport;
+exports.PDFWorker = pdfjsDisplayAPI.PDFWorker;
+exports.renderTextLayer = pdfjsDisplayTextLayer.renderTextLayer;
+exports.AnnotationLayer = pdfjsDisplayAnnotationLayer.AnnotationLayer;
+exports.createPromiseCapability = pdfjsSharedUtil.createPromiseCapability;
+exports.PasswordResponses = pdfjsSharedUtil.PasswordResponses;
+exports.InvalidPDFException = pdfjsSharedUtil.InvalidPDFException;
+exports.MissingPDFException = pdfjsSharedUtil.MissingPDFException;
+exports.SVGGraphics = pdfjsDisplaySVG.SVGGraphics;
+exports.NativeImageDecoding = pdfjsSharedUtil.NativeImageDecoding;
+exports.CMapCompressionType = pdfjsSharedUtil.CMapCompressionType;
+exports.PermissionFlag = pdfjsSharedUtil.PermissionFlag;
+exports.UnexpectedResponseException = pdfjsSharedUtil.UnexpectedResponseException;
+exports.OPS = pdfjsSharedUtil.OPS;
+exports.VerbosityLevel = pdfjsSharedUtil.VerbosityLevel;
+exports.UNSUPPORTED_FEATURES = pdfjsSharedUtil.UNSUPPORTED_FEATURES;
+exports.createValidAbsoluteUrl = pdfjsSharedUtil.createValidAbsoluteUrl;
+exports.createObjectURL = pdfjsSharedUtil.createObjectURL;
+exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters;
+exports.shadow = pdfjsSharedUtil.shadow;
+exports.Util = pdfjsSharedUtil.Util;
+exports.ReadableStream = pdfjsSharedUtil.ReadableStream;
+exports.URL = pdfjsSharedUtil.URL;
+exports.RenderingCancelledException = pdfjsDisplayDisplayUtils.RenderingCancelledException;
+exports.getFilenameFromUrl = pdfjsDisplayDisplayUtils.getFilenameFromUrl;
+exports.LinkTarget = pdfjsDisplayDisplayUtils.LinkTarget;
+exports.addLinkAttributes = pdfjsDisplayDisplayUtils.addLinkAttributes;
+exports.loadScript = pdfjsDisplayDisplayUtils.loadScript;
+exports.PDFDateString = pdfjsDisplayDisplayUtils.PDFDateString;
+exports.GlobalWorkerOptions = pdfjsDisplayWorkerOptions.GlobalWorkerOptions;
+exports.apiCompatibilityParams = pdfjsDisplayAPICompatibility.apiCompatibilityParams;
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.arrayByteLength = arrayByteLength;
+exports.arraysToBytes = arraysToBytes;
+exports.assert = assert;
+exports.bytesToString = bytesToString;
+exports.createPromiseCapability = createPromiseCapability;
+exports.getVerbosityLevel = getVerbosityLevel;
+exports.info = info;
+exports.isArrayBuffer = isArrayBuffer;
+exports.isArrayEqual = isArrayEqual;
+exports.isBool = isBool;
+exports.isEmptyObj = isEmptyObj;
+exports.isNum = isNum;
+exports.isString = isString;
+exports.isSpace = isSpace;
+exports.isSameOrigin = isSameOrigin;
+exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
+exports.isLittleEndian = isLittleEndian;
+exports.isEvalSupported = isEvalSupported;
+exports.log2 = log2;
+exports.readInt8 = readInt8;
+exports.readUint16 = readUint16;
+exports.readUint32 = readUint32;
+exports.removeNullCharacters = removeNullCharacters;
+exports.setVerbosityLevel = setVerbosityLevel;
+exports.shadow = shadow;
+exports.string32 = string32;
+exports.stringToBytes = stringToBytes;
+exports.stringToPDFString = stringToPDFString;
+exports.stringToUTF8String = stringToUTF8String;
+exports.utf8StringToString = utf8StringToString;
+exports.warn = warn;
+exports.unreachable = unreachable;
+Object.defineProperty(exports, "ReadableStream", {
+  enumerable: true,
+  get: function get() {
+    return _streams_polyfill.ReadableStream;
+  }
+});
+Object.defineProperty(exports, "URL", {
+  enumerable: true,
+  get: function get() {
+    return _url_polyfill.URL;
+  }
+});
+exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = void 0;
+
+__w_pdfjs_require__(2);
+
+var _streams_polyfill = __w_pdfjs_require__(143);
+
+var _url_polyfill = __w_pdfjs_require__(145);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
+var NativeImageDecoding = {
+  NONE: 'none',
+  DECODE: 'decode',
+  DISPLAY: 'display'
+};
+exports.NativeImageDecoding = NativeImageDecoding;
+var PermissionFlag = {
+  PRINT: 0x04,
+  MODIFY_CONTENTS: 0x08,
+  COPY: 0x10,
+  MODIFY_ANNOTATIONS: 0x20,
+  FILL_INTERACTIVE_FORMS: 0x100,
+  COPY_FOR_ACCESSIBILITY: 0x200,
+  ASSEMBLE: 0x400,
+  PRINT_HIGH_QUALITY: 0x800
+};
+exports.PermissionFlag = PermissionFlag;
+var TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7,
+  FILL_STROKE_MASK: 3,
+  ADD_TO_PATH_FLAG: 4
+};
+exports.TextRenderingMode = TextRenderingMode;
+var ImageKind = {
+  GRAYSCALE_1BPP: 1,
+  RGB_24BPP: 2,
+  RGBA_32BPP: 3
+};
+exports.ImageKind = ImageKind;
+var AnnotationType = {
+  TEXT: 1,
+  LINK: 2,
+  FREETEXT: 3,
+  LINE: 4,
+  SQUARE: 5,
+  CIRCLE: 6,
+  POLYGON: 7,
+  POLYLINE: 8,
+  HIGHLIGHT: 9,
+  UNDERLINE: 10,
+  SQUIGGLY: 11,
+  STRIKEOUT: 12,
+  STAMP: 13,
+  CARET: 14,
+  INK: 15,
+  POPUP: 16,
+  FILEATTACHMENT: 17,
+  SOUND: 18,
+  MOVIE: 19,
+  WIDGET: 20,
+  SCREEN: 21,
+  PRINTERMARK: 22,
+  TRAPNET: 23,
+  WATERMARK: 24,
+  THREED: 25,
+  REDACT: 26
+};
+exports.AnnotationType = AnnotationType;
+var AnnotationFlag = {
+  INVISIBLE: 0x01,
+  HIDDEN: 0x02,
+  PRINT: 0x04,
+  NOZOOM: 0x08,
+  NOROTATE: 0x10,
+  NOVIEW: 0x20,
+  READONLY: 0x40,
+  LOCKED: 0x80,
+  TOGGLENOVIEW: 0x100,
+  LOCKEDCONTENTS: 0x200
+};
+exports.AnnotationFlag = AnnotationFlag;
+var AnnotationFieldFlag = {
+  READONLY: 0x0000001,
+  REQUIRED: 0x0000002,
+  NOEXPORT: 0x0000004,
+  MULTILINE: 0x0001000,
+  PASSWORD: 0x0002000,
+  NOTOGGLETOOFF: 0x0004000,
+  RADIO: 0x0008000,
+  PUSHBUTTON: 0x0010000,
+  COMBO: 0x0020000,
+  EDIT: 0x0040000,
+  SORT: 0x0080000,
+  FILESELECT: 0x0100000,
+  MULTISELECT: 0x0200000,
+  DONOTSPELLCHECK: 0x0400000,
+  DONOTSCROLL: 0x0800000,
+  COMB: 0x1000000,
+  RICHTEXT: 0x2000000,
+  RADIOSINUNISON: 0x2000000,
+  COMMITONSELCHANGE: 0x4000000
+};
+exports.AnnotationFieldFlag = AnnotationFieldFlag;
+var AnnotationBorderStyleType = {
+  SOLID: 1,
+  DASHED: 2,
+  BEVELED: 3,
+  INSET: 4,
+  UNDERLINE: 5
+};
+exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
+var StreamType = {
+  UNKNOWN: 0,
+  FLATE: 1,
+  LZW: 2,
+  DCT: 3,
+  JPX: 4,
+  JBIG: 5,
+  A85: 6,
+  AHX: 7,
+  CCF: 8,
+  RL: 9
+};
+exports.StreamType = StreamType;
+var FontType = {
+  UNKNOWN: 0,
+  TYPE1: 1,
+  TYPE1C: 2,
+  CIDFONTTYPE0: 3,
+  CIDFONTTYPE0C: 4,
+  TRUETYPE: 5,
+  CIDFONTTYPE2: 6,
+  TYPE3: 7,
+  OPENTYPE: 8,
+  TYPE0: 9,
+  MMTYPE1: 10
+};
+exports.FontType = FontType;
+var VerbosityLevel = {
+  ERRORS: 0,
+  WARNINGS: 1,
+  INFOS: 5
+};
+exports.VerbosityLevel = VerbosityLevel;
+var CMapCompressionType = {
+  NONE: 0,
+  BINARY: 1,
+  STREAM: 2
+};
+exports.CMapCompressionType = CMapCompressionType;
+var OPS = {
+  dependency: 1,
+  setLineWidth: 2,
+  setLineCap: 3,
+  setLineJoin: 4,
+  setMiterLimit: 5,
+  setDash: 6,
+  setRenderingIntent: 7,
+  setFlatness: 8,
+  setGState: 9,
+  save: 10,
+  restore: 11,
+  transform: 12,
+  moveTo: 13,
+  lineTo: 14,
+  curveTo: 15,
+  curveTo2: 16,
+  curveTo3: 17,
+  closePath: 18,
+  rectangle: 19,
+  stroke: 20,
+  closeStroke: 21,
+  fill: 22,
+  eoFill: 23,
+  fillStroke: 24,
+  eoFillStroke: 25,
+  closeFillStroke: 26,
+  closeEOFillStroke: 27,
+  endPath: 28,
+  clip: 29,
+  eoClip: 30,
+  beginText: 31,
+  endText: 32,
+  setCharSpacing: 33,
+  setWordSpacing: 34,
+  setHScale: 35,
+  setLeading: 36,
+  setFont: 37,
+  setTextRenderingMode: 38,
+  setTextRise: 39,
+  moveText: 40,
+  setLeadingMoveText: 41,
+  setTextMatrix: 42,
+  nextLine: 43,
+  showText: 44,
+  showSpacedText: 45,
+  nextLineShowText: 46,
+  nextLineSetSpacingShowText: 47,
+  setCharWidth: 48,
+  setCharWidthAndBounds: 49,
+  setStrokeColorSpace: 50,
+  setFillColorSpace: 51,
+  setStrokeColor: 52,
+  setStrokeColorN: 53,
+  setFillColor: 54,
+  setFillColorN: 55,
+  setStrokeGray: 56,
+  setFillGray: 57,
+  setStrokeRGBColor: 58,
+  setFillRGBColor: 59,
+  setStrokeCMYKColor: 60,
+  setFillCMYKColor: 61,
+  shadingFill: 62,
+  beginInlineImage: 63,
+  beginImageData: 64,
+  endInlineImage: 65,
+  paintXObject: 66,
+  markPoint: 67,
+  markPointProps: 68,
+  beginMarkedContent: 69,
+  beginMarkedContentProps: 70,
+  endMarkedContent: 71,
+  beginCompat: 72,
+  endCompat: 73,
+  paintFormXObjectBegin: 74,
+  paintFormXObjectEnd: 75,
+  beginGroup: 76,
+  endGroup: 77,
+  beginAnnotations: 78,
+  endAnnotations: 79,
+  beginAnnotation: 80,
+  endAnnotation: 81,
+  paintJpegXObject: 82,
+  paintImageMaskXObject: 83,
+  paintImageMaskXObjectGroup: 84,
+  paintImageXObject: 85,
+  paintInlineImageXObject: 86,
+  paintInlineImageXObjectGroup: 87,
+  paintImageXObjectRepeat: 88,
+  paintImageMaskXObjectRepeat: 89,
+  paintSolidColorImageMask: 90,
+  constructPath: 91
+};
+exports.OPS = OPS;
+var UNSUPPORTED_FEATURES = {
+  unknown: 'unknown',
+  forms: 'forms',
+  javaScript: 'javaScript',
+  smask: 'smask',
+  shadingPattern: 'shadingPattern',
+  font: 'font'
+};
+exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
+var PasswordResponses = {
+  NEED_PASSWORD: 1,
+  INCORRECT_PASSWORD: 2
+};
+exports.PasswordResponses = PasswordResponses;
+var verbosity = VerbosityLevel.WARNINGS;
+
+function setVerbosityLevel(level) {
+  if (Number.isInteger(level)) {
+    verbosity = level;
+  }
+}
+
+function getVerbosityLevel() {
+  return verbosity;
+}
+
+function info(msg) {
+  if (verbosity >= VerbosityLevel.INFOS) {
+    console.log('Info: ' + msg);
+  }
+}
+
+function warn(msg) {
+  if (verbosity >= VerbosityLevel.WARNINGS) {
+    console.log('Warning: ' + msg);
+  }
+}
+
+function unreachable(msg) {
+  throw new Error(msg);
+}
+
+function assert(cond, msg) {
+  if (!cond) {
+    unreachable(msg);
+  }
+}
+
+function isSameOrigin(baseUrl, otherUrl) {
+  try {
+    var base = new _url_polyfill.URL(baseUrl);
+
+    if (!base.origin || base.origin === 'null') {
+      return false;
+    }
+  } catch (e) {
+    return false;
+  }
+
+  var other = new _url_polyfill.URL(otherUrl, base);
+  return base.origin === other.origin;
+}
+
+function _isValidProtocol(url) {
+  if (!url) {
+    return false;
+  }
+
+  switch (url.protocol) {
+    case 'http:':
+    case 'https:':
+    case 'ftp:':
+    case 'mailto:':
+    case 'tel:':
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+function createValidAbsoluteUrl(url, baseUrl) {
+  if (!url) {
+    return null;
+  }
+
+  try {
+    var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url);
+
+    if (_isValidProtocol(absoluteUrl)) {
+      return absoluteUrl;
+    }
+  } catch (ex) {}
+
+  return null;
+}
+
+function shadow(obj, prop, value) {
+  Object.defineProperty(obj, prop, {
+    value: value,
+    enumerable: true,
+    configurable: true,
+    writable: false
+  });
+  return value;
+}
+
+var PasswordException = function PasswordExceptionClosure() {
+  function PasswordException(msg, code) {
+    this.name = 'PasswordException';
+    this.message = msg;
+    this.code = code;
+  }
+
+  PasswordException.prototype = new Error();
+  PasswordException.constructor = PasswordException;
+  return PasswordException;
+}();
+
+exports.PasswordException = PasswordException;
+
+var UnknownErrorException = function UnknownErrorExceptionClosure() {
+  function UnknownErrorException(msg, details) {
+    this.name = 'UnknownErrorException';
+    this.message = msg;
+    this.details = details;
+  }
+
+  UnknownErrorException.prototype = new Error();
+  UnknownErrorException.constructor = UnknownErrorException;
+  return UnknownErrorException;
+}();
+
+exports.UnknownErrorException = UnknownErrorException;
+
+var InvalidPDFException = function InvalidPDFExceptionClosure() {
+  function InvalidPDFException(msg) {
+    this.name = 'InvalidPDFException';
+    this.message = msg;
+  }
+
+  InvalidPDFException.prototype = new Error();
+  InvalidPDFException.constructor = InvalidPDFException;
+  return InvalidPDFException;
+}();
+
+exports.InvalidPDFException = InvalidPDFException;
+
+var MissingPDFException = function MissingPDFExceptionClosure() {
+  function MissingPDFException(msg) {
+    this.name = 'MissingPDFException';
+    this.message = msg;
+  }
+
+  MissingPDFException.prototype = new Error();
+  MissingPDFException.constructor = MissingPDFException;
+  return MissingPDFException;
+}();
+
+exports.MissingPDFException = MissingPDFException;
+
+var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
+  function UnexpectedResponseException(msg, status) {
+    this.name = 'UnexpectedResponseException';
+    this.message = msg;
+    this.status = status;
+  }
+
+  UnexpectedResponseException.prototype = new Error();
+  UnexpectedResponseException.constructor = UnexpectedResponseException;
+  return UnexpectedResponseException;
+}();
+
+exports.UnexpectedResponseException = UnexpectedResponseException;
+
+var FormatError = function FormatErrorClosure() {
+  function FormatError(msg) {
+    this.message = msg;
+  }
+
+  FormatError.prototype = new Error();
+  FormatError.prototype.name = 'FormatError';
+  FormatError.constructor = FormatError;
+  return FormatError;
+}();
+
+exports.FormatError = FormatError;
+
+var AbortException = function AbortExceptionClosure() {
+  function AbortException(msg) {
+    this.name = 'AbortException';
+    this.message = msg;
+  }
+
+  AbortException.prototype = new Error();
+  AbortException.constructor = AbortException;
+  return AbortException;
+}();
+
+exports.AbortException = AbortException;
+var NullCharactersRegExp = /\x00/g;
+
+function removeNullCharacters(str) {
+  if (typeof str !== 'string') {
+    warn('The argument for removeNullCharacters must be a string.');
+    return str;
+  }
+
+  return str.replace(NullCharactersRegExp, '');
+}
+
+function bytesToString(bytes) {
+  assert(bytes !== null && _typeof(bytes) === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
+  var length = bytes.length;
+  var MAX_ARGUMENT_COUNT = 8192;
+
+  if (length < MAX_ARGUMENT_COUNT) {
+    return String.fromCharCode.apply(null, bytes);
+  }
+
+  var strBuf = [];
+
+  for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+    var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+    var chunk = bytes.subarray(i, chunkEnd);
+    strBuf.push(String.fromCharCode.apply(null, chunk));
+  }
+
+  return strBuf.join('');
+}
+
+function stringToBytes(str) {
+  assert(typeof str === 'string', 'Invalid argument for stringToBytes');
+  var length = str.length;
+  var bytes = new Uint8Array(length);
+
+  for (var i = 0; i < length; ++i) {
+    bytes[i] = str.charCodeAt(i) & 0xFF;
+  }
+
+  return bytes;
+}
+
+function arrayByteLength(arr) {
+  if (arr.length !== undefined) {
+    return arr.length;
+  }
+
+  assert(arr.byteLength !== undefined);
+  return arr.byteLength;
+}
+
+function arraysToBytes(arr) {
+  if (arr.length === 1 && arr[0] instanceof Uint8Array) {
+    return arr[0];
+  }
+
+  var resultLength = 0;
+  var i,
+      ii = arr.length;
+  var item, itemLength;
+
+  for (i = 0; i < ii; i++) {
+    item = arr[i];
+    itemLength = arrayByteLength(item);
+    resultLength += itemLength;
+  }
+
+  var pos = 0;
+  var data = new Uint8Array(resultLength);
+
+  for (i = 0; i < ii; i++) {
+    item = arr[i];
+
+    if (!(item instanceof Uint8Array)) {
+      if (typeof item === 'string') {
+        item = stringToBytes(item);
+      } else {
+        item = new Uint8Array(item);
+      }
+    }
+
+    itemLength = item.byteLength;
+    data.set(item, pos);
+    pos += itemLength;
+  }
+
+  return data;
+}
+
+function string32(value) {
+  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+}
+
+function log2(x) {
+  if (x <= 0) {
+    return 0;
+  }
+
+  return Math.ceil(Math.log2(x));
+}
+
+function readInt8(data, start) {
+  return data[start] << 24 >> 24;
+}
+
+function readUint16(data, offset) {
+  return data[offset] << 8 | data[offset + 1];
+}
+
+function readUint32(data, offset) {
+  return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
+}
+
+function isLittleEndian() {
+  var buffer8 = new Uint8Array(4);
+  buffer8[0] = 1;
+  var view32 = new Uint32Array(buffer8.buffer, 0, 1);
+  return view32[0] === 1;
+}
+
+function isEvalSupported() {
+  try {
+    new Function('');
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+var Util = function UtilClosure() {
+  function Util() {}
+
+  var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
+
+  Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
+    rgbBuf[1] = r;
+    rgbBuf[3] = g;
+    rgbBuf[5] = b;
+    return rgbBuf.join('');
+  };
+
+  Util.transform = function Util_transform(m1, m2) {
+    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
+  };
+
+  Util.applyTransform = function Util_applyTransform(p, m) {
+    var xt = p[0] * m[0] + p[1] * m[2] + m[4];
+    var yt = p[0] * m[1] + p[1] * m[3] + m[5];
+    return [xt, yt];
+  };
+
+  Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+    var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+    return [xt, yt];
+  };
+
+  Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
+    var p1 = Util.applyTransform(r, m);
+    var p2 = Util.applyTransform(r.slice(2, 4), m);
+    var p3 = Util.applyTransform([r[0], r[3]], m);
+    var p4 = Util.applyTransform([r[2], r[1]], m);
+    return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
+  };
+
+  Util.inverseTransform = function Util_inverseTransform(m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+  };
+
+  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+    return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
+  };
+
+  Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
+    var transpose = [m[0], m[2], m[1], m[3]];
+    var a = m[0] * transpose[0] + m[1] * transpose[2];
+    var b = m[0] * transpose[1] + m[1] * transpose[3];
+    var c = m[2] * transpose[0] + m[3] * transpose[2];
+    var d = m[2] * transpose[1] + m[3] * transpose[3];
+    var first = (a + d) / 2;
+    var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+    var sx = first + second || 1;
+    var sy = first - second || 1;
+    return [Math.sqrt(sx), Math.sqrt(sy)];
+  };
+
+  Util.normalizeRect = function Util_normalizeRect(rect) {
+    var r = rect.slice(0);
+
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+
+    return r;
+  };
+
+  Util.intersect = function Util_intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    }
+
+    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+        result = [];
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return false;
+    }
+
+    if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return false;
+    }
+
+    return result;
+  };
+
+  return Util;
+}();
+
+exports.Util = Util;
+var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC];
+
+function stringToPDFString(str) {
+  var i,
+      n = str.length,
+      strBuf = [];
+
+  if (str[0] === '\xFE' && str[1] === '\xFF') {
+    for (i = 2; i < n; i += 2) {
+      strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
+    }
+  } else {
+    for (i = 0; i < n; ++i) {
+      var code = PDFStringTranslateTable[str.charCodeAt(i)];
+      strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+    }
+  }
+
+  return strBuf.join('');
+}
+
+function stringToUTF8String(str) {
+  return decodeURIComponent(escape(str));
+}
+
+function utf8StringToString(str) {
+  return unescape(encodeURIComponent(str));
+}
+
+function isEmptyObj(obj) {
+  for (var key in obj) {
+    return false;
+  }
+
+  return true;
+}
+
+function isBool(v) {
+  return typeof v === 'boolean';
+}
+
+function isNum(v) {
+  return typeof v === 'number';
+}
+
+function isString(v) {
+  return typeof v === 'string';
+}
+
+function isArrayBuffer(v) {
+  return _typeof(v) === 'object' && v !== null && v.byteLength !== undefined;
+}
+
+function isArrayEqual(arr1, arr2) {
+  if (arr1.length !== arr2.length) {
+    return false;
+  }
+
+  return arr1.every(function (element, index) {
+    return element === arr2[index];
+  });
+}
+
+function isSpace(ch) {
+  return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
+}
+
+function createPromiseCapability() {
+  var capability = Object.create(null);
+  var isSettled = false;
+  Object.defineProperty(capability, 'settled', {
+    get: function get() {
+      return isSettled;
+    }
+  });
+  capability.promise = new Promise(function (resolve, reject) {
+    capability.resolve = function (data) {
+      isSettled = true;
+      resolve(data);
+    };
+
+    capability.reject = function (reason) {
+      isSettled = true;
+      reject(reason);
+    };
+  });
+  return capability;
+}
+
+var createObjectURL = function createObjectURLClosure() {
+  var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+  return function createObjectURL(data, contentType) {
+    var forceDataSchema = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+    if (!forceDataSchema && _url_polyfill.URL.createObjectURL) {
+      var blob = new Blob([data], {
+        type: contentType
+      });
+      return _url_polyfill.URL.createObjectURL(blob);
+    }
+
+    var buffer = 'data:' + contentType + ';base64,';
+
+    for (var i = 0, ii = data.length; i < ii; i += 3) {
+      var b1 = data[i] & 0xFF;
+      var b2 = data[i + 1] & 0xFF;
+      var b3 = data[i + 2] & 0xFF;
+      var d1 = b1 >> 2,
+          d2 = (b1 & 3) << 4 | b2 >> 4;
+      var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
+      var d4 = i + 2 < ii ? b3 & 0x3F : 64;
+      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+    }
+
+    return buffer;
+  };
+}();
+
+exports.createObjectURL = createObjectURL;
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var globalScope = __w_pdfjs_require__(3);
+
+if (!globalScope._pdfjsCompatibilityChecked) {
+  globalScope._pdfjsCompatibilityChecked = true;
+
+  var isNodeJS = __w_pdfjs_require__(4);
+
+  var hasDOM = (typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object' && (typeof document === "undefined" ? "undefined" : _typeof(document)) === 'object';
+
+  (function checkNodeBtoa() {
+    if (globalScope.btoa || !isNodeJS()) {
+      return;
+    }
+
+    globalScope.btoa = function (chars) {
+      return Buffer.from(chars, 'binary').toString('base64');
+    };
+  })();
+
+  (function checkNodeAtob() {
+    if (globalScope.atob || !isNodeJS()) {
+      return;
+    }
+
+    globalScope.atob = function (input) {
+      return Buffer.from(input, 'base64').toString('binary');
+    };
+  })();
+
+  (function checkChildNodeRemove() {
+    if (!hasDOM) {
+      return;
+    }
+
+    if (typeof Element.prototype.remove !== 'undefined') {
+      return;
+    }
+
+    Element.prototype.remove = function () {
+      if (this.parentNode) {
+        this.parentNode.removeChild(this);
+      }
+    };
+  })();
+
+  (function checkDOMTokenListAddRemove() {
+    if (!hasDOM || isNodeJS()) {
+      return;
+    }
+
+    var div = document.createElement('div');
+    div.classList.add('testOne', 'testTwo');
+
+    if (div.classList.contains('testOne') === true && div.classList.contains('testTwo') === true) {
+      return;
+    }
+
+    var OriginalDOMTokenListAdd = DOMTokenList.prototype.add;
+    var OriginalDOMTokenListRemove = DOMTokenList.prototype.remove;
+
+    DOMTokenList.prototype.add = function () {
+      for (var _len = arguments.length, tokens = new Array(_len), _key = 0; _key < _len; _key++) {
+        tokens[_key] = arguments[_key];
+      }
+
+      for (var _i = 0, _tokens = tokens; _i < _tokens.length; _i++) {
+        var token = _tokens[_i];
+        OriginalDOMTokenListAdd.call(this, token);
+      }
+    };
+
+    DOMTokenList.prototype.remove = function () {
+      for (var _len2 = arguments.length, tokens = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
+        tokens[_key2] = arguments[_key2];
+      }
+
+      for (var _i2 = 0, _tokens2 = tokens; _i2 < _tokens2.length; _i2++) {
+        var token = _tokens2[_i2];
+        OriginalDOMTokenListRemove.call(this, token);
+      }
+    };
+  })();
+
+  (function checkDOMTokenListToggle() {
+    if (!hasDOM || isNodeJS()) {
+      return;
+    }
+
+    var div = document.createElement('div');
+
+    if (div.classList.toggle('test', 0) === false) {
+      return;
+    }
+
+    DOMTokenList.prototype.toggle = function (token) {
+      var force = arguments.length > 1 ? !!arguments[1] : !this.contains(token);
+      return this[force ? 'add' : 'remove'](token), force;
+    };
+  })();
+
+  (function checkStringStartsWith() {
+    if (String.prototype.startsWith) {
+      return;
+    }
+
+    __w_pdfjs_require__(5);
+  })();
+
+  (function checkStringEndsWith() {
+    if (String.prototype.endsWith) {
+      return;
+    }
+
+    __w_pdfjs_require__(36);
+  })();
+
+  (function checkStringIncludes() {
+    if (String.prototype.includes) {
+      return;
+    }
+
+    __w_pdfjs_require__(38);
+  })();
+
+  (function checkArrayIncludes() {
+    if (Array.prototype.includes) {
+      return;
+    }
+
+    __w_pdfjs_require__(40);
+  })();
+
+  (function checkArrayFrom() {
+    if (Array.from) {
+      return;
+    }
+
+    __w_pdfjs_require__(47);
+  })();
+
+  (function checkObjectAssign() {
+    if (Object.assign) {
+      return;
+    }
+
+    __w_pdfjs_require__(70);
+  })();
+
+  (function checkMathLog2() {
+    if (Math.log2) {
+      return;
+    }
+
+    Math.log2 = __w_pdfjs_require__(75);
+  })();
+
+  (function checkNumberIsNaN() {
+    if (Number.isNaN) {
+      return;
+    }
+
+    Number.isNaN = __w_pdfjs_require__(77);
+  })();
+
+  (function checkNumberIsInteger() {
+    if (Number.isInteger) {
+      return;
+    }
+
+    Number.isInteger = __w_pdfjs_require__(79);
+  })();
+
+  (function checkPromise() {
+    if (globalScope.Promise && globalScope.Promise.prototype && globalScope.Promise.prototype["finally"]) {
+      return;
+    }
+
+    globalScope.Promise = __w_pdfjs_require__(82);
+  })();
+
+  (function checkWeakMap() {
+    if (globalScope.WeakMap) {
+      return;
+    }
+
+    globalScope.WeakMap = __w_pdfjs_require__(102);
+  })();
+
+  (function checkWeakSet() {
+    if (globalScope.WeakSet) {
+      return;
+    }
+
+    globalScope.WeakSet = __w_pdfjs_require__(119);
+  })();
+
+  (function checkStringCodePointAt() {
+    if (String.codePointAt) {
+      return;
+    }
+
+    String.codePointAt = __w_pdfjs_require__(123);
+  })();
+
+  (function checkStringFromCodePoint() {
+    if (String.fromCodePoint) {
+      return;
+    }
+
+    String.fromCodePoint = __w_pdfjs_require__(125);
+  })();
+
+  (function checkSymbol() {
+    if (globalScope.Symbol) {
+      return;
+    }
+
+    __w_pdfjs_require__(127);
+  })();
+
+  (function checkStringPadStart() {
+    if (String.prototype.padStart) {
+      return;
+    }
+
+    __w_pdfjs_require__(134);
+  })();
+
+  (function checkStringPadEnd() {
+    if (String.prototype.padEnd) {
+      return;
+    }
+
+    __w_pdfjs_require__(138);
+  })();
+
+  (function checkObjectValues() {
+    if (Object.values) {
+      return;
+    }
+
+    Object.values = __w_pdfjs_require__(140);
+  })();
+}
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = typeof window !== 'undefined' && window.Math === Math ? window : typeof global !== 'undefined' && global.Math === Math ? global : typeof self !== 'undefined' && self.Math === Math ? self : {};
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+module.exports = function isNodeJS() {
+  return (typeof process === "undefined" ? "undefined" : _typeof(process)) === 'object' && process + '' === '[object process]' && !process.versions['nw'] && !process.versions['electron'];
+};
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(6);
+
+module.exports = __w_pdfjs_require__(9).String.startsWith;
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var toLength = __w_pdfjs_require__(28);
+
+var context = __w_pdfjs_require__(30);
+
+var STARTS_WITH = 'startsWith';
+var $startsWith = ''[STARTS_WITH];
+$export($export.P + $export.F * __w_pdfjs_require__(35)(STARTS_WITH), 'String', {
+  startsWith: function startsWith(searchString) {
+    var that = context(this, searchString, STARTS_WITH);
+    var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));
+    var search = String(searchString);
+    return $startsWith ? $startsWith.call(that, search, index) : that.slice(index, index + search.length) === search;
+  }
+});
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var core = __w_pdfjs_require__(9);
+
+var hide = __w_pdfjs_require__(10);
+
+var redefine = __w_pdfjs_require__(20);
+
+var ctx = __w_pdfjs_require__(26);
+
+var PROTOTYPE = 'prototype';
+
+var $export = function $export(type, name, source) {
+  var IS_FORCED = type & $export.F;
+  var IS_GLOBAL = type & $export.G;
+  var IS_STATIC = type & $export.S;
+  var IS_PROTO = type & $export.P;
+  var IS_BIND = type & $export.B;
+  var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];
+  var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});
+  var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
+  var key, own, out, exp;
+  if (IS_GLOBAL) source = name;
+
+  for (key in source) {
+    own = !IS_FORCED && target && target[key] !== undefined;
+    out = (own ? target : source)[key];
+    exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
+    if (target) redefine(target, key, out, type & $export.U);
+    if (exports[key] != out) hide(exports, key, exp);
+    if (IS_PROTO && expProto[key] != out) expProto[key] = out;
+  }
+};
+
+global.core = core;
+$export.F = 1;
+$export.G = 2;
+$export.S = 4;
+$export.P = 8;
+$export.B = 16;
+$export.W = 32;
+$export.U = 64;
+$export.R = 128;
+module.exports = $export;
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
+if (typeof __g == 'number') __g = global;
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var core = module.exports = {
+  version: '2.6.9'
+};
+if (typeof __e == 'number') __e = core;
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var dP = __w_pdfjs_require__(11);
+
+var createDesc = __w_pdfjs_require__(19);
+
+module.exports = __w_pdfjs_require__(15) ? function (object, key, value) {
+  return dP.f(object, key, createDesc(1, value));
+} : function (object, key, value) {
+  object[key] = value;
+  return object;
+};
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(12);
+
+var IE8_DOM_DEFINE = __w_pdfjs_require__(14);
+
+var toPrimitive = __w_pdfjs_require__(18);
+
+var dP = Object.defineProperty;
+exports.f = __w_pdfjs_require__(15) ? Object.defineProperty : function defineProperty(O, P, Attributes) {
+  anObject(O);
+  P = toPrimitive(P, true);
+  anObject(Attributes);
+  if (IE8_DOM_DEFINE) try {
+    return dP(O, P, Attributes);
+  } catch (e) {}
+  if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
+  if ('value' in Attributes) O[P] = Attributes.value;
+  return O;
+};
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+module.exports = function (it) {
+  if (!isObject(it)) throw TypeError(it + ' is not an object!');
+  return it;
+};
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+module.exports = function (it) {
+  return _typeof(it) === 'object' ? it !== null : typeof it === 'function';
+};
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = !__w_pdfjs_require__(15) && !__w_pdfjs_require__(16)(function () {
+  return Object.defineProperty(__w_pdfjs_require__(17)('div'), 'a', {
+    get: function get() {
+      return 7;
+    }
+  }).a != 7;
+});
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = !__w_pdfjs_require__(16)(function () {
+  return Object.defineProperty({}, 'a', {
+    get: function get() {
+      return 7;
+    }
+  }).a != 7;
+});
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (exec) {
+  try {
+    return !!exec();
+  } catch (e) {
+    return true;
+  }
+};
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var document = __w_pdfjs_require__(8).document;
+
+var is = isObject(document) && isObject(document.createElement);
+
+module.exports = function (it) {
+  return is ? document.createElement(it) : {};
+};
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+module.exports = function (it, S) {
+  if (!isObject(it)) return it;
+  var fn, val;
+  if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
+  if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
+  if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
+  throw TypeError("Can't convert object to primitive value");
+};
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (bitmap, value) {
+  return {
+    enumerable: !(bitmap & 1),
+    configurable: !(bitmap & 2),
+    writable: !(bitmap & 4),
+    value: value
+  };
+};
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var hide = __w_pdfjs_require__(10);
+
+var has = __w_pdfjs_require__(21);
+
+var SRC = __w_pdfjs_require__(22)('src');
+
+var $toString = __w_pdfjs_require__(23);
+
+var TO_STRING = 'toString';
+var TPL = ('' + $toString).split(TO_STRING);
+
+__w_pdfjs_require__(9).inspectSource = function (it) {
+  return $toString.call(it);
+};
+
+(module.exports = function (O, key, val, safe) {
+  var isFunction = typeof val == 'function';
+  if (isFunction) has(val, 'name') || hide(val, 'name', key);
+  if (O[key] === val) return;
+  if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
+
+  if (O === global) {
+    O[key] = val;
+  } else if (!safe) {
+    delete O[key];
+    hide(O, key, val);
+  } else if (O[key]) {
+    O[key] = val;
+  } else {
+    hide(O, key, val);
+  }
+})(Function.prototype, TO_STRING, function toString() {
+  return typeof this == 'function' && this[SRC] || $toString.call(this);
+});
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var hasOwnProperty = {}.hasOwnProperty;
+
+module.exports = function (it, key) {
+  return hasOwnProperty.call(it, key);
+};
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var id = 0;
+var px = Math.random();
+
+module.exports = function (key) {
+  return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
+};
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = __w_pdfjs_require__(24)('native-function-to-string', Function.toString);
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var core = __w_pdfjs_require__(9);
+
+var global = __w_pdfjs_require__(8);
+
+var SHARED = '__core-js_shared__';
+var store = global[SHARED] || (global[SHARED] = {});
+(module.exports = function (key, value) {
+  return store[key] || (store[key] = value !== undefined ? value : {});
+})('versions', []).push({
+  version: core.version,
+  mode: __w_pdfjs_require__(25) ? 'pure' : 'global',
+  copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
+});
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = false;
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var aFunction = __w_pdfjs_require__(27);
+
+module.exports = function (fn, that, length) {
+  aFunction(fn);
+  if (that === undefined) return fn;
+
+  switch (length) {
+    case 1:
+      return function (a) {
+        return fn.call(that, a);
+      };
+
+    case 2:
+      return function (a, b) {
+        return fn.call(that, a, b);
+      };
+
+    case 3:
+      return function (a, b, c) {
+        return fn.call(that, a, b, c);
+      };
+  }
+
+  return function () {
+    return fn.apply(that, arguments);
+  };
+};
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it) {
+  if (typeof it != 'function') throw TypeError(it + ' is not a function!');
+  return it;
+};
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(29);
+
+var min = Math.min;
+
+module.exports = function (it) {
+  return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0;
+};
+
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ceil = Math.ceil;
+var floor = Math.floor;
+
+module.exports = function (it) {
+  return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
+};
+
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isRegExp = __w_pdfjs_require__(31);
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function (that, searchString, NAME) {
+  if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!");
+  return String(defined(that));
+};
+
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var cof = __w_pdfjs_require__(32);
+
+var MATCH = __w_pdfjs_require__(33)('match');
+
+module.exports = function (it) {
+  var isRegExp;
+  return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');
+};
+
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toString = {}.toString;
+
+module.exports = function (it) {
+  return toString.call(it).slice(8, -1);
+};
+
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var store = __w_pdfjs_require__(24)('wks');
+
+var uid = __w_pdfjs_require__(22);
+
+var _Symbol = __w_pdfjs_require__(8).Symbol;
+
+var USE_SYMBOL = typeof _Symbol == 'function';
+
+var $exports = module.exports = function (name) {
+  return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : uid)('Symbol.' + name));
+};
+
+$exports.store = store;
+
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it) {
+  if (it == undefined) throw TypeError("Can't call method on  " + it);
+  return it;
+};
+
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var MATCH = __w_pdfjs_require__(33)('match');
+
+module.exports = function (KEY) {
+  var re = /./;
+
+  try {
+    '/./'[KEY](re);
+  } catch (e) {
+    try {
+      re[MATCH] = false;
+      return !'/./'[KEY](re);
+    } catch (f) {}
+  }
+
+  return true;
+};
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(37);
+
+module.exports = __w_pdfjs_require__(9).String.endsWith;
+
+/***/ }),
+/* 37 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var toLength = __w_pdfjs_require__(28);
+
+var context = __w_pdfjs_require__(30);
+
+var ENDS_WITH = 'endsWith';
+var $endsWith = ''[ENDS_WITH];
+$export($export.P + $export.F * __w_pdfjs_require__(35)(ENDS_WITH), 'String', {
+  endsWith: function endsWith(searchString) {
+    var that = context(this, searchString, ENDS_WITH);
+    var endPosition = arguments.length > 1 ? arguments[1] : undefined;
+    var len = toLength(that.length);
+    var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len);
+    var search = String(searchString);
+    return $endsWith ? $endsWith.call(that, search, end) : that.slice(end - search.length, end) === search;
+  }
+});
+
+/***/ }),
+/* 38 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(39);
+
+module.exports = __w_pdfjs_require__(9).String.includes;
+
+/***/ }),
+/* 39 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var context = __w_pdfjs_require__(30);
+
+var INCLUDES = 'includes';
+$export($export.P + $export.F * __w_pdfjs_require__(35)(INCLUDES), 'String', {
+  includes: function includes(searchString) {
+    return !!~context(this, searchString, INCLUDES).indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);
+  }
+});
+
+/***/ }),
+/* 40 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(41);
+
+module.exports = __w_pdfjs_require__(9).Array.includes;
+
+/***/ }),
+/* 41 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var $includes = __w_pdfjs_require__(42)(true);
+
+$export($export.P, 'Array', {
+  includes: function includes(el) {
+    return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
+  }
+});
+
+__w_pdfjs_require__(46)('includes');
+
+/***/ }),
+/* 42 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toIObject = __w_pdfjs_require__(43);
+
+var toLength = __w_pdfjs_require__(28);
+
+var toAbsoluteIndex = __w_pdfjs_require__(45);
+
+module.exports = function (IS_INCLUDES) {
+  return function ($this, el, fromIndex) {
+    var O = toIObject($this);
+    var length = toLength(O.length);
+    var index = toAbsoluteIndex(fromIndex, length);
+    var value;
+    if (IS_INCLUDES && el != el) while (length > index) {
+      value = O[index++];
+      if (value != value) return true;
+    } else for (; length > index; index++) {
+      if (IS_INCLUDES || index in O) {
+        if (O[index] === el) return IS_INCLUDES || index || 0;
+      }
+    }
+    return !IS_INCLUDES && -1;
+  };
+};
+
+/***/ }),
+/* 43 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var IObject = __w_pdfjs_require__(44);
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function (it) {
+  return IObject(defined(it));
+};
+
+/***/ }),
+/* 44 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(32);
+
+module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
+  return cof(it) == 'String' ? it.split('') : Object(it);
+};
+
+/***/ }),
+/* 45 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(29);
+
+var max = Math.max;
+var min = Math.min;
+
+module.exports = function (index, length) {
+  index = toInteger(index);
+  return index < 0 ? max(index + length, 0) : min(index, length);
+};
+
+/***/ }),
+/* 46 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var UNSCOPABLES = __w_pdfjs_require__(33)('unscopables');
+
+var ArrayProto = Array.prototype;
+if (ArrayProto[UNSCOPABLES] == undefined) __w_pdfjs_require__(10)(ArrayProto, UNSCOPABLES, {});
+
+module.exports = function (key) {
+  ArrayProto[UNSCOPABLES][key] = true;
+};
+
+/***/ }),
+/* 47 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(48);
+
+__w_pdfjs_require__(63);
+
+module.exports = __w_pdfjs_require__(9).Array.from;
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $at = __w_pdfjs_require__(49)(true);
+
+__w_pdfjs_require__(50)(String, 'String', function (iterated) {
+  this._t = String(iterated);
+  this._i = 0;
+}, function () {
+  var O = this._t;
+  var index = this._i;
+  var point;
+  if (index >= O.length) return {
+    value: undefined,
+    done: true
+  };
+  point = $at(O, index);
+  this._i += point.length;
+  return {
+    value: point,
+    done: false
+  };
+});
+
+/***/ }),
+/* 49 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(29);
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function (TO_STRING) {
+  return function (that, pos) {
+    var s = String(defined(that));
+    var i = toInteger(pos);
+    var l = s.length;
+    var a, b;
+    if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
+    a = s.charCodeAt(i);
+    return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
+  };
+};
+
+/***/ }),
+/* 50 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var LIBRARY = __w_pdfjs_require__(25);
+
+var $export = __w_pdfjs_require__(7);
+
+var redefine = __w_pdfjs_require__(20);
+
+var hide = __w_pdfjs_require__(10);
+
+var Iterators = __w_pdfjs_require__(51);
+
+var $iterCreate = __w_pdfjs_require__(52);
+
+var setToStringTag = __w_pdfjs_require__(60);
+
+var getPrototypeOf = __w_pdfjs_require__(61);
+
+var ITERATOR = __w_pdfjs_require__(33)('iterator');
+
+var BUGGY = !([].keys && 'next' in [].keys());
+var FF_ITERATOR = '@@iterator';
+var KEYS = 'keys';
+var VALUES = 'values';
+
+var returnThis = function returnThis() {
+  return this;
+};
+
+module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
+  $iterCreate(Constructor, NAME, next);
+
+  var getMethod = function getMethod(kind) {
+    if (!BUGGY && kind in proto) return proto[kind];
+
+    switch (kind) {
+      case KEYS:
+        return function keys() {
+          return new Constructor(this, kind);
+        };
+
+      case VALUES:
+        return function values() {
+          return new Constructor(this, kind);
+        };
+    }
+
+    return function entries() {
+      return new Constructor(this, kind);
+    };
+  };
+
+  var TAG = NAME + ' Iterator';
+  var DEF_VALUES = DEFAULT == VALUES;
+  var VALUES_BUG = false;
+  var proto = Base.prototype;
+  var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
+  var $default = $native || getMethod(DEFAULT);
+  var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
+  var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
+  var methods, key, IteratorPrototype;
+
+  if ($anyNative) {
+    IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
+
+    if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
+      setToStringTag(IteratorPrototype, TAG, true);
+      if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);
+    }
+  }
+
+  if (DEF_VALUES && $native && $native.name !== VALUES) {
+    VALUES_BUG = true;
+
+    $default = function values() {
+      return $native.call(this);
+    };
+  }
+
+  if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
+    hide(proto, ITERATOR, $default);
+  }
+
+  Iterators[NAME] = $default;
+  Iterators[TAG] = returnThis;
+
+  if (DEFAULT) {
+    methods = {
+      values: DEF_VALUES ? $default : getMethod(VALUES),
+      keys: IS_SET ? $default : getMethod(KEYS),
+      entries: $entries
+    };
+    if (FORCED) for (key in methods) {
+      if (!(key in proto)) redefine(proto, key, methods[key]);
+    } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
+  }
+
+  return methods;
+};
+
+/***/ }),
+/* 51 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = {};
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var create = __w_pdfjs_require__(53);
+
+var descriptor = __w_pdfjs_require__(19);
+
+var setToStringTag = __w_pdfjs_require__(60);
+
+var IteratorPrototype = {};
+
+__w_pdfjs_require__(10)(IteratorPrototype, __w_pdfjs_require__(33)('iterator'), function () {
+  return this;
+});
+
+module.exports = function (Constructor, NAME, next) {
+  Constructor.prototype = create(IteratorPrototype, {
+    next: descriptor(1, next)
+  });
+  setToStringTag(Constructor, NAME + ' Iterator');
+};
+
+/***/ }),
+/* 53 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(12);
+
+var dPs = __w_pdfjs_require__(54);
+
+var enumBugKeys = __w_pdfjs_require__(58);
+
+var IE_PROTO = __w_pdfjs_require__(57)('IE_PROTO');
+
+var Empty = function Empty() {};
+
+var PROTOTYPE = 'prototype';
+
+var _createDict = function createDict() {
+  var iframe = __w_pdfjs_require__(17)('iframe');
+
+  var i = enumBugKeys.length;
+  var lt = '<';
+  var gt = '>';
+  var iframeDocument;
+  iframe.style.display = 'none';
+
+  __w_pdfjs_require__(59).appendChild(iframe);
+
+  iframe.src = 'javascript:';
+  iframeDocument = iframe.contentWindow.document;
+  iframeDocument.open();
+  iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
+  iframeDocument.close();
+  _createDict = iframeDocument.F;
+
+  while (i--) {
+    delete _createDict[PROTOTYPE][enumBugKeys[i]];
+  }
+
+  return _createDict();
+};
+
+module.exports = Object.create || function create(O, Properties) {
+  var result;
+
+  if (O !== null) {
+    Empty[PROTOTYPE] = anObject(O);
+    result = new Empty();
+    Empty[PROTOTYPE] = null;
+    result[IE_PROTO] = O;
+  } else result = _createDict();
+
+  return Properties === undefined ? result : dPs(result, Properties);
+};
+
+/***/ }),
+/* 54 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var dP = __w_pdfjs_require__(11);
+
+var anObject = __w_pdfjs_require__(12);
+
+var getKeys = __w_pdfjs_require__(55);
+
+module.exports = __w_pdfjs_require__(15) ? Object.defineProperties : function defineProperties(O, Properties) {
+  anObject(O);
+  var keys = getKeys(Properties);
+  var length = keys.length;
+  var i = 0;
+  var P;
+
+  while (length > i) {
+    dP.f(O, P = keys[i++], Properties[P]);
+  }
+
+  return O;
+};
+
+/***/ }),
+/* 55 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $keys = __w_pdfjs_require__(56);
+
+var enumBugKeys = __w_pdfjs_require__(58);
+
+module.exports = Object.keys || function keys(O) {
+  return $keys(O, enumBugKeys);
+};
+
+/***/ }),
+/* 56 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var has = __w_pdfjs_require__(21);
+
+var toIObject = __w_pdfjs_require__(43);
+
+var arrayIndexOf = __w_pdfjs_require__(42)(false);
+
+var IE_PROTO = __w_pdfjs_require__(57)('IE_PROTO');
+
+module.exports = function (object, names) {
+  var O = toIObject(object);
+  var i = 0;
+  var result = [];
+  var key;
+
+  for (key in O) {
+    if (key != IE_PROTO) has(O, key) && result.push(key);
+  }
+
+  while (names.length > i) {
+    if (has(O, key = names[i++])) {
+      ~arrayIndexOf(result, key) || result.push(key);
+    }
+  }
+
+  return result;
+};
+
+/***/ }),
+/* 57 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var shared = __w_pdfjs_require__(24)('keys');
+
+var uid = __w_pdfjs_require__(22);
+
+module.exports = function (key) {
+  return shared[key] || (shared[key] = uid(key));
+};
+
+/***/ }),
+/* 58 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
+
+/***/ }),
+/* 59 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var document = __w_pdfjs_require__(8).document;
+
+module.exports = document && document.documentElement;
+
+/***/ }),
+/* 60 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var def = __w_pdfjs_require__(11).f;
+
+var has = __w_pdfjs_require__(21);
+
+var TAG = __w_pdfjs_require__(33)('toStringTag');
+
+module.exports = function (it, tag, stat) {
+  if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, {
+    configurable: true,
+    value: tag
+  });
+};
+
+/***/ }),
+/* 61 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var has = __w_pdfjs_require__(21);
+
+var toObject = __w_pdfjs_require__(62);
+
+var IE_PROTO = __w_pdfjs_require__(57)('IE_PROTO');
+
+var ObjectProto = Object.prototype;
+
+module.exports = Object.getPrototypeOf || function (O) {
+  O = toObject(O);
+  if (has(O, IE_PROTO)) return O[IE_PROTO];
+
+  if (typeof O.constructor == 'function' && O instanceof O.constructor) {
+    return O.constructor.prototype;
+  }
+
+  return O instanceof Object ? ObjectProto : null;
+};
+
+/***/ }),
+/* 62 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function (it) {
+  return Object(defined(it));
+};
+
+/***/ }),
+/* 63 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(26);
+
+var $export = __w_pdfjs_require__(7);
+
+var toObject = __w_pdfjs_require__(62);
+
+var call = __w_pdfjs_require__(64);
+
+var isArrayIter = __w_pdfjs_require__(65);
+
+var toLength = __w_pdfjs_require__(28);
+
+var createProperty = __w_pdfjs_require__(66);
+
+var getIterFn = __w_pdfjs_require__(67);
+
+$export($export.S + $export.F * !__w_pdfjs_require__(69)(function (iter) {
+  Array.from(iter);
+}), 'Array', {
+  from: function from(arrayLike) {
+    var O = toObject(arrayLike);
+    var C = typeof this == 'function' ? this : Array;
+    var aLen = arguments.length;
+    var mapfn = aLen > 1 ? arguments[1] : undefined;
+    var mapping = mapfn !== undefined;
+    var index = 0;
+    var iterFn = getIterFn(O);
+    var length, result, step, iterator;
+    if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);
+
+    if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {
+      for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
+        createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);
+      }
+    } else {
+      length = toLength(O.length);
+
+      for (result = new C(length); length > index; index++) {
+        createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
+      }
+    }
+
+    result.length = index;
+    return result;
+  }
+});
+
+/***/ }),
+/* 64 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(12);
+
+module.exports = function (iterator, fn, value, entries) {
+  try {
+    return entries ? fn(anObject(value)[0], value[1]) : fn(value);
+  } catch (e) {
+    var ret = iterator['return'];
+    if (ret !== undefined) anObject(ret.call(iterator));
+    throw e;
+  }
+};
+
+/***/ }),
+/* 65 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var Iterators = __w_pdfjs_require__(51);
+
+var ITERATOR = __w_pdfjs_require__(33)('iterator');
+
+var ArrayProto = Array.prototype;
+
+module.exports = function (it) {
+  return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
+};
+
+/***/ }),
+/* 66 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $defineProperty = __w_pdfjs_require__(11);
+
+var createDesc = __w_pdfjs_require__(19);
+
+module.exports = function (object, index, value) {
+  if (index in object) $defineProperty.f(object, index, createDesc(0, value));else object[index] = value;
+};
+
+/***/ }),
+/* 67 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var classof = __w_pdfjs_require__(68);
+
+var ITERATOR = __w_pdfjs_require__(33)('iterator');
+
+var Iterators = __w_pdfjs_require__(51);
+
+module.exports = __w_pdfjs_require__(9).getIteratorMethod = function (it) {
+  if (it != undefined) return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)];
+};
+
+/***/ }),
+/* 68 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(32);
+
+var TAG = __w_pdfjs_require__(33)('toStringTag');
+
+var ARG = cof(function () {
+  return arguments;
+}()) == 'Arguments';
+
+var tryGet = function tryGet(it, key) {
+  try {
+    return it[key];
+  } catch (e) {}
+};
+
+module.exports = function (it) {
+  var O, T, B;
+  return it === undefined ? 'Undefined' : it === null ? 'Null' : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T : ARG ? cof(O) : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
+};
+
+/***/ }),
+/* 69 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ITERATOR = __w_pdfjs_require__(33)('iterator');
+
+var SAFE_CLOSING = false;
+
+try {
+  var riter = [7][ITERATOR]();
+
+  riter['return'] = function () {
+    SAFE_CLOSING = true;
+  };
+
+  Array.from(riter, function () {
+    throw 2;
+  });
+} catch (e) {}
+
+module.exports = function (exec, skipClosing) {
+  if (!skipClosing && !SAFE_CLOSING) return false;
+  var safe = false;
+
+  try {
+    var arr = [7];
+    var iter = arr[ITERATOR]();
+
+    iter.next = function () {
+      return {
+        done: safe = true
+      };
+    };
+
+    arr[ITERATOR] = function () {
+      return iter;
+    };
+
+    exec(arr);
+  } catch (e) {}
+
+  return safe;
+};
+
+/***/ }),
+/* 70 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(71);
+
+module.exports = __w_pdfjs_require__(9).Object.assign;
+
+/***/ }),
+/* 71 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+$export($export.S + $export.F, 'Object', {
+  assign: __w_pdfjs_require__(72)
+});
+
+/***/ }),
+/* 72 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var DESCRIPTORS = __w_pdfjs_require__(15);
+
+var getKeys = __w_pdfjs_require__(55);
+
+var gOPS = __w_pdfjs_require__(73);
+
+var pIE = __w_pdfjs_require__(74);
+
+var toObject = __w_pdfjs_require__(62);
+
+var IObject = __w_pdfjs_require__(44);
+
+var $assign = Object.assign;
+module.exports = !$assign || __w_pdfjs_require__(16)(function () {
+  var A = {};
+  var B = {};
+  var S = Symbol();
+  var K = 'abcdefghijklmnopqrst';
+  A[S] = 7;
+  K.split('').forEach(function (k) {
+    B[k] = k;
+  });
+  return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
+}) ? function assign(target, source) {
+  var T = toObject(target);
+  var aLen = arguments.length;
+  var index = 1;
+  var getSymbols = gOPS.f;
+  var isEnum = pIE.f;
+
+  while (aLen > index) {
+    var S = IObject(arguments[index++]);
+    var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);
+    var length = keys.length;
+    var j = 0;
+    var key;
+
+    while (length > j) {
+      key = keys[j++];
+      if (!DESCRIPTORS || isEnum.call(S, key)) T[key] = S[key];
+    }
+  }
+
+  return T;
+} : $assign;
+
+/***/ }),
+/* 73 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = Object.getOwnPropertySymbols;
+
+/***/ }),
+/* 74 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = {}.propertyIsEnumerable;
+
+/***/ }),
+/* 75 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(76);
+
+module.exports = __w_pdfjs_require__(9).Math.log2;
+
+/***/ }),
+/* 76 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+$export($export.S, 'Math', {
+  log2: function log2(x) {
+    return Math.log(x) / Math.LN2;
+  }
+});
+
+/***/ }),
+/* 77 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(78);
+
+module.exports = __w_pdfjs_require__(9).Number.isNaN;
+
+/***/ }),
+/* 78 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+$export($export.S, 'Number', {
+  isNaN: function isNaN(number) {
+    return number != number;
+  }
+});
+
+/***/ }),
+/* 79 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(80);
+
+module.exports = __w_pdfjs_require__(9).Number.isInteger;
+
+/***/ }),
+/* 80 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+$export($export.S, 'Number', {
+  isInteger: __w_pdfjs_require__(81)
+});
+
+/***/ }),
+/* 81 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var floor = Math.floor;
+
+module.exports = function isInteger(it) {
+  return !isObject(it) && isFinite(it) && floor(it) === it;
+};
+
+/***/ }),
+/* 82 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(83);
+
+__w_pdfjs_require__(48);
+
+__w_pdfjs_require__(84);
+
+__w_pdfjs_require__(87);
+
+__w_pdfjs_require__(100);
+
+__w_pdfjs_require__(101);
+
+module.exports = __w_pdfjs_require__(9).Promise;
+
+/***/ }),
+/* 83 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var classof = __w_pdfjs_require__(68);
+
+var test = {};
+test[__w_pdfjs_require__(33)('toStringTag')] = 'z';
+
+if (test + '' != '[object z]') {
+  __w_pdfjs_require__(20)(Object.prototype, 'toString', function toString() {
+    return '[object ' + classof(this) + ']';
+  }, true);
+}
+
+/***/ }),
+/* 84 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $iterators = __w_pdfjs_require__(85);
+
+var getKeys = __w_pdfjs_require__(55);
+
+var redefine = __w_pdfjs_require__(20);
+
+var global = __w_pdfjs_require__(8);
+
+var hide = __w_pdfjs_require__(10);
+
+var Iterators = __w_pdfjs_require__(51);
+
+var wks = __w_pdfjs_require__(33);
+
+var ITERATOR = wks('iterator');
+var TO_STRING_TAG = wks('toStringTag');
+var ArrayValues = Iterators.Array;
+var DOMIterables = {
+  CSSRuleList: true,
+  CSSStyleDeclaration: false,
+  CSSValueList: false,
+  ClientRectList: false,
+  DOMRectList: false,
+  DOMStringList: false,
+  DOMTokenList: true,
+  DataTransferItemList: false,
+  FileList: false,
+  HTMLAllCollection: false,
+  HTMLCollection: false,
+  HTMLFormElement: false,
+  HTMLSelectElement: false,
+  MediaList: true,
+  MimeTypeArray: false,
+  NamedNodeMap: false,
+  NodeList: true,
+  PaintRequestList: false,
+  Plugin: false,
+  PluginArray: false,
+  SVGLengthList: false,
+  SVGNumberList: false,
+  SVGPathSegList: false,
+  SVGPointList: false,
+  SVGStringList: false,
+  SVGTransformList: false,
+  SourceBufferList: false,
+  StyleSheetList: true,
+  TextTrackCueList: false,
+  TextTrackList: false,
+  TouchList: false
+};
+
+for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {
+  var NAME = collections[i];
+  var explicit = DOMIterables[NAME];
+  var Collection = global[NAME];
+  var proto = Collection && Collection.prototype;
+  var key;
+
+  if (proto) {
+    if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);
+    if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);
+    Iterators[NAME] = ArrayValues;
+    if (explicit) for (key in $iterators) {
+      if (!proto[key]) redefine(proto, key, $iterators[key], true);
+    }
+  }
+}
+
+/***/ }),
+/* 85 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var addToUnscopables = __w_pdfjs_require__(46);
+
+var step = __w_pdfjs_require__(86);
+
+var Iterators = __w_pdfjs_require__(51);
+
+var toIObject = __w_pdfjs_require__(43);
+
+module.exports = __w_pdfjs_require__(50)(Array, 'Array', function (iterated, kind) {
+  this._t = toIObject(iterated);
+  this._i = 0;
+  this._k = kind;
+}, function () {
+  var O = this._t;
+  var kind = this._k;
+  var index = this._i++;
+
+  if (!O || index >= O.length) {
+    this._t = undefined;
+    return step(1);
+  }
+
+  if (kind == 'keys') return step(0, index);
+  if (kind == 'values') return step(0, O[index]);
+  return step(0, [index, O[index]]);
+}, 'values');
+Iterators.Arguments = Iterators.Array;
+addToUnscopables('keys');
+addToUnscopables('values');
+addToUnscopables('entries');
+
+/***/ }),
+/* 86 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (done, value) {
+  return {
+    value: value,
+    done: !!done
+  };
+};
+
+/***/ }),
+/* 87 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var LIBRARY = __w_pdfjs_require__(25);
+
+var global = __w_pdfjs_require__(8);
+
+var ctx = __w_pdfjs_require__(26);
+
+var classof = __w_pdfjs_require__(68);
+
+var $export = __w_pdfjs_require__(7);
+
+var isObject = __w_pdfjs_require__(13);
+
+var aFunction = __w_pdfjs_require__(27);
+
+var anInstance = __w_pdfjs_require__(88);
+
+var forOf = __w_pdfjs_require__(89);
+
+var speciesConstructor = __w_pdfjs_require__(90);
+
+var task = __w_pdfjs_require__(91).set;
+
+var microtask = __w_pdfjs_require__(93)();
+
+var newPromiseCapabilityModule = __w_pdfjs_require__(94);
+
+var perform = __w_pdfjs_require__(95);
+
+var userAgent = __w_pdfjs_require__(96);
+
+var promiseResolve = __w_pdfjs_require__(97);
+
+var PROMISE = 'Promise';
+var TypeError = global.TypeError;
+var process = global.process;
+var versions = process && process.versions;
+var v8 = versions && versions.v8 || '';
+var $Promise = global[PROMISE];
+var isNode = classof(process) == 'process';
+
+var empty = function empty() {};
+
+var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
+var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
+var USE_NATIVE = !!function () {
+  try {
+    var promise = $Promise.resolve(1);
+
+    var FakePromise = (promise.constructor = {})[__w_pdfjs_require__(33)('species')] = function (exec) {
+      exec(empty, empty);
+    };
+
+    return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise && v8.indexOf('6.6') !== 0 && userAgent.indexOf('Chrome/66') === -1;
+  } catch (e) {}
+}();
+
+var isThenable = function isThenable(it) {
+  var then;
+  return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
+};
+
+var notify = function notify(promise, isReject) {
+  if (promise._n) return;
+  promise._n = true;
+  var chain = promise._c;
+  microtask(function () {
+    var value = promise._v;
+    var ok = promise._s == 1;
+    var i = 0;
+
+    var run = function run(reaction) {
+      var handler = ok ? reaction.ok : reaction.fail;
+      var resolve = reaction.resolve;
+      var reject = reaction.reject;
+      var domain = reaction.domain;
+      var result, then, exited;
+
+      try {
+        if (handler) {
+          if (!ok) {
+            if (promise._h == 2) onHandleUnhandled(promise);
+            promise._h = 1;
+          }
+
+          if (handler === true) result = value;else {
+            if (domain) domain.enter();
+            result = handler(value);
+
+            if (domain) {
+              domain.exit();
+              exited = true;
+            }
+          }
+
+          if (result === reaction.promise) {
+            reject(TypeError('Promise-chain cycle'));
+          } else if (then = isThenable(result)) {
+            then.call(result, resolve, reject);
+          } else resolve(result);
+        } else reject(value);
+      } catch (e) {
+        if (domain && !exited) domain.exit();
+        reject(e);
+      }
+    };
+
+    while (chain.length > i) {
+      run(chain[i++]);
+    }
+
+    promise._c = [];
+    promise._n = false;
+    if (isReject && !promise._h) onUnhandled(promise);
+  });
+};
+
+var onUnhandled = function onUnhandled(promise) {
+  task.call(global, function () {
+    var value = promise._v;
+    var unhandled = isUnhandled(promise);
+    var result, handler, console;
+
+    if (unhandled) {
+      result = perform(function () {
+        if (isNode) {
+          process.emit('unhandledRejection', value, promise);
+        } else if (handler = global.onunhandledrejection) {
+          handler({
+            promise: promise,
+            reason: value
+          });
+        } else if ((console = global.console) && console.error) {
+          console.error('Unhandled promise rejection', value);
+        }
+      });
+      promise._h = isNode || isUnhandled(promise) ? 2 : 1;
+    }
+
+    promise._a = undefined;
+    if (unhandled && result.e) throw result.v;
+  });
+};
+
+var isUnhandled = function isUnhandled(promise) {
+  return promise._h !== 1 && (promise._a || promise._c).length === 0;
+};
+
+var onHandleUnhandled = function onHandleUnhandled(promise) {
+  task.call(global, function () {
+    var handler;
+
+    if (isNode) {
+      process.emit('rejectionHandled', promise);
+    } else if (handler = global.onrejectionhandled) {
+      handler({
+        promise: promise,
+        reason: promise._v
+      });
+    }
+  });
+};
+
+var $reject = function $reject(value) {
+  var promise = this;
+  if (promise._d) return;
+  promise._d = true;
+  promise = promise._w || promise;
+  promise._v = value;
+  promise._s = 2;
+  if (!promise._a) promise._a = promise._c.slice();
+  notify(promise, true);
+};
+
+var $resolve = function $resolve(value) {
+  var promise = this;
+  var then;
+  if (promise._d) return;
+  promise._d = true;
+  promise = promise._w || promise;
+
+  try {
+    if (promise === value) throw TypeError("Promise can't be resolved itself");
+
+    if (then = isThenable(value)) {
+      microtask(function () {
+        var wrapper = {
+          _w: promise,
+          _d: false
+        };
+
+        try {
+          then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
+        } catch (e) {
+          $reject.call(wrapper, e);
+        }
+      });
+    } else {
+      promise._v = value;
+      promise._s = 1;
+      notify(promise, false);
+    }
+  } catch (e) {
+    $reject.call({
+      _w: promise,
+      _d: false
+    }, e);
+  }
+};
+
+if (!USE_NATIVE) {
+  $Promise = function Promise(executor) {
+    anInstance(this, $Promise, PROMISE, '_h');
+    aFunction(executor);
+    Internal.call(this);
+
+    try {
+      executor(ctx($resolve, this, 1), ctx($reject, this, 1));
+    } catch (err) {
+      $reject.call(this, err);
+    }
+  };
+
+  Internal = function Promise(executor) {
+    this._c = [];
+    this._a = undefined;
+    this._s = 0;
+    this._d = false;
+    this._v = undefined;
+    this._h = 0;
+    this._n = false;
+  };
+
+  Internal.prototype = __w_pdfjs_require__(98)($Promise.prototype, {
+    then: function then(onFulfilled, onRejected) {
+      var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
+      reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
+      reaction.fail = typeof onRejected == 'function' && onRejected;
+      reaction.domain = isNode ? process.domain : undefined;
+
+      this._c.push(reaction);
+
+      if (this._a) this._a.push(reaction);
+      if (this._s) notify(this, false);
+      return reaction.promise;
+    },
+    'catch': function _catch(onRejected) {
+      return this.then(undefined, onRejected);
+    }
+  });
+
+  OwnPromiseCapability = function OwnPromiseCapability() {
+    var promise = new Internal();
+    this.promise = promise;
+    this.resolve = ctx($resolve, promise, 1);
+    this.reject = ctx($reject, promise, 1);
+  };
+
+  newPromiseCapabilityModule.f = newPromiseCapability = function newPromiseCapability(C) {
+    return C === $Promise || C === Wrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C);
+  };
+}
+
+$export($export.G + $export.W + $export.F * !USE_NATIVE, {
+  Promise: $Promise
+});
+
+__w_pdfjs_require__(60)($Promise, PROMISE);
+
+__w_pdfjs_require__(99)(PROMISE);
+
+Wrapper = __w_pdfjs_require__(9)[PROMISE];
+$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
+  reject: function reject(r) {
+    var capability = newPromiseCapability(this);
+    var $$reject = capability.reject;
+    $$reject(r);
+    return capability.promise;
+  }
+});
+$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
+  resolve: function resolve(x) {
+    return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);
+  }
+});
+$export($export.S + $export.F * !(USE_NATIVE && __w_pdfjs_require__(69)(function (iter) {
+  $Promise.all(iter)['catch'](empty);
+})), PROMISE, {
+  all: function all(iterable) {
+    var C = this;
+    var capability = newPromiseCapability(C);
+    var resolve = capability.resolve;
+    var reject = capability.reject;
+    var result = perform(function () {
+      var values = [];
+      var index = 0;
+      var remaining = 1;
+      forOf(iterable, false, function (promise) {
+        var $index = index++;
+        var alreadyCalled = false;
+        values.push(undefined);
+        remaining++;
+        C.resolve(promise).then(function (value) {
+          if (alreadyCalled) return;
+          alreadyCalled = true;
+          values[$index] = value;
+          --remaining || resolve(values);
+        }, reject);
+      });
+      --remaining || resolve(values);
+    });
+    if (result.e) reject(result.v);
+    return capability.promise;
+  },
+  race: function race(iterable) {
+    var C = this;
+    var capability = newPromiseCapability(C);
+    var reject = capability.reject;
+    var result = perform(function () {
+      forOf(iterable, false, function (promise) {
+        C.resolve(promise).then(capability.resolve, reject);
+      });
+    });
+    if (result.e) reject(result.v);
+    return capability.promise;
+  }
+});
+
+/***/ }),
+/* 88 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it, Constructor, name, forbiddenField) {
+  if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) {
+    throw TypeError(name + ': incorrect invocation!');
+  }
+
+  return it;
+};
+
+/***/ }),
+/* 89 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(26);
+
+var call = __w_pdfjs_require__(64);
+
+var isArrayIter = __w_pdfjs_require__(65);
+
+var anObject = __w_pdfjs_require__(12);
+
+var toLength = __w_pdfjs_require__(28);
+
+var getIterFn = __w_pdfjs_require__(67);
+
+var BREAK = {};
+var RETURN = {};
+
+var _exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
+  var iterFn = ITERATOR ? function () {
+    return iterable;
+  } : getIterFn(iterable);
+  var f = ctx(fn, that, entries ? 2 : 1);
+  var index = 0;
+  var length, step, iterator, result;
+  if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
+  if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {
+    result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
+    if (result === BREAK || result === RETURN) return result;
+  } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
+    result = call(iterator, f, step.value, entries);
+    if (result === BREAK || result === RETURN) return result;
+  }
+};
+
+_exports.BREAK = BREAK;
+_exports.RETURN = RETURN;
+
+/***/ }),
+/* 90 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(12);
+
+var aFunction = __w_pdfjs_require__(27);
+
+var SPECIES = __w_pdfjs_require__(33)('species');
+
+module.exports = function (O, D) {
+  var C = anObject(O).constructor;
+  var S;
+  return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
+};
+
+/***/ }),
+/* 91 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(26);
+
+var invoke = __w_pdfjs_require__(92);
+
+var html = __w_pdfjs_require__(59);
+
+var cel = __w_pdfjs_require__(17);
+
+var global = __w_pdfjs_require__(8);
+
+var process = global.process;
+var setTask = global.setImmediate;
+var clearTask = global.clearImmediate;
+var MessageChannel = global.MessageChannel;
+var Dispatch = global.Dispatch;
+var counter = 0;
+var queue = {};
+var ONREADYSTATECHANGE = 'onreadystatechange';
+var defer, channel, port;
+
+var run = function run() {
+  var id = +this;
+
+  if (queue.hasOwnProperty(id)) {
+    var fn = queue[id];
+    delete queue[id];
+    fn();
+  }
+};
+
+var listener = function listener(event) {
+  run.call(event.data);
+};
+
+if (!setTask || !clearTask) {
+  setTask = function setImmediate(fn) {
+    var args = [];
+    var i = 1;
+
+    while (arguments.length > i) {
+      args.push(arguments[i++]);
+    }
+
+    queue[++counter] = function () {
+      invoke(typeof fn == 'function' ? fn : Function(fn), args);
+    };
+
+    defer(counter);
+    return counter;
+  };
+
+  clearTask = function clearImmediate(id) {
+    delete queue[id];
+  };
+
+  if (__w_pdfjs_require__(32)(process) == 'process') {
+    defer = function defer(id) {
+      process.nextTick(ctx(run, id, 1));
+    };
+  } else if (Dispatch && Dispatch.now) {
+    defer = function defer(id) {
+      Dispatch.now(ctx(run, id, 1));
+    };
+  } else if (MessageChannel) {
+    channel = new MessageChannel();
+    port = channel.port2;
+    channel.port1.onmessage = listener;
+    defer = ctx(port.postMessage, port, 1);
+  } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
+    defer = function defer(id) {
+      global.postMessage(id + '', '*');
+    };
+
+    global.addEventListener('message', listener, false);
+  } else if (ONREADYSTATECHANGE in cel('script')) {
+    defer = function defer(id) {
+      html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
+        html.removeChild(this);
+        run.call(id);
+      };
+    };
+  } else {
+    defer = function defer(id) {
+      setTimeout(ctx(run, id, 1), 0);
+    };
+  }
+}
+
+module.exports = {
+  set: setTask,
+  clear: clearTask
+};
+
+/***/ }),
+/* 92 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (fn, args, that) {
+  var un = that === undefined;
+
+  switch (args.length) {
+    case 0:
+      return un ? fn() : fn.call(that);
+
+    case 1:
+      return un ? fn(args[0]) : fn.call(that, args[0]);
+
+    case 2:
+      return un ? fn(args[0], args[1]) : fn.call(that, args[0], args[1]);
+
+    case 3:
+      return un ? fn(args[0], args[1], args[2]) : fn.call(that, args[0], args[1], args[2]);
+
+    case 4:
+      return un ? fn(args[0], args[1], args[2], args[3]) : fn.call(that, args[0], args[1], args[2], args[3]);
+  }
+
+  return fn.apply(that, args);
+};
+
+/***/ }),
+/* 93 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var macrotask = __w_pdfjs_require__(91).set;
+
+var Observer = global.MutationObserver || global.WebKitMutationObserver;
+var process = global.process;
+var Promise = global.Promise;
+var isNode = __w_pdfjs_require__(32)(process) == 'process';
+
+module.exports = function () {
+  var head, last, notify;
+
+  var flush = function flush() {
+    var parent, fn;
+    if (isNode && (parent = process.domain)) parent.exit();
+
+    while (head) {
+      fn = head.fn;
+      head = head.next;
+
+      try {
+        fn();
+      } catch (e) {
+        if (head) notify();else last = undefined;
+        throw e;
+      }
+    }
+
+    last = undefined;
+    if (parent) parent.enter();
+  };
+
+  if (isNode) {
+    notify = function notify() {
+      process.nextTick(flush);
+    };
+  } else if (Observer && !(global.navigator && global.navigator.standalone)) {
+    var toggle = true;
+    var node = document.createTextNode('');
+    new Observer(flush).observe(node, {
+      characterData: true
+    });
+
+    notify = function notify() {
+      node.data = toggle = !toggle;
+    };
+  } else if (Promise && Promise.resolve) {
+    var promise = Promise.resolve(undefined);
+
+    notify = function notify() {
+      promise.then(flush);
+    };
+  } else {
+    notify = function notify() {
+      macrotask.call(global, flush);
+    };
+  }
+
+  return function (fn) {
+    var task = {
+      fn: fn,
+      next: undefined
+    };
+    if (last) last.next = task;
+
+    if (!head) {
+      head = task;
+      notify();
+    }
+
+    last = task;
+  };
+};
+
+/***/ }),
+/* 94 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var aFunction = __w_pdfjs_require__(27);
+
+function PromiseCapability(C) {
+  var resolve, reject;
+  this.promise = new C(function ($$resolve, $$reject) {
+    if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
+    resolve = $$resolve;
+    reject = $$reject;
+  });
+  this.resolve = aFunction(resolve);
+  this.reject = aFunction(reject);
+}
+
+module.exports.f = function (C) {
+  return new PromiseCapability(C);
+};
+
+/***/ }),
+/* 95 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (exec) {
+  try {
+    return {
+      e: false,
+      v: exec()
+    };
+  } catch (e) {
+    return {
+      e: true,
+      v: e
+    };
+  }
+};
+
+/***/ }),
+/* 96 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var navigator = global.navigator;
+module.exports = navigator && navigator.userAgent || '';
+
+/***/ }),
+/* 97 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(12);
+
+var isObject = __w_pdfjs_require__(13);
+
+var newPromiseCapability = __w_pdfjs_require__(94);
+
+module.exports = function (C, x) {
+  anObject(C);
+  if (isObject(x) && x.constructor === C) return x;
+  var promiseCapability = newPromiseCapability.f(C);
+  var resolve = promiseCapability.resolve;
+  resolve(x);
+  return promiseCapability.promise;
+};
+
+/***/ }),
+/* 98 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var redefine = __w_pdfjs_require__(20);
+
+module.exports = function (target, src, safe) {
+  for (var key in src) {
+    redefine(target, key, src[key], safe);
+  }
+
+  return target;
+};
+
+/***/ }),
+/* 99 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var dP = __w_pdfjs_require__(11);
+
+var DESCRIPTORS = __w_pdfjs_require__(15);
+
+var SPECIES = __w_pdfjs_require__(33)('species');
+
+module.exports = function (KEY) {
+  var C = global[KEY];
+  if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {
+    configurable: true,
+    get: function get() {
+      return this;
+    }
+  });
+};
+
+/***/ }),
+/* 100 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var core = __w_pdfjs_require__(9);
+
+var global = __w_pdfjs_require__(8);
+
+var speciesConstructor = __w_pdfjs_require__(90);
+
+var promiseResolve = __w_pdfjs_require__(97);
+
+$export($export.P + $export.R, 'Promise', {
+  'finally': function _finally(onFinally) {
+    var C = speciesConstructor(this, core.Promise || global.Promise);
+    var isFunction = typeof onFinally == 'function';
+    return this.then(isFunction ? function (x) {
+      return promiseResolve(C, onFinally()).then(function () {
+        return x;
+      });
+    } : onFinally, isFunction ? function (e) {
+      return promiseResolve(C, onFinally()).then(function () {
+        throw e;
+      });
+    } : onFinally);
+  }
+});
+
+/***/ }),
+/* 101 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var newPromiseCapability = __w_pdfjs_require__(94);
+
+var perform = __w_pdfjs_require__(95);
+
+$export($export.S, 'Promise', {
+  'try': function _try(callbackfn) {
+    var promiseCapability = newPromiseCapability.f(this);
+    var result = perform(callbackfn);
+    (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v);
+    return promiseCapability.promise;
+  }
+});
+
+/***/ }),
+/* 102 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(83);
+
+__w_pdfjs_require__(84);
+
+__w_pdfjs_require__(103);
+
+__w_pdfjs_require__(115);
+
+__w_pdfjs_require__(117);
+
+module.exports = __w_pdfjs_require__(9).WeakMap;
+
+/***/ }),
+/* 103 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var each = __w_pdfjs_require__(104)(0);
+
+var redefine = __w_pdfjs_require__(20);
+
+var meta = __w_pdfjs_require__(108);
+
+var assign = __w_pdfjs_require__(72);
+
+var weak = __w_pdfjs_require__(109);
+
+var isObject = __w_pdfjs_require__(13);
+
+var validate = __w_pdfjs_require__(110);
+
+var NATIVE_WEAK_MAP = __w_pdfjs_require__(110);
+
+var IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;
+var WEAK_MAP = 'WeakMap';
+var getWeak = meta.getWeak;
+var isExtensible = Object.isExtensible;
+var uncaughtFrozenStore = weak.ufstore;
+var InternalMap;
+
+var wrapper = function wrapper(get) {
+  return function WeakMap() {
+    return get(this, arguments.length > 0 ? arguments[0] : undefined);
+  };
+};
+
+var methods = {
+  get: function get(key) {
+    if (isObject(key)) {
+      var data = getWeak(key);
+      if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);
+      return data ? data[this._i] : undefined;
+    }
+  },
+  set: function set(key, value) {
+    return weak.def(validate(this, WEAK_MAP), key, value);
+  }
+};
+
+var $WeakMap = module.exports = __w_pdfjs_require__(111)(WEAK_MAP, wrapper, methods, weak, true, true);
+
+if (NATIVE_WEAK_MAP && IS_IE11) {
+  InternalMap = weak.getConstructor(wrapper, WEAK_MAP);
+  assign(InternalMap.prototype, methods);
+  meta.NEED = true;
+  each(['delete', 'has', 'get', 'set'], function (key) {
+    var proto = $WeakMap.prototype;
+    var method = proto[key];
+    redefine(proto, key, function (a, b) {
+      if (isObject(a) && !isExtensible(a)) {
+        if (!this._f) this._f = new InternalMap();
+
+        var result = this._f[key](a, b);
+
+        return key == 'set' ? this : result;
+      }
+
+      return method.call(this, a, b);
+    });
+  });
+}
+
+/***/ }),
+/* 104 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(26);
+
+var IObject = __w_pdfjs_require__(44);
+
+var toObject = __w_pdfjs_require__(62);
+
+var toLength = __w_pdfjs_require__(28);
+
+var asc = __w_pdfjs_require__(105);
+
+module.exports = function (TYPE, $create) {
+  var IS_MAP = TYPE == 1;
+  var IS_FILTER = TYPE == 2;
+  var IS_SOME = TYPE == 3;
+  var IS_EVERY = TYPE == 4;
+  var IS_FIND_INDEX = TYPE == 6;
+  var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
+  var create = $create || asc;
+  return function ($this, callbackfn, that) {
+    var O = toObject($this);
+    var self = IObject(O);
+    var f = ctx(callbackfn, that, 3);
+    var length = toLength(self.length);
+    var index = 0;
+    var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
+    var val, res;
+
+    for (; length > index; index++) {
+      if (NO_HOLES || index in self) {
+        val = self[index];
+        res = f(val, index, O);
+
+        if (TYPE) {
+          if (IS_MAP) result[index] = res;else if (res) switch (TYPE) {
+            case 3:
+              return true;
+
+            case 5:
+              return val;
+
+            case 6:
+              return index;
+
+            case 2:
+              result.push(val);
+          } else if (IS_EVERY) return false;
+        }
+      }
+    }
+
+    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
+  };
+};
+
+/***/ }),
+/* 105 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var speciesConstructor = __w_pdfjs_require__(106);
+
+module.exports = function (original, length) {
+  return new (speciesConstructor(original))(length);
+};
+
+/***/ }),
+/* 106 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var isArray = __w_pdfjs_require__(107);
+
+var SPECIES = __w_pdfjs_require__(33)('species');
+
+module.exports = function (original) {
+  var C;
+
+  if (isArray(original)) {
+    C = original.constructor;
+    if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
+
+    if (isObject(C)) {
+      C = C[SPECIES];
+      if (C === null) C = undefined;
+    }
+  }
+
+  return C === undefined ? Array : C;
+};
+
+/***/ }),
+/* 107 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(32);
+
+module.exports = Array.isArray || function isArray(arg) {
+  return cof(arg) == 'Array';
+};
+
+/***/ }),
+/* 108 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var META = __w_pdfjs_require__(22)('meta');
+
+var isObject = __w_pdfjs_require__(13);
+
+var has = __w_pdfjs_require__(21);
+
+var setDesc = __w_pdfjs_require__(11).f;
+
+var id = 0;
+
+var isExtensible = Object.isExtensible || function () {
+  return true;
+};
+
+var FREEZE = !__w_pdfjs_require__(16)(function () {
+  return isExtensible(Object.preventExtensions({}));
+});
+
+var setMeta = function setMeta(it) {
+  setDesc(it, META, {
+    value: {
+      i: 'O' + ++id,
+      w: {}
+    }
+  });
+};
+
+var fastKey = function fastKey(it, create) {
+  if (!isObject(it)) return _typeof(it) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
+
+  if (!has(it, META)) {
+    if (!isExtensible(it)) return 'F';
+    if (!create) return 'E';
+    setMeta(it);
+  }
+
+  return it[META].i;
+};
+
+var getWeak = function getWeak(it, create) {
+  if (!has(it, META)) {
+    if (!isExtensible(it)) return true;
+    if (!create) return false;
+    setMeta(it);
+  }
+
+  return it[META].w;
+};
+
+var onFreeze = function onFreeze(it) {
+  if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
+  return it;
+};
+
+var meta = module.exports = {
+  KEY: META,
+  NEED: false,
+  fastKey: fastKey,
+  getWeak: getWeak,
+  onFreeze: onFreeze
+};
+
+/***/ }),
+/* 109 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var redefineAll = __w_pdfjs_require__(98);
+
+var getWeak = __w_pdfjs_require__(108).getWeak;
+
+var anObject = __w_pdfjs_require__(12);
+
+var isObject = __w_pdfjs_require__(13);
+
+var anInstance = __w_pdfjs_require__(88);
+
+var forOf = __w_pdfjs_require__(89);
+
+var createArrayMethod = __w_pdfjs_require__(104);
+
+var $has = __w_pdfjs_require__(21);
+
+var validate = __w_pdfjs_require__(110);
+
+var arrayFind = createArrayMethod(5);
+var arrayFindIndex = createArrayMethod(6);
+var id = 0;
+
+var uncaughtFrozenStore = function uncaughtFrozenStore(that) {
+  return that._l || (that._l = new UncaughtFrozenStore());
+};
+
+var UncaughtFrozenStore = function UncaughtFrozenStore() {
+  this.a = [];
+};
+
+var findUncaughtFrozen = function findUncaughtFrozen(store, key) {
+  return arrayFind(store.a, function (it) {
+    return it[0] === key;
+  });
+};
+
+UncaughtFrozenStore.prototype = {
+  get: function get(key) {
+    var entry = findUncaughtFrozen(this, key);
+    if (entry) return entry[1];
+  },
+  has: function has(key) {
+    return !!findUncaughtFrozen(this, key);
+  },
+  set: function set(key, value) {
+    var entry = findUncaughtFrozen(this, key);
+    if (entry) entry[1] = value;else this.a.push([key, value]);
+  },
+  'delete': function _delete(key) {
+    var index = arrayFindIndex(this.a, function (it) {
+      return it[0] === key;
+    });
+    if (~index) this.a.splice(index, 1);
+    return !!~index;
+  }
+};
+module.exports = {
+  getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
+    var C = wrapper(function (that, iterable) {
+      anInstance(that, C, NAME, '_i');
+      that._t = NAME;
+      that._i = id++;
+      that._l = undefined;
+      if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
+    });
+    redefineAll(C.prototype, {
+      'delete': function _delete(key) {
+        if (!isObject(key)) return false;
+        var data = getWeak(key);
+        if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
+        return data && $has(data, this._i) && delete data[this._i];
+      },
+      has: function has(key) {
+        if (!isObject(key)) return false;
+        var data = getWeak(key);
+        if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
+        return data && $has(data, this._i);
+      }
+    });
+    return C;
+  },
+  def: function def(that, key, value) {
+    var data = getWeak(anObject(key), true);
+    if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value;
+    return that;
+  },
+  ufstore: uncaughtFrozenStore
+};
+
+/***/ }),
+/* 110 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+module.exports = function (it, TYPE) {
+  if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
+  return it;
+};
+
+/***/ }),
+/* 111 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var $export = __w_pdfjs_require__(7);
+
+var redefine = __w_pdfjs_require__(20);
+
+var redefineAll = __w_pdfjs_require__(98);
+
+var meta = __w_pdfjs_require__(108);
+
+var forOf = __w_pdfjs_require__(89);
+
+var anInstance = __w_pdfjs_require__(88);
+
+var isObject = __w_pdfjs_require__(13);
+
+var fails = __w_pdfjs_require__(16);
+
+var $iterDetect = __w_pdfjs_require__(69);
+
+var setToStringTag = __w_pdfjs_require__(60);
+
+var inheritIfRequired = __w_pdfjs_require__(112);
+
+module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
+  var Base = global[NAME];
+  var C = Base;
+  var ADDER = IS_MAP ? 'set' : 'add';
+  var proto = C && C.prototype;
+  var O = {};
+
+  var fixMethod = function fixMethod(KEY) {
+    var fn = proto[KEY];
+    redefine(proto, KEY, KEY == 'delete' ? function (a) {
+      return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'has' ? function has(a) {
+      return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'get' ? function get(a) {
+      return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'add' ? function add(a) {
+      fn.call(this, a === 0 ? 0 : a);
+      return this;
+    } : function set(a, b) {
+      fn.call(this, a === 0 ? 0 : a, b);
+      return this;
+    });
+  };
+
+  if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
+    new C().entries().next();
+  }))) {
+    C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
+    redefineAll(C.prototype, methods);
+    meta.NEED = true;
+  } else {
+    var instance = new C();
+    var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
+    var THROWS_ON_PRIMITIVES = fails(function () {
+      instance.has(1);
+    });
+    var ACCEPT_ITERABLES = $iterDetect(function (iter) {
+      new C(iter);
+    });
+    var BUGGY_ZERO = !IS_WEAK && fails(function () {
+      var $instance = new C();
+      var index = 5;
+
+      while (index--) {
+        $instance[ADDER](index, index);
+      }
+
+      return !$instance.has(-0);
+    });
+
+    if (!ACCEPT_ITERABLES) {
+      C = wrapper(function (target, iterable) {
+        anInstance(target, C, NAME);
+        var that = inheritIfRequired(new Base(), target, C);
+        if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
+        return that;
+      });
+      C.prototype = proto;
+      proto.constructor = C;
+    }
+
+    if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
+      fixMethod('delete');
+      fixMethod('has');
+      IS_MAP && fixMethod('get');
+    }
+
+    if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
+    if (IS_WEAK && proto.clear) delete proto.clear;
+  }
+
+  setToStringTag(C, NAME);
+  O[NAME] = C;
+  $export($export.G + $export.W + $export.F * (C != Base), O);
+  if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
+  return C;
+};
+
+/***/ }),
+/* 112 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var setPrototypeOf = __w_pdfjs_require__(113).set;
+
+module.exports = function (that, target, C) {
+  var S = target.constructor;
+  var P;
+
+  if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {
+    setPrototypeOf(that, P);
+  }
+
+  return that;
+};
+
+/***/ }),
+/* 113 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(13);
+
+var anObject = __w_pdfjs_require__(12);
+
+var check = function check(O, proto) {
+  anObject(O);
+  if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
+};
+
+module.exports = {
+  set: Object.setPrototypeOf || ('__proto__' in {} ? function (test, buggy, set) {
+    try {
+      set = __w_pdfjs_require__(26)(Function.call, __w_pdfjs_require__(114).f(Object.prototype, '__proto__').set, 2);
+      set(test, []);
+      buggy = !(test instanceof Array);
+    } catch (e) {
+      buggy = true;
+    }
+
+    return function setPrototypeOf(O, proto) {
+      check(O, proto);
+      if (buggy) O.__proto__ = proto;else set(O, proto);
+      return O;
+    };
+  }({}, false) : undefined),
+  check: check
+};
+
+/***/ }),
+/* 114 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var pIE = __w_pdfjs_require__(74);
+
+var createDesc = __w_pdfjs_require__(19);
+
+var toIObject = __w_pdfjs_require__(43);
+
+var toPrimitive = __w_pdfjs_require__(18);
+
+var has = __w_pdfjs_require__(21);
+
+var IE8_DOM_DEFINE = __w_pdfjs_require__(14);
+
+var gOPD = Object.getOwnPropertyDescriptor;
+exports.f = __w_pdfjs_require__(15) ? gOPD : function getOwnPropertyDescriptor(O, P) {
+  O = toIObject(O);
+  P = toPrimitive(P, true);
+  if (IE8_DOM_DEFINE) try {
+    return gOPD(O, P);
+  } catch (e) {}
+  if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
+};
+
+/***/ }),
+/* 115 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(116)('WeakMap');
+
+/***/ }),
+/* 116 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+module.exports = function (COLLECTION) {
+  $export($export.S, COLLECTION, {
+    of: function of() {
+      var length = arguments.length;
+      var A = new Array(length);
+
+      while (length--) {
+        A[length] = arguments[length];
+      }
+
+      return new this(A);
+    }
+  });
+};
+
+/***/ }),
+/* 117 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(118)('WeakMap');
+
+/***/ }),
+/* 118 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var aFunction = __w_pdfjs_require__(27);
+
+var ctx = __w_pdfjs_require__(26);
+
+var forOf = __w_pdfjs_require__(89);
+
+module.exports = function (COLLECTION) {
+  $export($export.S, COLLECTION, {
+    from: function from(source) {
+      var mapFn = arguments[1];
+      var mapping, A, n, cb;
+      aFunction(this);
+      mapping = mapFn !== undefined;
+      if (mapping) aFunction(mapFn);
+      if (source == undefined) return new this();
+      A = [];
+
+      if (mapping) {
+        n = 0;
+        cb = ctx(mapFn, arguments[2], 2);
+        forOf(source, false, function (nextItem) {
+          A.push(cb(nextItem, n++));
+        });
+      } else {
+        forOf(source, false, A.push, A);
+      }
+
+      return new this(A);
+    }
+  });
+};
+
+/***/ }),
+/* 119 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(83);
+
+__w_pdfjs_require__(84);
+
+__w_pdfjs_require__(120);
+
+__w_pdfjs_require__(121);
+
+__w_pdfjs_require__(122);
+
+module.exports = __w_pdfjs_require__(9).WeakSet;
+
+/***/ }),
+/* 120 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var weak = __w_pdfjs_require__(109);
+
+var validate = __w_pdfjs_require__(110);
+
+var WEAK_SET = 'WeakSet';
+
+__w_pdfjs_require__(111)(WEAK_SET, function (get) {
+  return function WeakSet() {
+    return get(this, arguments.length > 0 ? arguments[0] : undefined);
+  };
+}, {
+  add: function add(value) {
+    return weak.def(validate(this, WEAK_SET), value, true);
+  }
+}, weak, false, true);
+
+/***/ }),
+/* 121 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(116)('WeakSet');
+
+/***/ }),
+/* 122 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(118)('WeakSet');
+
+/***/ }),
+/* 123 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(124);
+
+module.exports = __w_pdfjs_require__(9).String.codePointAt;
+
+/***/ }),
+/* 124 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var $at = __w_pdfjs_require__(49)(false);
+
+$export($export.P, 'String', {
+  codePointAt: function codePointAt(pos) {
+    return $at(this, pos);
+  }
+});
+
+/***/ }),
+/* 125 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(126);
+
+module.exports = __w_pdfjs_require__(9).String.fromCodePoint;
+
+/***/ }),
+/* 126 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var toAbsoluteIndex = __w_pdfjs_require__(45);
+
+var fromCharCode = String.fromCharCode;
+var $fromCodePoint = String.fromCodePoint;
+$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {
+  fromCodePoint: function fromCodePoint(x) {
+    var res = [];
+    var aLen = arguments.length;
+    var i = 0;
+    var code;
+
+    while (aLen > i) {
+      code = +arguments[i++];
+      if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');
+      res.push(code < 0x10000 ? fromCharCode(code) : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00));
+    }
+
+    return res.join('');
+  }
+});
+
+/***/ }),
+/* 127 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(128);
+
+__w_pdfjs_require__(83);
+
+module.exports = __w_pdfjs_require__(9).Symbol;
+
+/***/ }),
+/* 128 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var global = __w_pdfjs_require__(8);
+
+var has = __w_pdfjs_require__(21);
+
+var DESCRIPTORS = __w_pdfjs_require__(15);
+
+var $export = __w_pdfjs_require__(7);
+
+var redefine = __w_pdfjs_require__(20);
+
+var META = __w_pdfjs_require__(108).KEY;
+
+var $fails = __w_pdfjs_require__(16);
+
+var shared = __w_pdfjs_require__(24);
+
+var setToStringTag = __w_pdfjs_require__(60);
+
+var uid = __w_pdfjs_require__(22);
+
+var wks = __w_pdfjs_require__(33);
+
+var wksExt = __w_pdfjs_require__(129);
+
+var wksDefine = __w_pdfjs_require__(130);
+
+var enumKeys = __w_pdfjs_require__(131);
+
+var isArray = __w_pdfjs_require__(107);
+
+var anObject = __w_pdfjs_require__(12);
+
+var isObject = __w_pdfjs_require__(13);
+
+var toObject = __w_pdfjs_require__(62);
+
+var toIObject = __w_pdfjs_require__(43);
+
+var toPrimitive = __w_pdfjs_require__(18);
+
+var createDesc = __w_pdfjs_require__(19);
+
+var _create = __w_pdfjs_require__(53);
+
+var gOPNExt = __w_pdfjs_require__(132);
+
+var $GOPD = __w_pdfjs_require__(114);
+
+var $GOPS = __w_pdfjs_require__(73);
+
+var $DP = __w_pdfjs_require__(11);
+
+var $keys = __w_pdfjs_require__(55);
+
+var gOPD = $GOPD.f;
+var dP = $DP.f;
+var gOPN = gOPNExt.f;
+var $Symbol = global.Symbol;
+var $JSON = global.JSON;
+
+var _stringify = $JSON && $JSON.stringify;
+
+var PROTOTYPE = 'prototype';
+var HIDDEN = wks('_hidden');
+var TO_PRIMITIVE = wks('toPrimitive');
+var isEnum = {}.propertyIsEnumerable;
+var SymbolRegistry = shared('symbol-registry');
+var AllSymbols = shared('symbols');
+var OPSymbols = shared('op-symbols');
+var ObjectProto = Object[PROTOTYPE];
+var USE_NATIVE = typeof $Symbol == 'function' && !!$GOPS.f;
+var QObject = global.QObject;
+var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
+var setSymbolDesc = DESCRIPTORS && $fails(function () {
+  return _create(dP({}, 'a', {
+    get: function get() {
+      return dP(this, 'a', {
+        value: 7
+      }).a;
+    }
+  })).a != 7;
+}) ? function (it, key, D) {
+  var protoDesc = gOPD(ObjectProto, key);
+  if (protoDesc) delete ObjectProto[key];
+  dP(it, key, D);
+  if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);
+} : dP;
+
+var wrap = function wrap(tag) {
+  var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
+
+  sym._k = tag;
+  return sym;
+};
+
+var isSymbol = USE_NATIVE && _typeof($Symbol.iterator) == 'symbol' ? function (it) {
+  return _typeof(it) == 'symbol';
+} : function (it) {
+  return it instanceof $Symbol;
+};
+
+var $defineProperty = function defineProperty(it, key, D) {
+  if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
+  anObject(it);
+  key = toPrimitive(key, true);
+  anObject(D);
+
+  if (has(AllSymbols, key)) {
+    if (!D.enumerable) {
+      if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));
+      it[HIDDEN][key] = true;
+    } else {
+      if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
+      D = _create(D, {
+        enumerable: createDesc(0, false)
+      });
+    }
+
+    return setSymbolDesc(it, key, D);
+  }
+
+  return dP(it, key, D);
+};
+
+var $defineProperties = function defineProperties(it, P) {
+  anObject(it);
+  var keys = enumKeys(P = toIObject(P));
+  var i = 0;
+  var l = keys.length;
+  var key;
+
+  while (l > i) {
+    $defineProperty(it, key = keys[i++], P[key]);
+  }
+
+  return it;
+};
+
+var $create = function create(it, P) {
+  return P === undefined ? _create(it) : $defineProperties(_create(it), P);
+};
+
+var $propertyIsEnumerable = function propertyIsEnumerable(key) {
+  var E = isEnum.call(this, key = toPrimitive(key, true));
+  if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;
+  return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
+};
+
+var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
+  it = toIObject(it);
+  key = toPrimitive(key, true);
+  if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;
+  var D = gOPD(it, key);
+  if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
+  return D;
+};
+
+var $getOwnPropertyNames = function getOwnPropertyNames(it) {
+  var names = gOPN(toIObject(it));
+  var result = [];
+  var i = 0;
+  var key;
+
+  while (names.length > i) {
+    if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
+  }
+
+  return result;
+};
+
+var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
+  var IS_OP = it === ObjectProto;
+  var names = gOPN(IS_OP ? OPSymbols : toIObject(it));
+  var result = [];
+  var i = 0;
+  var key;
+
+  while (names.length > i) {
+    if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
+  }
+
+  return result;
+};
+
+if (!USE_NATIVE) {
+  $Symbol = function _Symbol() {
+    if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
+    var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
+
+    var $set = function $set(value) {
+      if (this === ObjectProto) $set.call(OPSymbols, value);
+      if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
+      setSymbolDesc(this, tag, createDesc(1, value));
+    };
+
+    if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, {
+      configurable: true,
+      set: $set
+    });
+    return wrap(tag);
+  };
+
+  redefine($Symbol[PROTOTYPE], 'toString', function toString() {
+    return this._k;
+  });
+  $GOPD.f = $getOwnPropertyDescriptor;
+  $DP.f = $defineProperty;
+  __w_pdfjs_require__(133).f = gOPNExt.f = $getOwnPropertyNames;
+  __w_pdfjs_require__(74).f = $propertyIsEnumerable;
+  $GOPS.f = $getOwnPropertySymbols;
+
+  if (DESCRIPTORS && !__w_pdfjs_require__(25)) {
+    redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
+  }
+
+  wksExt.f = function (name) {
+    return wrap(wks(name));
+  };
+}
+
+$export($export.G + $export.W + $export.F * !USE_NATIVE, {
+  Symbol: $Symbol
+});
+
+for (var es6Symbols = 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'.split(','), j = 0; es6Symbols.length > j;) {
+  wks(es6Symbols[j++]);
+}
+
+for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) {
+  wksDefine(wellKnownSymbols[k++]);
+}
+
+$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
+  'for': function _for(key) {
+    return has(SymbolRegistry, key += '') ? SymbolRegistry[key] : SymbolRegistry[key] = $Symbol(key);
+  },
+  keyFor: function keyFor(sym) {
+    if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
+
+    for (var key in SymbolRegistry) {
+      if (SymbolRegistry[key] === sym) return key;
+    }
+  },
+  useSetter: function useSetter() {
+    setter = true;
+  },
+  useSimple: function useSimple() {
+    setter = false;
+  }
+});
+$export($export.S + $export.F * !USE_NATIVE, 'Object', {
+  create: $create,
+  defineProperty: $defineProperty,
+  defineProperties: $defineProperties,
+  getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
+  getOwnPropertyNames: $getOwnPropertyNames,
+  getOwnPropertySymbols: $getOwnPropertySymbols
+});
+var FAILS_ON_PRIMITIVES = $fails(function () {
+  $GOPS.f(1);
+});
+$export($export.S + $export.F * FAILS_ON_PRIMITIVES, 'Object', {
+  getOwnPropertySymbols: function getOwnPropertySymbols(it) {
+    return $GOPS.f(toObject(it));
+  }
+});
+$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {
+  var S = $Symbol();
+  return _stringify([S]) != '[null]' || _stringify({
+    a: S
+  }) != '{}' || _stringify(Object(S)) != '{}';
+})), 'JSON', {
+  stringify: function stringify(it) {
+    var args = [it];
+    var i = 1;
+    var replacer, $replacer;
+
+    while (arguments.length > i) {
+      args.push(arguments[i++]);
+    }
+
+    $replacer = replacer = args[1];
+    if (!isObject(replacer) && it === undefined || isSymbol(it)) return;
+    if (!isArray(replacer)) replacer = function replacer(key, value) {
+      if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
+      if (!isSymbol(value)) return value;
+    };
+    args[1] = replacer;
+    return _stringify.apply($JSON, args);
+  }
+});
+$Symbol[PROTOTYPE][TO_PRIMITIVE] || __w_pdfjs_require__(10)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
+setToStringTag($Symbol, 'Symbol');
+setToStringTag(Math, 'Math', true);
+setToStringTag(global.JSON, 'JSON', true);
+
+/***/ }),
+/* 129 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = __w_pdfjs_require__(33);
+
+/***/ }),
+/* 130 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(8);
+
+var core = __w_pdfjs_require__(9);
+
+var LIBRARY = __w_pdfjs_require__(25);
+
+var wksExt = __w_pdfjs_require__(129);
+
+var defineProperty = __w_pdfjs_require__(11).f;
+
+module.exports = function (name) {
+  var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
+  if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, {
+    value: wksExt.f(name)
+  });
+};
+
+/***/ }),
+/* 131 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var getKeys = __w_pdfjs_require__(55);
+
+var gOPS = __w_pdfjs_require__(73);
+
+var pIE = __w_pdfjs_require__(74);
+
+module.exports = function (it) {
+  var result = getKeys(it);
+  var getSymbols = gOPS.f;
+
+  if (getSymbols) {
+    var symbols = getSymbols(it);
+    var isEnum = pIE.f;
+    var i = 0;
+    var key;
+
+    while (symbols.length > i) {
+      if (isEnum.call(it, key = symbols[i++])) result.push(key);
+    }
+  }
+
+  return result;
+};
+
+/***/ }),
+/* 132 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var toIObject = __w_pdfjs_require__(43);
+
+var gOPN = __w_pdfjs_require__(133).f;
+
+var toString = {}.toString;
+var windowNames = (typeof window === "undefined" ? "undefined" : _typeof(window)) == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
+
+var getWindowNames = function getWindowNames(it) {
+  try {
+    return gOPN(it);
+  } catch (e) {
+    return windowNames.slice();
+  }
+};
+
+module.exports.f = function getOwnPropertyNames(it) {
+  return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
+};
+
+/***/ }),
+/* 133 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $keys = __w_pdfjs_require__(56);
+
+var hiddenKeys = __w_pdfjs_require__(58).concat('length', 'prototype');
+
+exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
+  return $keys(O, hiddenKeys);
+};
+
+/***/ }),
+/* 134 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(135);
+
+module.exports = __w_pdfjs_require__(9).String.padStart;
+
+/***/ }),
+/* 135 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var $pad = __w_pdfjs_require__(136);
+
+var userAgent = __w_pdfjs_require__(96);
+
+var WEBKIT_BUG = /Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(userAgent);
+$export($export.P + $export.F * WEBKIT_BUG, 'String', {
+  padStart: function padStart(maxLength) {
+    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true);
+  }
+});
+
+/***/ }),
+/* 136 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toLength = __w_pdfjs_require__(28);
+
+var repeat = __w_pdfjs_require__(137);
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function (that, maxLength, fillString, left) {
+  var S = String(defined(that));
+  var stringLength = S.length;
+  var fillStr = fillString === undefined ? ' ' : String(fillString);
+  var intMaxLength = toLength(maxLength);
+  if (intMaxLength <= stringLength || fillStr == '') return S;
+  var fillLen = intMaxLength - stringLength;
+  var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));
+  if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);
+  return left ? stringFiller + S : S + stringFiller;
+};
+
+/***/ }),
+/* 137 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(29);
+
+var defined = __w_pdfjs_require__(34);
+
+module.exports = function repeat(count) {
+  var str = String(defined(this));
+  var res = '';
+  var n = toInteger(count);
+  if (n < 0 || n == Infinity) throw RangeError("Count can't be negative");
+
+  for (; n > 0; (n >>>= 1) && (str += str)) {
+    if (n & 1) res += str;
+  }
+
+  return res;
+};
+
+/***/ }),
+/* 138 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(139);
+
+module.exports = __w_pdfjs_require__(9).String.padEnd;
+
+/***/ }),
+/* 139 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var $pad = __w_pdfjs_require__(136);
+
+var userAgent = __w_pdfjs_require__(96);
+
+var WEBKIT_BUG = /Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(userAgent);
+$export($export.P + $export.F * WEBKIT_BUG, 'String', {
+  padEnd: function padEnd(maxLength) {
+    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false);
+  }
+});
+
+/***/ }),
+/* 140 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(141);
+
+module.exports = __w_pdfjs_require__(9).Object.values;
+
+/***/ }),
+/* 141 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(7);
+
+var $values = __w_pdfjs_require__(142)(false);
+
+$export($export.S, 'Object', {
+  values: function values(it) {
+    return $values(it);
+  }
+});
+
+/***/ }),
+/* 142 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var DESCRIPTORS = __w_pdfjs_require__(15);
+
+var getKeys = __w_pdfjs_require__(55);
+
+var toIObject = __w_pdfjs_require__(43);
+
+var isEnum = __w_pdfjs_require__(74).f;
+
+module.exports = function (isEntries) {
+  return function (it) {
+    var O = toIObject(it);
+    var keys = getKeys(O);
+    var length = keys.length;
+    var i = 0;
+    var result = [];
+    var key;
+
+    while (length > i) {
+      key = keys[i++];
+
+      if (!DESCRIPTORS || isEnum.call(O, key)) {
+        result.push(isEntries ? [key, O[key]] : O[key]);
+      }
+    }
+
+    return result;
+  };
+};
+
+/***/ }),
+/* 143 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+{
+  var isReadableStreamSupported = false;
+
+  if (typeof ReadableStream !== 'undefined') {
+    try {
+      new ReadableStream({
+        start: function start(controller) {
+          controller.close();
+        }
+      });
+      isReadableStreamSupported = true;
+    } catch (e) {}
+  }
+
+  if (isReadableStreamSupported) {
+    exports.ReadableStream = ReadableStream;
+  } else {
+    exports.ReadableStream = __w_pdfjs_require__(144).ReadableStream;
+  }
+}
+
+/***/ }),
+/* 144 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
+
+(function (e, a) {
+  for (var i in a) {
+    e[i] = a[i];
+  }
+})(exports, function (modules) {
+  var installedModules = {};
+
+  function __w_pdfjs_require__(moduleId) {
+    if (installedModules[moduleId]) return installedModules[moduleId].exports;
+    var module = installedModules[moduleId] = {
+      i: moduleId,
+      l: false,
+      exports: {}
+    };
+    modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
+    module.l = true;
+    return module.exports;
+  }
+
+  __w_pdfjs_require__.m = modules;
+  __w_pdfjs_require__.c = installedModules;
+
+  __w_pdfjs_require__.i = function (value) {
+    return value;
+  };
+
+  __w_pdfjs_require__.d = function (exports, name, getter) {
+    if (!__w_pdfjs_require__.o(exports, name)) {
+      Object.defineProperty(exports, name, {
+        configurable: false,
+        enumerable: true,
+        get: getter
+      });
+    }
+  };
+
+  __w_pdfjs_require__.n = function (module) {
+    var getter = module && module.__esModule ? function getDefault() {
+      return module['default'];
+    } : function getModuleExports() {
+      return module;
+    };
+
+    __w_pdfjs_require__.d(getter, 'a', getter);
+
+    return getter;
+  };
+
+  __w_pdfjs_require__.o = function (object, property) {
+    return Object.prototype.hasOwnProperty.call(object, property);
+  };
+
+  __w_pdfjs_require__.p = "";
+  return __w_pdfjs_require__(__w_pdfjs_require__.s = 7);
+}([function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
+    return _typeof2(obj);
+  } : function (obj) {
+    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
+  };
+
+  var _require = __w_pdfjs_require__(1),
+      assert = _require.assert;
+
+  function IsPropertyKey(argument) {
+    return typeof argument === 'string' || (typeof argument === 'undefined' ? 'undefined' : _typeof(argument)) === 'symbol';
+  }
+
+  exports.typeIsObject = function (x) {
+    return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function';
+  };
+
+  exports.createDataProperty = function (o, p, v) {
+    assert(exports.typeIsObject(o));
+    Object.defineProperty(o, p, {
+      value: v,
+      writable: true,
+      enumerable: true,
+      configurable: true
+    });
+  };
+
+  exports.createArrayFromList = function (elements) {
+    return elements.slice();
+  };
+
+  exports.ArrayBufferCopy = function (dest, destOffset, src, srcOffset, n) {
+    new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset);
+  };
+
+  exports.CreateIterResultObject = function (value, done) {
+    assert(typeof done === 'boolean');
+    var obj = {};
+    Object.defineProperty(obj, 'value', {
+      value: value,
+      enumerable: true,
+      writable: true,
+      configurable: true
+    });
+    Object.defineProperty(obj, 'done', {
+      value: done,
+      enumerable: true,
+      writable: true,
+      configurable: true
+    });
+    return obj;
+  };
+
+  exports.IsFiniteNonNegativeNumber = function (v) {
+    if (Number.isNaN(v)) {
+      return false;
+    }
+
+    if (v === Infinity) {
+      return false;
+    }
+
+    if (v < 0) {
+      return false;
+    }
+
+    return true;
+  };
+
+  function Call(F, V, args) {
+    if (typeof F !== 'function') {
+      throw new TypeError('Argument is not a function');
+    }
+
+    return Function.prototype.apply.call(F, V, args);
+  }
+
+  exports.InvokeOrNoop = function (O, P, args) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+    var method = O[P];
+
+    if (method === undefined) {
+      return undefined;
+    }
+
+    return Call(method, O, args);
+  };
+
+  exports.PromiseInvokeOrNoop = function (O, P, args) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+
+    try {
+      return Promise.resolve(exports.InvokeOrNoop(O, P, args));
+    } catch (returnValueE) {
+      return Promise.reject(returnValueE);
+    }
+  };
+
+  exports.PromiseInvokeOrPerformFallback = function (O, P, args, F, argsF) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+    assert(Array.isArray(argsF));
+    var method = void 0;
+
+    try {
+      method = O[P];
+    } catch (methodE) {
+      return Promise.reject(methodE);
+    }
+
+    if (method === undefined) {
+      return F.apply(null, argsF);
+    }
+
+    try {
+      return Promise.resolve(Call(method, O, args));
+    } catch (e) {
+      return Promise.reject(e);
+    }
+  };
+
+  exports.TransferArrayBuffer = function (O) {
+    return O.slice();
+  };
+
+  exports.ValidateAndNormalizeHighWaterMark = function (highWaterMark) {
+    highWaterMark = Number(highWaterMark);
+
+    if (Number.isNaN(highWaterMark) || highWaterMark < 0) {
+      throw new RangeError('highWaterMark property of a queuing strategy must be non-negative and non-NaN');
+    }
+
+    return highWaterMark;
+  };
+
+  exports.ValidateAndNormalizeQueuingStrategy = function (size, highWaterMark) {
+    if (size !== undefined && typeof size !== 'function') {
+      throw new TypeError('size property of a queuing strategy must be a function');
+    }
+
+    highWaterMark = exports.ValidateAndNormalizeHighWaterMark(highWaterMark);
+    return {
+      size: size,
+      highWaterMark: highWaterMark
+    };
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  function rethrowAssertionErrorRejection(e) {
+    if (e && e.constructor === AssertionError) {
+      setTimeout(function () {
+        throw e;
+      }, 0);
+    }
+  }
+
+  function AssertionError(message) {
+    this.name = 'AssertionError';
+    this.message = message || '';
+    this.stack = new Error().stack;
+  }
+
+  AssertionError.prototype = Object.create(Error.prototype);
+  AssertionError.prototype.constructor = AssertionError;
+
+  function assert(value, message) {
+    if (!value) {
+      throw new AssertionError(message);
+    }
+  }
+
+  module.exports = {
+    rethrowAssertionErrorRejection: rethrowAssertionErrorRejection,
+    AssertionError: AssertionError,
+    assert: assert
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(0),
+      InvokeOrNoop = _require.InvokeOrNoop,
+      PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
+      ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
+      typeIsObject = _require.typeIsObject;
+
+  var _require2 = __w_pdfjs_require__(1),
+      assert = _require2.assert,
+      rethrowAssertionErrorRejection = _require2.rethrowAssertionErrorRejection;
+
+  var _require3 = __w_pdfjs_require__(3),
+      DequeueValue = _require3.DequeueValue,
+      EnqueueValueWithSize = _require3.EnqueueValueWithSize,
+      PeekQueueValue = _require3.PeekQueueValue,
+      ResetQueue = _require3.ResetQueue;
+
+  var WritableStream = function () {
+    function WritableStream() {
+      var underlyingSink = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          size = _ref.size,
+          _ref$highWaterMark = _ref.highWaterMark,
+          highWaterMark = _ref$highWaterMark === undefined ? 1 : _ref$highWaterMark;
+
+      _classCallCheck(this, WritableStream);
+
+      this._state = 'writable';
+      this._storedError = undefined;
+      this._writer = undefined;
+      this._writableStreamController = undefined;
+      this._writeRequests = [];
+      this._inFlightWriteRequest = undefined;
+      this._closeRequest = undefined;
+      this._inFlightCloseRequest = undefined;
+      this._pendingAbortRequest = undefined;
+      this._backpressure = false;
+      var type = underlyingSink.type;
+
+      if (type !== undefined) {
+        throw new RangeError('Invalid type is specified');
+      }
+
+      this._writableStreamController = new WritableStreamDefaultController(this, underlyingSink, size, highWaterMark);
+
+      this._writableStreamController.__startSteps();
+    }
+
+    _createClass(WritableStream, [{
+      key: 'abort',
+      value: function abort(reason) {
+        if (IsWritableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('abort'));
+        }
+
+        if (IsWritableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('Cannot abort a stream that already has a writer'));
+        }
+
+        return WritableStreamAbort(this, reason);
+      }
+    }, {
+      key: 'getWriter',
+      value: function getWriter() {
+        if (IsWritableStream(this) === false) {
+          throw streamBrandCheckException('getWriter');
+        }
+
+        return AcquireWritableStreamDefaultWriter(this);
+      }
+    }, {
+      key: 'locked',
+      get: function get() {
+        if (IsWritableStream(this) === false) {
+          throw streamBrandCheckException('locked');
+        }
+
+        return IsWritableStreamLocked(this);
+      }
+    }]);
+
+    return WritableStream;
+  }();
+
+  module.exports = {
+    AcquireWritableStreamDefaultWriter: AcquireWritableStreamDefaultWriter,
+    IsWritableStream: IsWritableStream,
+    IsWritableStreamLocked: IsWritableStreamLocked,
+    WritableStream: WritableStream,
+    WritableStreamAbort: WritableStreamAbort,
+    WritableStreamDefaultControllerError: WritableStreamDefaultControllerError,
+    WritableStreamDefaultWriterCloseWithErrorPropagation: WritableStreamDefaultWriterCloseWithErrorPropagation,
+    WritableStreamDefaultWriterRelease: WritableStreamDefaultWriterRelease,
+    WritableStreamDefaultWriterWrite: WritableStreamDefaultWriterWrite,
+    WritableStreamCloseQueuedOrInFlight: WritableStreamCloseQueuedOrInFlight
+  };
+
+  function AcquireWritableStreamDefaultWriter(stream) {
+    return new WritableStreamDefaultWriter(stream);
+  }
+
+  function IsWritableStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsWritableStreamLocked(stream) {
+    assert(IsWritableStream(stream) === true, 'IsWritableStreamLocked should only be used on known writable streams');
+
+    if (stream._writer === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamAbort(stream, reason) {
+    var state = stream._state;
+
+    if (state === 'closed') {
+      return Promise.resolve(undefined);
+    }
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    var error = new TypeError('Requested to abort');
+
+    if (stream._pendingAbortRequest !== undefined) {
+      return Promise.reject(error);
+    }
+
+    assert(state === 'writable' || state === 'erroring', 'state must be writable or erroring');
+    var wasAlreadyErroring = false;
+
+    if (state === 'erroring') {
+      wasAlreadyErroring = true;
+      reason = undefined;
+    }
+
+    var promise = new Promise(function (resolve, reject) {
+      stream._pendingAbortRequest = {
+        _resolve: resolve,
+        _reject: reject,
+        _reason: reason,
+        _wasAlreadyErroring: wasAlreadyErroring
+      };
+    });
+
+    if (wasAlreadyErroring === false) {
+      WritableStreamStartErroring(stream, error);
+    }
+
+    return promise;
+  }
+
+  function WritableStreamAddWriteRequest(stream) {
+    assert(IsWritableStreamLocked(stream) === true);
+    assert(stream._state === 'writable');
+    var promise = new Promise(function (resolve, reject) {
+      var writeRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._writeRequests.push(writeRequest);
+    });
+    return promise;
+  }
+
+  function WritableStreamDealWithRejection(stream, error) {
+    var state = stream._state;
+
+    if (state === 'writable') {
+      WritableStreamStartErroring(stream, error);
+      return;
+    }
+
+    assert(state === 'erroring');
+    WritableStreamFinishErroring(stream);
+  }
+
+  function WritableStreamStartErroring(stream, reason) {
+    assert(stream._storedError === undefined, 'stream._storedError === undefined');
+    assert(stream._state === 'writable', 'state must be writable');
+    var controller = stream._writableStreamController;
+    assert(controller !== undefined, 'controller must not be undefined');
+    stream._state = 'erroring';
+    stream._storedError = reason;
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
+    }
+
+    if (WritableStreamHasOperationMarkedInFlight(stream) === false && controller._started === true) {
+      WritableStreamFinishErroring(stream);
+    }
+  }
+
+  function WritableStreamFinishErroring(stream) {
+    assert(stream._state === 'erroring', 'stream._state === erroring');
+    assert(WritableStreamHasOperationMarkedInFlight(stream) === false, 'WritableStreamHasOperationMarkedInFlight(stream) === false');
+    stream._state = 'errored';
+
+    stream._writableStreamController.__errorSteps();
+
+    var storedError = stream._storedError;
+
+    for (var i = 0; i < stream._writeRequests.length; i++) {
+      var writeRequest = stream._writeRequests[i];
+
+      writeRequest._reject(storedError);
+    }
+
+    stream._writeRequests = [];
+
+    if (stream._pendingAbortRequest === undefined) {
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    var abortRequest = stream._pendingAbortRequest;
+    stream._pendingAbortRequest = undefined;
+
+    if (abortRequest._wasAlreadyErroring === true) {
+      abortRequest._reject(storedError);
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    var promise = stream._writableStreamController.__abortSteps(abortRequest._reason);
+
+    promise.then(function () {
+      abortRequest._resolve();
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+    }, function (reason) {
+      abortRequest._reject(reason);
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+    });
+  }
+
+  function WritableStreamFinishInFlightWrite(stream) {
+    assert(stream._inFlightWriteRequest !== undefined);
+
+    stream._inFlightWriteRequest._resolve(undefined);
+
+    stream._inFlightWriteRequest = undefined;
+  }
+
+  function WritableStreamFinishInFlightWriteWithError(stream, error) {
+    assert(stream._inFlightWriteRequest !== undefined);
+
+    stream._inFlightWriteRequest._reject(error);
+
+    stream._inFlightWriteRequest = undefined;
+    assert(stream._state === 'writable' || stream._state === 'erroring');
+    WritableStreamDealWithRejection(stream, error);
+  }
+
+  function WritableStreamFinishInFlightClose(stream) {
+    assert(stream._inFlightCloseRequest !== undefined);
+
+    stream._inFlightCloseRequest._resolve(undefined);
+
+    stream._inFlightCloseRequest = undefined;
+    var state = stream._state;
+    assert(state === 'writable' || state === 'erroring');
+
+    if (state === 'erroring') {
+      stream._storedError = undefined;
+
+      if (stream._pendingAbortRequest !== undefined) {
+        stream._pendingAbortRequest._resolve();
+
+        stream._pendingAbortRequest = undefined;
+      }
+    }
+
+    stream._state = 'closed';
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      defaultWriterClosedPromiseResolve(writer);
+    }
+
+    assert(stream._pendingAbortRequest === undefined, 'stream._pendingAbortRequest === undefined');
+    assert(stream._storedError === undefined, 'stream._storedError === undefined');
+  }
+
+  function WritableStreamFinishInFlightCloseWithError(stream, error) {
+    assert(stream._inFlightCloseRequest !== undefined);
+
+    stream._inFlightCloseRequest._reject(error);
+
+    stream._inFlightCloseRequest = undefined;
+    assert(stream._state === 'writable' || stream._state === 'erroring');
+
+    if (stream._pendingAbortRequest !== undefined) {
+      stream._pendingAbortRequest._reject(error);
+
+      stream._pendingAbortRequest = undefined;
+    }
+
+    WritableStreamDealWithRejection(stream, error);
+  }
+
+  function WritableStreamCloseQueuedOrInFlight(stream) {
+    if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamHasOperationMarkedInFlight(stream) {
+    if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamMarkCloseRequestInFlight(stream) {
+    assert(stream._inFlightCloseRequest === undefined);
+    assert(stream._closeRequest !== undefined);
+    stream._inFlightCloseRequest = stream._closeRequest;
+    stream._closeRequest = undefined;
+  }
+
+  function WritableStreamMarkFirstWriteRequestInFlight(stream) {
+    assert(stream._inFlightWriteRequest === undefined, 'there must be no pending write request');
+    assert(stream._writeRequests.length !== 0, 'writeRequests must not be empty');
+    stream._inFlightWriteRequest = stream._writeRequests.shift();
+  }
+
+  function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
+    assert(stream._state === 'errored', '_stream_.[[state]] is `"errored"`');
+
+    if (stream._closeRequest !== undefined) {
+      assert(stream._inFlightCloseRequest === undefined);
+
+      stream._closeRequest._reject(stream._storedError);
+
+      stream._closeRequest = undefined;
+    }
+
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      defaultWriterClosedPromiseReject(writer, stream._storedError);
+
+      writer._closedPromise["catch"](function () {});
+    }
+  }
+
+  function WritableStreamUpdateBackpressure(stream, backpressure) {
+    assert(stream._state === 'writable');
+    assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
+    var writer = stream._writer;
+
+    if (writer !== undefined && backpressure !== stream._backpressure) {
+      if (backpressure === true) {
+        defaultWriterReadyPromiseReset(writer);
+      } else {
+        assert(backpressure === false);
+        defaultWriterReadyPromiseResolve(writer);
+      }
+    }
+
+    stream._backpressure = backpressure;
+  }
+
+  var WritableStreamDefaultWriter = function () {
+    function WritableStreamDefaultWriter(stream) {
+      _classCallCheck(this, WritableStreamDefaultWriter);
+
+      if (IsWritableStream(stream) === false) {
+        throw new TypeError('WritableStreamDefaultWriter can only be constructed with a WritableStream instance');
+      }
+
+      if (IsWritableStreamLocked(stream) === true) {
+        throw new TypeError('This stream has already been locked for exclusive writing by another writer');
+      }
+
+      this._ownerWritableStream = stream;
+      stream._writer = this;
+      var state = stream._state;
+
+      if (state === 'writable') {
+        if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._backpressure === true) {
+          defaultWriterReadyPromiseInitialize(this);
+        } else {
+          defaultWriterReadyPromiseInitializeAsResolved(this);
+        }
+
+        defaultWriterClosedPromiseInitialize(this);
+      } else if (state === 'erroring') {
+        defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError);
+
+        this._readyPromise["catch"](function () {});
+
+        defaultWriterClosedPromiseInitialize(this);
+      } else if (state === 'closed') {
+        defaultWriterReadyPromiseInitializeAsResolved(this);
+        defaultWriterClosedPromiseInitializeAsResolved(this);
+      } else {
+        assert(state === 'errored', 'state must be errored');
+        var storedError = stream._storedError;
+        defaultWriterReadyPromiseInitializeAsRejected(this, storedError);
+
+        this._readyPromise["catch"](function () {});
+
+        defaultWriterClosedPromiseInitializeAsRejected(this, storedError);
+
+        this._closedPromise["catch"](function () {});
+      }
+    }
+
+    _createClass(WritableStreamDefaultWriter, [{
+      key: 'abort',
+      value: function abort(reason) {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('abort'));
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          return Promise.reject(defaultWriterLockException('abort'));
+        }
+
+        return WritableStreamDefaultWriterAbort(this, reason);
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('close'));
+        }
+
+        var stream = this._ownerWritableStream;
+
+        if (stream === undefined) {
+          return Promise.reject(defaultWriterLockException('close'));
+        }
+
+        if (WritableStreamCloseQueuedOrInFlight(stream) === true) {
+          return Promise.reject(new TypeError('cannot close an already-closing stream'));
+        }
+
+        return WritableStreamDefaultWriterClose(this);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          throw defaultWriterBrandCheckException('releaseLock');
+        }
+
+        var stream = this._ownerWritableStream;
+
+        if (stream === undefined) {
+          return;
+        }
+
+        assert(stream._writer !== undefined);
+        WritableStreamDefaultWriterRelease(this);
+      }
+    }, {
+      key: 'write',
+      value: function write(chunk) {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('write'));
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          return Promise.reject(defaultWriterLockException('write to'));
+        }
+
+        return WritableStreamDefaultWriterWrite(this, chunk);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          throw defaultWriterBrandCheckException('desiredSize');
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          throw defaultWriterLockException('desiredSize');
+        }
+
+        return WritableStreamDefaultWriterGetDesiredSize(this);
+      }
+    }, {
+      key: 'ready',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('ready'));
+        }
+
+        return this._readyPromise;
+      }
+    }]);
+
+    return WritableStreamDefaultWriter;
+  }();
+
+  function IsWritableStreamDefaultWriter(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamDefaultWriterAbort(writer, reason) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    return WritableStreamAbort(stream, reason);
+  }
+
+  function WritableStreamDefaultWriterClose(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var state = stream._state;
+
+    if (state === 'closed' || state === 'errored') {
+      return Promise.reject(new TypeError('The stream (in ' + state + ' state) is not in the writable state and cannot be closed'));
+    }
+
+    assert(state === 'writable' || state === 'erroring');
+    assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
+    var promise = new Promise(function (resolve, reject) {
+      var closeRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+      stream._closeRequest = closeRequest;
+    });
+
+    if (stream._backpressure === true && state === 'writable') {
+      defaultWriterReadyPromiseResolve(writer);
+    }
+
+    WritableStreamDefaultControllerClose(stream._writableStreamController);
+    return promise;
+  }
+
+  function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var state = stream._state;
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
+      return Promise.resolve();
+    }
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(state === 'writable' || state === 'erroring');
+    return WritableStreamDefaultWriterClose(writer);
+  }
+
+  function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) {
+    if (writer._closedPromiseState === 'pending') {
+      defaultWriterClosedPromiseReject(writer, error);
+    } else {
+      defaultWriterClosedPromiseResetToRejected(writer, error);
+    }
+
+    writer._closedPromise["catch"](function () {});
+  }
+
+  function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) {
+    if (writer._readyPromiseState === 'pending') {
+      defaultWriterReadyPromiseReject(writer, error);
+    } else {
+      defaultWriterReadyPromiseResetToRejected(writer, error);
+    }
+
+    writer._readyPromise["catch"](function () {});
+  }
+
+  function WritableStreamDefaultWriterGetDesiredSize(writer) {
+    var stream = writer._ownerWritableStream;
+    var state = stream._state;
+
+    if (state === 'errored' || state === 'erroring') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController);
+  }
+
+  function WritableStreamDefaultWriterRelease(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    assert(stream._writer === writer);
+    var releasedError = new TypeError('Writer was released and can no longer be used to monitor the stream\'s closedness');
+    WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError);
+    WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
+    stream._writer = undefined;
+    writer._ownerWritableStream = undefined;
+  }
+
+  function WritableStreamDefaultWriterWrite(writer, chunk) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var controller = stream._writableStreamController;
+    var chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk);
+
+    if (stream !== writer._ownerWritableStream) {
+      return Promise.reject(defaultWriterLockException('write to'));
+    }
+
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
+      return Promise.reject(new TypeError('The stream is closing or closed and cannot be written to'));
+    }
+
+    if (state === 'erroring') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(state === 'writable');
+    var promise = WritableStreamAddWriteRequest(stream);
+    WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
+    return promise;
+  }
+
+  var WritableStreamDefaultController = function () {
+    function WritableStreamDefaultController(stream, underlyingSink, size, highWaterMark) {
+      _classCallCheck(this, WritableStreamDefaultController);
+
+      if (IsWritableStream(stream) === false) {
+        throw new TypeError('WritableStreamDefaultController can only be constructed with a WritableStream instance');
+      }
+
+      if (stream._writableStreamController !== undefined) {
+        throw new TypeError('WritableStreamDefaultController instances can only be created by the WritableStream constructor');
+      }
+
+      this._controlledWritableStream = stream;
+      this._underlyingSink = underlyingSink;
+      this._queue = undefined;
+      this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._started = false;
+      var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
+      this._strategySize = normalizedStrategy.size;
+      this._strategyHWM = normalizedStrategy.highWaterMark;
+      var backpressure = WritableStreamDefaultControllerGetBackpressure(this);
+      WritableStreamUpdateBackpressure(stream, backpressure);
+    }
+
+    _createClass(WritableStreamDefaultController, [{
+      key: 'error',
+      value: function error(e) {
+        if (IsWritableStreamDefaultController(this) === false) {
+          throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController');
+        }
+
+        var state = this._controlledWritableStream._state;
+
+        if (state !== 'writable') {
+          return;
+        }
+
+        WritableStreamDefaultControllerError(this, e);
+      }
+    }, {
+      key: '__abortSteps',
+      value: function __abortSteps(reason) {
+        return PromiseInvokeOrNoop(this._underlyingSink, 'abort', [reason]);
+      }
+    }, {
+      key: '__errorSteps',
+      value: function __errorSteps() {
+        ResetQueue(this);
+      }
+    }, {
+      key: '__startSteps',
+      value: function __startSteps() {
+        var _this = this;
+
+        var startResult = InvokeOrNoop(this._underlyingSink, 'start', [this]);
+        var stream = this._controlledWritableStream;
+        Promise.resolve(startResult).then(function () {
+          assert(stream._state === 'writable' || stream._state === 'erroring');
+          _this._started = true;
+          WritableStreamDefaultControllerAdvanceQueueIfNeeded(_this);
+        }, function (r) {
+          assert(stream._state === 'writable' || stream._state === 'erroring');
+          _this._started = true;
+          WritableStreamDealWithRejection(stream, r);
+        })["catch"](rethrowAssertionErrorRejection);
+      }
+    }]);
+
+    return WritableStreamDefaultController;
+  }();
+
+  function WritableStreamDefaultControllerClose(controller) {
+    EnqueueValueWithSize(controller, 'close', 0);
+    WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+  }
+
+  function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
+    var strategySize = controller._strategySize;
+
+    if (strategySize === undefined) {
+      return 1;
+    }
+
+    try {
+      return strategySize(chunk);
+    } catch (chunkSizeE) {
+      WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
+      return 1;
+    }
+  }
+
+  function WritableStreamDefaultControllerGetDesiredSize(controller) {
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
+    var writeRecord = {
+      chunk: chunk
+    };
+
+    try {
+      EnqueueValueWithSize(controller, writeRecord, chunkSize);
+    } catch (enqueueE) {
+      WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
+      return;
+    }
+
+    var stream = controller._controlledWritableStream;
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._state === 'writable') {
+      var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
+      WritableStreamUpdateBackpressure(stream, backpressure);
+    }
+
+    WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+  }
+
+  function IsWritableStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSink')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
+    var stream = controller._controlledWritableStream;
+
+    if (controller._started === false) {
+      return;
+    }
+
+    if (stream._inFlightWriteRequest !== undefined) {
+      return;
+    }
+
+    var state = stream._state;
+
+    if (state === 'closed' || state === 'errored') {
+      return;
+    }
+
+    if (state === 'erroring') {
+      WritableStreamFinishErroring(stream);
+      return;
+    }
+
+    if (controller._queue.length === 0) {
+      return;
+    }
+
+    var writeRecord = PeekQueueValue(controller);
+
+    if (writeRecord === 'close') {
+      WritableStreamDefaultControllerProcessClose(controller);
+    } else {
+      WritableStreamDefaultControllerProcessWrite(controller, writeRecord.chunk);
+    }
+  }
+
+  function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
+    if (controller._controlledWritableStream._state === 'writable') {
+      WritableStreamDefaultControllerError(controller, error);
+    }
+  }
+
+  function WritableStreamDefaultControllerProcessClose(controller) {
+    var stream = controller._controlledWritableStream;
+    WritableStreamMarkCloseRequestInFlight(stream);
+    DequeueValue(controller);
+    assert(controller._queue.length === 0, 'queue must be empty once the final write record is dequeued');
+    var sinkClosePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'close', []);
+    sinkClosePromise.then(function () {
+      WritableStreamFinishInFlightClose(stream);
+    }, function (reason) {
+      WritableStreamFinishInFlightCloseWithError(stream, reason);
+    })["catch"](rethrowAssertionErrorRejection);
+  }
+
+  function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
+    var stream = controller._controlledWritableStream;
+    WritableStreamMarkFirstWriteRequestInFlight(stream);
+    var sinkWritePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'write', [chunk, controller]);
+    sinkWritePromise.then(function () {
+      WritableStreamFinishInFlightWrite(stream);
+      var state = stream._state;
+      assert(state === 'writable' || state === 'erroring');
+      DequeueValue(controller);
+
+      if (WritableStreamCloseQueuedOrInFlight(stream) === false && state === 'writable') {
+        var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
+        WritableStreamUpdateBackpressure(stream, backpressure);
+      }
+
+      WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+    }, function (reason) {
+      WritableStreamFinishInFlightWriteWithError(stream, reason);
+    })["catch"](rethrowAssertionErrorRejection);
+  }
+
+  function WritableStreamDefaultControllerGetBackpressure(controller) {
+    var desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller);
+    return desiredSize <= 0;
+  }
+
+  function WritableStreamDefaultControllerError(controller, error) {
+    var stream = controller._controlledWritableStream;
+    assert(stream._state === 'writable');
+    WritableStreamStartErroring(stream, error);
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('WritableStream.prototype.' + name + ' can only be used on a WritableStream');
+  }
+
+  function defaultWriterBrandCheckException(name) {
+    return new TypeError('WritableStreamDefaultWriter.prototype.' + name + ' can only be used on a WritableStreamDefaultWriter');
+  }
+
+  function defaultWriterLockException(name) {
+    return new TypeError('Cannot ' + name + ' a stream using a released writer');
+  }
+
+  function defaultWriterClosedPromiseInitialize(writer) {
+    writer._closedPromise = new Promise(function (resolve, reject) {
+      writer._closedPromise_resolve = resolve;
+      writer._closedPromise_reject = reject;
+      writer._closedPromiseState = 'pending';
+    });
+  }
+
+  function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) {
+    writer._closedPromise = Promise.reject(reason);
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseInitializeAsResolved(writer) {
+    writer._closedPromise = Promise.resolve(undefined);
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'resolved';
+  }
+
+  function defaultWriterClosedPromiseReject(writer, reason) {
+    assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
+    assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
+    assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
+
+    writer._closedPromise_reject(reason);
+
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseResetToRejected(writer, reason) {
+    assert(writer._closedPromise_resolve === undefined, 'writer._closedPromise_resolve === undefined');
+    assert(writer._closedPromise_reject === undefined, 'writer._closedPromise_reject === undefined');
+    assert(writer._closedPromiseState !== 'pending', 'writer._closedPromiseState is not pending');
+    writer._closedPromise = Promise.reject(reason);
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseResolve(writer) {
+    assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
+    assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
+    assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
+
+    writer._closedPromise_resolve(undefined);
+
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'resolved';
+  }
+
+  function defaultWriterReadyPromiseInitialize(writer) {
+    writer._readyPromise = new Promise(function (resolve, reject) {
+      writer._readyPromise_resolve = resolve;
+      writer._readyPromise_reject = reject;
+    });
+    writer._readyPromiseState = 'pending';
+  }
+
+  function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) {
+    writer._readyPromise = Promise.reject(reason);
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseInitializeAsResolved(writer) {
+    writer._readyPromise = Promise.resolve(undefined);
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'fulfilled';
+  }
+
+  function defaultWriterReadyPromiseReject(writer, reason) {
+    assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
+    assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
+
+    writer._readyPromise_reject(reason);
+
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseReset(writer) {
+    assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
+    assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
+    writer._readyPromise = new Promise(function (resolve, reject) {
+      writer._readyPromise_resolve = resolve;
+      writer._readyPromise_reject = reject;
+    });
+    writer._readyPromiseState = 'pending';
+  }
+
+  function defaultWriterReadyPromiseResetToRejected(writer, reason) {
+    assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
+    assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
+    writer._readyPromise = Promise.reject(reason);
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseResolve(writer) {
+    assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
+    assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
+
+    writer._readyPromise_resolve(undefined);
+
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'fulfilled';
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _require = __w_pdfjs_require__(0),
+      IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber;
+
+  var _require2 = __w_pdfjs_require__(1),
+      assert = _require2.assert;
+
+  exports.DequeueValue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    assert(container._queue.length > 0, 'Spec-level failure: should never dequeue from an empty queue.');
+
+    var pair = container._queue.shift();
+
+    container._queueTotalSize -= pair.size;
+
+    if (container._queueTotalSize < 0) {
+      container._queueTotalSize = 0;
+    }
+
+    return pair.value;
+  };
+
+  exports.EnqueueValueWithSize = function (container, value, size) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and ' + '[[queueTotalSize]].');
+    size = Number(size);
+
+    if (!IsFiniteNonNegativeNumber(size)) {
+      throw new RangeError('Size must be a finite, non-NaN, non-negative number.');
+    }
+
+    container._queue.push({
+      value: value,
+      size: size
+    });
+
+    container._queueTotalSize += size;
+  };
+
+  exports.PeekQueueValue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    assert(container._queue.length > 0, 'Spec-level failure: should never peek at an empty queue.');
+    var pair = container._queue[0];
+    return pair.value;
+  };
+
+  exports.ResetQueue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    container._queue = [];
+    container._queueTotalSize = 0;
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(0),
+      ArrayBufferCopy = _require.ArrayBufferCopy,
+      CreateIterResultObject = _require.CreateIterResultObject,
+      IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber,
+      InvokeOrNoop = _require.InvokeOrNoop,
+      PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
+      TransferArrayBuffer = _require.TransferArrayBuffer,
+      ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
+      ValidateAndNormalizeHighWaterMark = _require.ValidateAndNormalizeHighWaterMark;
+
+  var _require2 = __w_pdfjs_require__(0),
+      createArrayFromList = _require2.createArrayFromList,
+      createDataProperty = _require2.createDataProperty,
+      typeIsObject = _require2.typeIsObject;
+
+  var _require3 = __w_pdfjs_require__(1),
+      assert = _require3.assert,
+      rethrowAssertionErrorRejection = _require3.rethrowAssertionErrorRejection;
+
+  var _require4 = __w_pdfjs_require__(3),
+      DequeueValue = _require4.DequeueValue,
+      EnqueueValueWithSize = _require4.EnqueueValueWithSize,
+      ResetQueue = _require4.ResetQueue;
+
+  var _require5 = __w_pdfjs_require__(2),
+      AcquireWritableStreamDefaultWriter = _require5.AcquireWritableStreamDefaultWriter,
+      IsWritableStream = _require5.IsWritableStream,
+      IsWritableStreamLocked = _require5.IsWritableStreamLocked,
+      WritableStreamAbort = _require5.WritableStreamAbort,
+      WritableStreamDefaultWriterCloseWithErrorPropagation = _require5.WritableStreamDefaultWriterCloseWithErrorPropagation,
+      WritableStreamDefaultWriterRelease = _require5.WritableStreamDefaultWriterRelease,
+      WritableStreamDefaultWriterWrite = _require5.WritableStreamDefaultWriterWrite,
+      WritableStreamCloseQueuedOrInFlight = _require5.WritableStreamCloseQueuedOrInFlight;
+
+  var ReadableStream = function () {
+    function ReadableStream() {
+      var underlyingSource = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          size = _ref.size,
+          highWaterMark = _ref.highWaterMark;
+
+      _classCallCheck(this, ReadableStream);
+
+      this._state = 'readable';
+      this._reader = undefined;
+      this._storedError = undefined;
+      this._disturbed = false;
+      this._readableStreamController = undefined;
+      var type = underlyingSource.type;
+      var typeString = String(type);
+
+      if (typeString === 'bytes') {
+        if (highWaterMark === undefined) {
+          highWaterMark = 0;
+        }
+
+        this._readableStreamController = new ReadableByteStreamController(this, underlyingSource, highWaterMark);
+      } else if (type === undefined) {
+        if (highWaterMark === undefined) {
+          highWaterMark = 1;
+        }
+
+        this._readableStreamController = new ReadableStreamDefaultController(this, underlyingSource, size, highWaterMark);
+      } else {
+        throw new RangeError('Invalid type is specified');
+      }
+    }
+
+    _createClass(ReadableStream, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (IsReadableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('cancel'));
+        }
+
+        if (IsReadableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('Cannot cancel a stream that already has a reader'));
+        }
+
+        return ReadableStreamCancel(this, reason);
+      }
+    }, {
+      key: 'getReader',
+      value: function getReader() {
+        var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+            mode = _ref2.mode;
+
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('getReader');
+        }
+
+        if (mode === undefined) {
+          return AcquireReadableStreamDefaultReader(this);
+        }
+
+        mode = String(mode);
+
+        if (mode === 'byob') {
+          return AcquireReadableStreamBYOBReader(this);
+        }
+
+        throw new RangeError('Invalid mode is specified');
+      }
+    }, {
+      key: 'pipeThrough',
+      value: function pipeThrough(_ref3, options) {
+        var writable = _ref3.writable,
+            readable = _ref3.readable;
+        var promise = this.pipeTo(writable, options);
+        ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise);
+        return readable;
+      }
+    }, {
+      key: 'pipeTo',
+      value: function pipeTo(dest) {
+        var _this = this;
+
+        var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+            preventClose = _ref4.preventClose,
+            preventAbort = _ref4.preventAbort,
+            preventCancel = _ref4.preventCancel;
+
+        if (IsReadableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('pipeTo'));
+        }
+
+        if (IsWritableStream(dest) === false) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream'));
+        }
+
+        preventClose = Boolean(preventClose);
+        preventAbort = Boolean(preventAbort);
+        preventCancel = Boolean(preventCancel);
+
+        if (IsReadableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream'));
+        }
+
+        if (IsWritableStreamLocked(dest) === true) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream'));
+        }
+
+        var reader = AcquireReadableStreamDefaultReader(this);
+        var writer = AcquireWritableStreamDefaultWriter(dest);
+        var shuttingDown = false;
+        var currentWrite = Promise.resolve();
+        return new Promise(function (resolve, reject) {
+          function pipeLoop() {
+            currentWrite = Promise.resolve();
+
+            if (shuttingDown === true) {
+              return Promise.resolve();
+            }
+
+            return writer._readyPromise.then(function () {
+              return ReadableStreamDefaultReaderRead(reader).then(function (_ref5) {
+                var value = _ref5.value,
+                    done = _ref5.done;
+
+                if (done === true) {
+                  return;
+                }
+
+                currentWrite = WritableStreamDefaultWriterWrite(writer, value)["catch"](function () {});
+              });
+            }).then(pipeLoop);
+          }
+
+          isOrBecomesErrored(_this, reader._closedPromise, function (storedError) {
+            if (preventAbort === false) {
+              shutdownWithAction(function () {
+                return WritableStreamAbort(dest, storedError);
+              }, true, storedError);
+            } else {
+              shutdown(true, storedError);
+            }
+          });
+          isOrBecomesErrored(dest, writer._closedPromise, function (storedError) {
+            if (preventCancel === false) {
+              shutdownWithAction(function () {
+                return ReadableStreamCancel(_this, storedError);
+              }, true, storedError);
+            } else {
+              shutdown(true, storedError);
+            }
+          });
+          isOrBecomesClosed(_this, reader._closedPromise, function () {
+            if (preventClose === false) {
+              shutdownWithAction(function () {
+                return WritableStreamDefaultWriterCloseWithErrorPropagation(writer);
+              });
+            } else {
+              shutdown();
+            }
+          });
+
+          if (WritableStreamCloseQueuedOrInFlight(dest) === true || dest._state === 'closed') {
+            var destClosed = new TypeError('the destination writable stream closed before all data could be piped to it');
+
+            if (preventCancel === false) {
+              shutdownWithAction(function () {
+                return ReadableStreamCancel(_this, destClosed);
+              }, true, destClosed);
+            } else {
+              shutdown(true, destClosed);
+            }
+          }
+
+          pipeLoop()["catch"](function (err) {
+            currentWrite = Promise.resolve();
+            rethrowAssertionErrorRejection(err);
+          });
+
+          function waitForWritesToFinish() {
+            var oldCurrentWrite = currentWrite;
+            return currentWrite.then(function () {
+              return oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined;
+            });
+          }
+
+          function isOrBecomesErrored(stream, promise, action) {
+            if (stream._state === 'errored') {
+              action(stream._storedError);
+            } else {
+              promise["catch"](action)["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function isOrBecomesClosed(stream, promise, action) {
+            if (stream._state === 'closed') {
+              action();
+            } else {
+              promise.then(action)["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function shutdownWithAction(action, originalIsError, originalError) {
+            if (shuttingDown === true) {
+              return;
+            }
+
+            shuttingDown = true;
+
+            if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
+              waitForWritesToFinish().then(doTheRest);
+            } else {
+              doTheRest();
+            }
+
+            function doTheRest() {
+              action().then(function () {
+                return finalize(originalIsError, originalError);
+              }, function (newError) {
+                return finalize(true, newError);
+              })["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function shutdown(isError, error) {
+            if (shuttingDown === true) {
+              return;
+            }
+
+            shuttingDown = true;
+
+            if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
+              waitForWritesToFinish().then(function () {
+                return finalize(isError, error);
+              })["catch"](rethrowAssertionErrorRejection);
+            } else {
+              finalize(isError, error);
+            }
+          }
+
+          function finalize(isError, error) {
+            WritableStreamDefaultWriterRelease(writer);
+            ReadableStreamReaderGenericRelease(reader);
+
+            if (isError) {
+              reject(error);
+            } else {
+              resolve(undefined);
+            }
+          }
+        });
+      }
+    }, {
+      key: 'tee',
+      value: function tee() {
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('tee');
+        }
+
+        var branches = ReadableStreamTee(this, false);
+        return createArrayFromList(branches);
+      }
+    }, {
+      key: 'locked',
+      get: function get() {
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('locked');
+        }
+
+        return IsReadableStreamLocked(this);
+      }
+    }]);
+
+    return ReadableStream;
+  }();
+
+  module.exports = {
+    ReadableStream: ReadableStream,
+    IsReadableStreamDisturbed: IsReadableStreamDisturbed,
+    ReadableStreamDefaultControllerClose: ReadableStreamDefaultControllerClose,
+    ReadableStreamDefaultControllerEnqueue: ReadableStreamDefaultControllerEnqueue,
+    ReadableStreamDefaultControllerError: ReadableStreamDefaultControllerError,
+    ReadableStreamDefaultControllerGetDesiredSize: ReadableStreamDefaultControllerGetDesiredSize
+  };
+
+  function AcquireReadableStreamBYOBReader(stream) {
+    return new ReadableStreamBYOBReader(stream);
+  }
+
+  function AcquireReadableStreamDefaultReader(stream) {
+    return new ReadableStreamDefaultReader(stream);
+  }
+
+  function IsReadableStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamDisturbed(stream) {
+    assert(IsReadableStream(stream) === true, 'IsReadableStreamDisturbed should only be used on known readable streams');
+    return stream._disturbed;
+  }
+
+  function IsReadableStreamLocked(stream) {
+    assert(IsReadableStream(stream) === true, 'IsReadableStreamLocked should only be used on known readable streams');
+
+    if (stream._reader === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamTee(stream, cloneForBranch2) {
+    assert(IsReadableStream(stream) === true);
+    assert(typeof cloneForBranch2 === 'boolean');
+    var reader = AcquireReadableStreamDefaultReader(stream);
+    var teeState = {
+      closedOrErrored: false,
+      canceled1: false,
+      canceled2: false,
+      reason1: undefined,
+      reason2: undefined
+    };
+    teeState.promise = new Promise(function (resolve) {
+      teeState._resolve = resolve;
+    });
+    var pull = create_ReadableStreamTeePullFunction();
+    pull._reader = reader;
+    pull._teeState = teeState;
+    pull._cloneForBranch2 = cloneForBranch2;
+    var cancel1 = create_ReadableStreamTeeBranch1CancelFunction();
+    cancel1._stream = stream;
+    cancel1._teeState = teeState;
+    var cancel2 = create_ReadableStreamTeeBranch2CancelFunction();
+    cancel2._stream = stream;
+    cancel2._teeState = teeState;
+    var underlyingSource1 = Object.create(Object.prototype);
+    createDataProperty(underlyingSource1, 'pull', pull);
+    createDataProperty(underlyingSource1, 'cancel', cancel1);
+    var branch1Stream = new ReadableStream(underlyingSource1);
+    var underlyingSource2 = Object.create(Object.prototype);
+    createDataProperty(underlyingSource2, 'pull', pull);
+    createDataProperty(underlyingSource2, 'cancel', cancel2);
+    var branch2Stream = new ReadableStream(underlyingSource2);
+    pull._branch1 = branch1Stream._readableStreamController;
+    pull._branch2 = branch2Stream._readableStreamController;
+
+    reader._closedPromise["catch"](function (r) {
+      if (teeState.closedOrErrored === true) {
+        return;
+      }
+
+      ReadableStreamDefaultControllerError(pull._branch1, r);
+      ReadableStreamDefaultControllerError(pull._branch2, r);
+      teeState.closedOrErrored = true;
+    });
+
+    return [branch1Stream, branch2Stream];
+  }
+
+  function create_ReadableStreamTeePullFunction() {
+    function f() {
+      var reader = f._reader,
+          branch1 = f._branch1,
+          branch2 = f._branch2,
+          teeState = f._teeState;
+      return ReadableStreamDefaultReaderRead(reader).then(function (result) {
+        assert(typeIsObject(result));
+        var value = result.value;
+        var done = result.done;
+        assert(typeof done === 'boolean');
+
+        if (done === true && teeState.closedOrErrored === false) {
+          if (teeState.canceled1 === false) {
+            ReadableStreamDefaultControllerClose(branch1);
+          }
+
+          if (teeState.canceled2 === false) {
+            ReadableStreamDefaultControllerClose(branch2);
+          }
+
+          teeState.closedOrErrored = true;
+        }
+
+        if (teeState.closedOrErrored === true) {
+          return;
+        }
+
+        var value1 = value;
+        var value2 = value;
+
+        if (teeState.canceled1 === false) {
+          ReadableStreamDefaultControllerEnqueue(branch1, value1);
+        }
+
+        if (teeState.canceled2 === false) {
+          ReadableStreamDefaultControllerEnqueue(branch2, value2);
+        }
+      });
+    }
+
+    return f;
+  }
+
+  function create_ReadableStreamTeeBranch1CancelFunction() {
+    function f(reason) {
+      var stream = f._stream,
+          teeState = f._teeState;
+      teeState.canceled1 = true;
+      teeState.reason1 = reason;
+
+      if (teeState.canceled2 === true) {
+        var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
+        var cancelResult = ReadableStreamCancel(stream, compositeReason);
+
+        teeState._resolve(cancelResult);
+      }
+
+      return teeState.promise;
+    }
+
+    return f;
+  }
+
+  function create_ReadableStreamTeeBranch2CancelFunction() {
+    function f(reason) {
+      var stream = f._stream,
+          teeState = f._teeState;
+      teeState.canceled2 = true;
+      teeState.reason2 = reason;
+
+      if (teeState.canceled1 === true) {
+        var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
+        var cancelResult = ReadableStreamCancel(stream, compositeReason);
+
+        teeState._resolve(cancelResult);
+      }
+
+      return teeState.promise;
+    }
+
+    return f;
+  }
+
+  function ReadableStreamAddReadIntoRequest(stream) {
+    assert(IsReadableStreamBYOBReader(stream._reader) === true);
+    assert(stream._state === 'readable' || stream._state === 'closed');
+    var promise = new Promise(function (resolve, reject) {
+      var readIntoRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._reader._readIntoRequests.push(readIntoRequest);
+    });
+    return promise;
+  }
+
+  function ReadableStreamAddReadRequest(stream) {
+    assert(IsReadableStreamDefaultReader(stream._reader) === true);
+    assert(stream._state === 'readable');
+    var promise = new Promise(function (resolve, reject) {
+      var readRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._reader._readRequests.push(readRequest);
+    });
+    return promise;
+  }
+
+  function ReadableStreamCancel(stream, reason) {
+    stream._disturbed = true;
+
+    if (stream._state === 'closed') {
+      return Promise.resolve(undefined);
+    }
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    ReadableStreamClose(stream);
+
+    var sourceCancelPromise = stream._readableStreamController.__cancelSteps(reason);
+
+    return sourceCancelPromise.then(function () {
+      return undefined;
+    });
+  }
+
+  function ReadableStreamClose(stream) {
+    assert(stream._state === 'readable');
+    stream._state = 'closed';
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return undefined;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === true) {
+      for (var i = 0; i < reader._readRequests.length; i++) {
+        var _resolve = reader._readRequests[i]._resolve;
+
+        _resolve(CreateIterResultObject(undefined, true));
+      }
+
+      reader._readRequests = [];
+    }
+
+    defaultReaderClosedPromiseResolve(reader);
+    return undefined;
+  }
+
+  function ReadableStreamError(stream, e) {
+    assert(IsReadableStream(stream) === true, 'stream must be ReadableStream');
+    assert(stream._state === 'readable', 'state must be readable');
+    stream._state = 'errored';
+    stream._storedError = e;
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return undefined;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === true) {
+      for (var i = 0; i < reader._readRequests.length; i++) {
+        var readRequest = reader._readRequests[i];
+
+        readRequest._reject(e);
+      }
+
+      reader._readRequests = [];
+    } else {
+      assert(IsReadableStreamBYOBReader(reader), 'reader must be ReadableStreamBYOBReader');
+
+      for (var _i = 0; _i < reader._readIntoRequests.length; _i++) {
+        var readIntoRequest = reader._readIntoRequests[_i];
+
+        readIntoRequest._reject(e);
+      }
+
+      reader._readIntoRequests = [];
+    }
+
+    defaultReaderClosedPromiseReject(reader, e);
+
+    reader._closedPromise["catch"](function () {});
+  }
+
+  function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) {
+    var reader = stream._reader;
+    assert(reader._readIntoRequests.length > 0);
+
+    var readIntoRequest = reader._readIntoRequests.shift();
+
+    readIntoRequest._resolve(CreateIterResultObject(chunk, done));
+  }
+
+  function ReadableStreamFulfillReadRequest(stream, chunk, done) {
+    var reader = stream._reader;
+    assert(reader._readRequests.length > 0);
+
+    var readRequest = reader._readRequests.shift();
+
+    readRequest._resolve(CreateIterResultObject(chunk, done));
+  }
+
+  function ReadableStreamGetNumReadIntoRequests(stream) {
+    return stream._reader._readIntoRequests.length;
+  }
+
+  function ReadableStreamGetNumReadRequests(stream) {
+    return stream._reader._readRequests.length;
+  }
+
+  function ReadableStreamHasBYOBReader(stream) {
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return false;
+    }
+
+    if (IsReadableStreamBYOBReader(reader) === false) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamHasDefaultReader(stream) {
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return false;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === false) {
+      return false;
+    }
+
+    return true;
+  }
+
+  var ReadableStreamDefaultReader = function () {
+    function ReadableStreamDefaultReader(stream) {
+      _classCallCheck(this, ReadableStreamDefaultReader);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableStreamDefaultReader can only be constructed with a ReadableStream instance');
+      }
+
+      if (IsReadableStreamLocked(stream) === true) {
+        throw new TypeError('This stream has already been locked for exclusive reading by another reader');
+      }
+
+      ReadableStreamReaderGenericInitialize(this, stream);
+      this._readRequests = [];
+    }
+
+    _createClass(ReadableStreamDefaultReader, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('cancel'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('cancel'));
+        }
+
+        return ReadableStreamReaderGenericCancel(this, reason);
+      }
+    }, {
+      key: 'read',
+      value: function read() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('read'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('read from'));
+        }
+
+        return ReadableStreamDefaultReaderRead(this);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          throw defaultReaderBrandCheckException('releaseLock');
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return;
+        }
+
+        if (this._readRequests.length > 0) {
+          throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
+        }
+
+        ReadableStreamReaderGenericRelease(this);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }]);
+
+    return ReadableStreamDefaultReader;
+  }();
+
+  var ReadableStreamBYOBReader = function () {
+    function ReadableStreamBYOBReader(stream) {
+      _classCallCheck(this, ReadableStreamBYOBReader);
+
+      if (!IsReadableStream(stream)) {
+        throw new TypeError('ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a ' + 'byte source');
+      }
+
+      if (IsReadableByteStreamController(stream._readableStreamController) === false) {
+        throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + 'source');
+      }
+
+      if (IsReadableStreamLocked(stream)) {
+        throw new TypeError('This stream has already been locked for exclusive reading by another reader');
+      }
+
+      ReadableStreamReaderGenericInitialize(this, stream);
+      this._readIntoRequests = [];
+    }
+
+    _createClass(ReadableStreamBYOBReader, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('cancel'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('cancel'));
+        }
+
+        return ReadableStreamReaderGenericCancel(this, reason);
+      }
+    }, {
+      key: 'read',
+      value: function read(view) {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('read'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('read from'));
+        }
+
+        if (!ArrayBuffer.isView(view)) {
+          return Promise.reject(new TypeError('view must be an array buffer view'));
+        }
+
+        if (view.byteLength === 0) {
+          return Promise.reject(new TypeError('view must have non-zero byteLength'));
+        }
+
+        return ReadableStreamBYOBReaderRead(this, view);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (!IsReadableStreamBYOBReader(this)) {
+          throw byobReaderBrandCheckException('releaseLock');
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return;
+        }
+
+        if (this._readIntoRequests.length > 0) {
+          throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
+        }
+
+        ReadableStreamReaderGenericRelease(this);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }]);
+
+    return ReadableStreamBYOBReader;
+  }();
+
+  function IsReadableStreamBYOBReader(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamDefaultReader(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamReaderGenericInitialize(reader, stream) {
+    reader._ownerReadableStream = stream;
+    stream._reader = reader;
+
+    if (stream._state === 'readable') {
+      defaultReaderClosedPromiseInitialize(reader);
+    } else if (stream._state === 'closed') {
+      defaultReaderClosedPromiseInitializeAsResolved(reader);
+    } else {
+      assert(stream._state === 'errored', 'state must be errored');
+      defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError);
+
+      reader._closedPromise["catch"](function () {});
+    }
+  }
+
+  function ReadableStreamReaderGenericCancel(reader, reason) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    return ReadableStreamCancel(stream, reason);
+  }
+
+  function ReadableStreamReaderGenericRelease(reader) {
+    assert(reader._ownerReadableStream !== undefined);
+    assert(reader._ownerReadableStream._reader === reader);
+
+    if (reader._ownerReadableStream._state === 'readable') {
+      defaultReaderClosedPromiseReject(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
+    } else {
+      defaultReaderClosedPromiseResetToRejected(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
+    }
+
+    reader._closedPromise["catch"](function () {});
+
+    reader._ownerReadableStream._reader = undefined;
+    reader._ownerReadableStream = undefined;
+  }
+
+  function ReadableStreamBYOBReaderRead(reader, view) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    stream._disturbed = true;
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    return ReadableByteStreamControllerPullInto(stream._readableStreamController, view);
+  }
+
+  function ReadableStreamDefaultReaderRead(reader) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    stream._disturbed = true;
+
+    if (stream._state === 'closed') {
+      return Promise.resolve(CreateIterResultObject(undefined, true));
+    }
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(stream._state === 'readable');
+    return stream._readableStreamController.__pullSteps();
+  }
+
+  var ReadableStreamDefaultController = function () {
+    function ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark) {
+      _classCallCheck(this, ReadableStreamDefaultController);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableStreamDefaultController can only be constructed with a ReadableStream instance');
+      }
+
+      if (stream._readableStreamController !== undefined) {
+        throw new TypeError('ReadableStreamDefaultController instances can only be created by the ReadableStream constructor');
+      }
+
+      this._controlledReadableStream = stream;
+      this._underlyingSource = underlyingSource;
+      this._queue = undefined;
+      this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._started = false;
+      this._closeRequested = false;
+      this._pullAgain = false;
+      this._pulling = false;
+      var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
+      this._strategySize = normalizedStrategy.size;
+      this._strategyHWM = normalizedStrategy.highWaterMark;
+      var controller = this;
+      var startResult = InvokeOrNoop(underlyingSource, 'start', [this]);
+      Promise.resolve(startResult).then(function () {
+        controller._started = true;
+        assert(controller._pulling === false);
+        assert(controller._pullAgain === false);
+        ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+      }, function (r) {
+        ReadableStreamDefaultControllerErrorIfNeeded(controller, r);
+      })["catch"](rethrowAssertionErrorRejection);
+    }
+
+    _createClass(ReadableStreamDefaultController, [{
+      key: 'close',
+      value: function close() {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('close');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('The stream has already been closed; do not close it again!');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
+        }
+
+        ReadableStreamDefaultControllerClose(this);
+      }
+    }, {
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('enqueue');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('stream is closed or draining');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
+        }
+
+        return ReadableStreamDefaultControllerEnqueue(this, chunk);
+      }
+    }, {
+      key: 'error',
+      value: function error(e) {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('error');
+        }
+
+        var stream = this._controlledReadableStream;
+
+        if (stream._state !== 'readable') {
+          throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
+        }
+
+        ReadableStreamDefaultControllerError(this, e);
+      }
+    }, {
+      key: '__cancelSteps',
+      value: function __cancelSteps(reason) {
+        ResetQueue(this);
+        return PromiseInvokeOrNoop(this._underlyingSource, 'cancel', [reason]);
+      }
+    }, {
+      key: '__pullSteps',
+      value: function __pullSteps() {
+        var stream = this._controlledReadableStream;
+
+        if (this._queue.length > 0) {
+          var chunk = DequeueValue(this);
+
+          if (this._closeRequested === true && this._queue.length === 0) {
+            ReadableStreamClose(stream);
+          } else {
+            ReadableStreamDefaultControllerCallPullIfNeeded(this);
+          }
+
+          return Promise.resolve(CreateIterResultObject(chunk, false));
+        }
+
+        var pendingPromise = ReadableStreamAddReadRequest(stream);
+        ReadableStreamDefaultControllerCallPullIfNeeded(this);
+        return pendingPromise;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('desiredSize');
+        }
+
+        return ReadableStreamDefaultControllerGetDesiredSize(this);
+      }
+    }]);
+
+    return ReadableStreamDefaultController;
+  }();
+
+  function IsReadableStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSource')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
+    var shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller);
+
+    if (shouldPull === false) {
+      return undefined;
+    }
+
+    if (controller._pulling === true) {
+      controller._pullAgain = true;
+      return undefined;
+    }
+
+    assert(controller._pullAgain === false);
+    controller._pulling = true;
+    var pullPromise = PromiseInvokeOrNoop(controller._underlyingSource, 'pull', [controller]);
+    pullPromise.then(function () {
+      controller._pulling = false;
+
+      if (controller._pullAgain === true) {
+        controller._pullAgain = false;
+        return ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+      }
+
+      return undefined;
+    }, function (e) {
+      ReadableStreamDefaultControllerErrorIfNeeded(controller, e);
+    })["catch"](rethrowAssertionErrorRejection);
+    return undefined;
+  }
+
+  function ReadableStreamDefaultControllerShouldCallPull(controller) {
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state === 'closed' || stream._state === 'errored') {
+      return false;
+    }
+
+    if (controller._closeRequested === true) {
+      return false;
+    }
+
+    if (controller._started === false) {
+      return false;
+    }
+
+    if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      return true;
+    }
+
+    var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
+
+    if (desiredSize > 0) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function ReadableStreamDefaultControllerClose(controller) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+    controller._closeRequested = true;
+
+    if (controller._queue.length === 0) {
+      ReadableStreamClose(stream);
+    }
+  }
+
+  function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+
+    if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      ReadableStreamFulfillReadRequest(stream, chunk, false);
+    } else {
+      var chunkSize = 1;
+
+      if (controller._strategySize !== undefined) {
+        var strategySize = controller._strategySize;
+
+        try {
+          chunkSize = strategySize(chunk);
+        } catch (chunkSizeE) {
+          ReadableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
+          throw chunkSizeE;
+        }
+      }
+
+      try {
+        EnqueueValueWithSize(controller, chunk, chunkSize);
+      } catch (enqueueE) {
+        ReadableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
+        throw enqueueE;
+      }
+    }
+
+    ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+    return undefined;
+  }
+
+  function ReadableStreamDefaultControllerError(controller, e) {
+    var stream = controller._controlledReadableStream;
+    assert(stream._state === 'readable');
+    ResetQueue(controller);
+    ReadableStreamError(stream, e);
+  }
+
+  function ReadableStreamDefaultControllerErrorIfNeeded(controller, e) {
+    if (controller._controlledReadableStream._state === 'readable') {
+      ReadableStreamDefaultControllerError(controller, e);
+    }
+  }
+
+  function ReadableStreamDefaultControllerGetDesiredSize(controller) {
+    var stream = controller._controlledReadableStream;
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  var ReadableStreamBYOBRequest = function () {
+    function ReadableStreamBYOBRequest(controller, view) {
+      _classCallCheck(this, ReadableStreamBYOBRequest);
+
+      this._associatedReadableByteStreamController = controller;
+      this._view = view;
+    }
+
+    _createClass(ReadableStreamBYOBRequest, [{
+      key: 'respond',
+      value: function respond(bytesWritten) {
+        if (IsReadableStreamBYOBRequest(this) === false) {
+          throw byobRequestBrandCheckException('respond');
+        }
+
+        if (this._associatedReadableByteStreamController === undefined) {
+          throw new TypeError('This BYOB request has been invalidated');
+        }
+
+        ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten);
+      }
+    }, {
+      key: 'respondWithNewView',
+      value: function respondWithNewView(view) {
+        if (IsReadableStreamBYOBRequest(this) === false) {
+          throw byobRequestBrandCheckException('respond');
+        }
+
+        if (this._associatedReadableByteStreamController === undefined) {
+          throw new TypeError('This BYOB request has been invalidated');
+        }
+
+        if (!ArrayBuffer.isView(view)) {
+          throw new TypeError('You can only respond with array buffer views');
+        }
+
+        ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view);
+      }
+    }, {
+      key: 'view',
+      get: function get() {
+        return this._view;
+      }
+    }]);
+
+    return ReadableStreamBYOBRequest;
+  }();
+
+  var ReadableByteStreamController = function () {
+    function ReadableByteStreamController(stream, underlyingByteSource, highWaterMark) {
+      _classCallCheck(this, ReadableByteStreamController);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableByteStreamController can only be constructed with a ReadableStream instance given ' + 'a byte source');
+      }
+
+      if (stream._readableStreamController !== undefined) {
+        throw new TypeError('ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte ' + 'source');
+      }
+
+      this._controlledReadableStream = stream;
+      this._underlyingByteSource = underlyingByteSource;
+      this._pullAgain = false;
+      this._pulling = false;
+      ReadableByteStreamControllerClearPendingPullIntos(this);
+      this._queue = this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._closeRequested = false;
+      this._started = false;
+      this._strategyHWM = ValidateAndNormalizeHighWaterMark(highWaterMark);
+      var autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize;
+
+      if (autoAllocateChunkSize !== undefined) {
+        if (Number.isInteger(autoAllocateChunkSize) === false || autoAllocateChunkSize <= 0) {
+          throw new RangeError('autoAllocateChunkSize must be a positive integer');
+        }
+      }
+
+      this._autoAllocateChunkSize = autoAllocateChunkSize;
+      this._pendingPullIntos = [];
+      var controller = this;
+      var startResult = InvokeOrNoop(underlyingByteSource, 'start', [this]);
+      Promise.resolve(startResult).then(function () {
+        controller._started = true;
+        assert(controller._pulling === false);
+        assert(controller._pullAgain === false);
+        ReadableByteStreamControllerCallPullIfNeeded(controller);
+      }, function (r) {
+        if (stream._state === 'readable') {
+          ReadableByteStreamControllerError(controller, r);
+        }
+      })["catch"](rethrowAssertionErrorRejection);
+    }
+
+    _createClass(ReadableByteStreamController, [{
+      key: 'close',
+      value: function close() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('close');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('The stream has already been closed; do not close it again!');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
+        }
+
+        ReadableByteStreamControllerClose(this);
+      }
+    }, {
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('enqueue');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('stream is closed or draining');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
+        }
+
+        if (!ArrayBuffer.isView(chunk)) {
+          throw new TypeError('You can only enqueue array buffer views when using a ReadableByteStreamController');
+        }
+
+        ReadableByteStreamControllerEnqueue(this, chunk);
+      }
+    }, {
+      key: 'error',
+      value: function error(e) {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('error');
+        }
+
+        var stream = this._controlledReadableStream;
+
+        if (stream._state !== 'readable') {
+          throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
+        }
+
+        ReadableByteStreamControllerError(this, e);
+      }
+    }, {
+      key: '__cancelSteps',
+      value: function __cancelSteps(reason) {
+        if (this._pendingPullIntos.length > 0) {
+          var firstDescriptor = this._pendingPullIntos[0];
+          firstDescriptor.bytesFilled = 0;
+        }
+
+        ResetQueue(this);
+        return PromiseInvokeOrNoop(this._underlyingByteSource, 'cancel', [reason]);
+      }
+    }, {
+      key: '__pullSteps',
+      value: function __pullSteps() {
+        var stream = this._controlledReadableStream;
+        assert(ReadableStreamHasDefaultReader(stream) === true);
+
+        if (this._queueTotalSize > 0) {
+          assert(ReadableStreamGetNumReadRequests(stream) === 0);
+
+          var entry = this._queue.shift();
+
+          this._queueTotalSize -= entry.byteLength;
+          ReadableByteStreamControllerHandleQueueDrain(this);
+          var view = void 0;
+
+          try {
+            view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength);
+          } catch (viewE) {
+            return Promise.reject(viewE);
+          }
+
+          return Promise.resolve(CreateIterResultObject(view, false));
+        }
+
+        var autoAllocateChunkSize = this._autoAllocateChunkSize;
+
+        if (autoAllocateChunkSize !== undefined) {
+          var buffer = void 0;
+
+          try {
+            buffer = new ArrayBuffer(autoAllocateChunkSize);
+          } catch (bufferE) {
+            return Promise.reject(bufferE);
+          }
+
+          var pullIntoDescriptor = {
+            buffer: buffer,
+            byteOffset: 0,
+            byteLength: autoAllocateChunkSize,
+            bytesFilled: 0,
+            elementSize: 1,
+            ctor: Uint8Array,
+            readerType: 'default'
+          };
+
+          this._pendingPullIntos.push(pullIntoDescriptor);
+        }
+
+        var promise = ReadableStreamAddReadRequest(stream);
+        ReadableByteStreamControllerCallPullIfNeeded(this);
+        return promise;
+      }
+    }, {
+      key: 'byobRequest',
+      get: function get() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('byobRequest');
+        }
+
+        if (this._byobRequest === undefined && this._pendingPullIntos.length > 0) {
+          var firstDescriptor = this._pendingPullIntos[0];
+          var view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled);
+          this._byobRequest = new ReadableStreamBYOBRequest(this, view);
+        }
+
+        return this._byobRequest;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('desiredSize');
+        }
+
+        return ReadableByteStreamControllerGetDesiredSize(this);
+      }
+    }]);
+
+    return ReadableByteStreamController;
+  }();
+
+  function IsReadableByteStreamController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingByteSource')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamBYOBRequest(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableByteStreamControllerCallPullIfNeeded(controller) {
+    var shouldPull = ReadableByteStreamControllerShouldCallPull(controller);
+
+    if (shouldPull === false) {
+      return undefined;
+    }
+
+    if (controller._pulling === true) {
+      controller._pullAgain = true;
+      return undefined;
+    }
+
+    assert(controller._pullAgain === false);
+    controller._pulling = true;
+    var pullPromise = PromiseInvokeOrNoop(controller._underlyingByteSource, 'pull', [controller]);
+    pullPromise.then(function () {
+      controller._pulling = false;
+
+      if (controller._pullAgain === true) {
+        controller._pullAgain = false;
+        ReadableByteStreamControllerCallPullIfNeeded(controller);
+      }
+    }, function (e) {
+      if (controller._controlledReadableStream._state === 'readable') {
+        ReadableByteStreamControllerError(controller, e);
+      }
+    })["catch"](rethrowAssertionErrorRejection);
+    return undefined;
+  }
+
+  function ReadableByteStreamControllerClearPendingPullIntos(controller) {
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    controller._pendingPullIntos = [];
+  }
+
+  function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) {
+    assert(stream._state !== 'errored', 'state must not be errored');
+    var done = false;
+
+    if (stream._state === 'closed') {
+      assert(pullIntoDescriptor.bytesFilled === 0);
+      done = true;
+    }
+
+    var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
+
+    if (pullIntoDescriptor.readerType === 'default') {
+      ReadableStreamFulfillReadRequest(stream, filledView, done);
+    } else {
+      assert(pullIntoDescriptor.readerType === 'byob');
+      ReadableStreamFulfillReadIntoRequest(stream, filledView, done);
+    }
+  }
+
+  function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) {
+    var bytesFilled = pullIntoDescriptor.bytesFilled;
+    var elementSize = pullIntoDescriptor.elementSize;
+    assert(bytesFilled <= pullIntoDescriptor.byteLength);
+    assert(bytesFilled % elementSize === 0);
+    return new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize);
+  }
+
+  function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) {
+    controller._queue.push({
+      buffer: buffer,
+      byteOffset: byteOffset,
+      byteLength: byteLength
+    });
+
+    controller._queueTotalSize += byteLength;
+  }
+
+  function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) {
+    var elementSize = pullIntoDescriptor.elementSize;
+    var currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize;
+    var maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled);
+    var maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
+    var maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize;
+    var totalBytesToCopyRemaining = maxBytesToCopy;
+    var ready = false;
+
+    if (maxAlignedBytes > currentAlignedBytes) {
+      totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
+      ready = true;
+    }
+
+    var queue = controller._queue;
+
+    while (totalBytesToCopyRemaining > 0) {
+      var headOfQueue = queue[0];
+      var bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength);
+      var destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+      ArrayBufferCopy(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy);
+
+      if (headOfQueue.byteLength === bytesToCopy) {
+        queue.shift();
+      } else {
+        headOfQueue.byteOffset += bytesToCopy;
+        headOfQueue.byteLength -= bytesToCopy;
+      }
+
+      controller._queueTotalSize -= bytesToCopy;
+      ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor);
+      totalBytesToCopyRemaining -= bytesToCopy;
+    }
+
+    if (ready === false) {
+      assert(controller._queueTotalSize === 0, 'queue must be empty');
+      assert(pullIntoDescriptor.bytesFilled > 0);
+      assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
+    }
+
+    return ready;
+  }
+
+  function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) {
+    assert(controller._pendingPullIntos.length === 0 || controller._pendingPullIntos[0] === pullIntoDescriptor);
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    pullIntoDescriptor.bytesFilled += size;
+  }
+
+  function ReadableByteStreamControllerHandleQueueDrain(controller) {
+    assert(controller._controlledReadableStream._state === 'readable');
+
+    if (controller._queueTotalSize === 0 && controller._closeRequested === true) {
+      ReadableStreamClose(controller._controlledReadableStream);
+    } else {
+      ReadableByteStreamControllerCallPullIfNeeded(controller);
+    }
+  }
+
+  function ReadableByteStreamControllerInvalidateBYOBRequest(controller) {
+    if (controller._byobRequest === undefined) {
+      return;
+    }
+
+    controller._byobRequest._associatedReadableByteStreamController = undefined;
+    controller._byobRequest._view = undefined;
+    controller._byobRequest = undefined;
+  }
+
+  function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) {
+    assert(controller._closeRequested === false);
+
+    while (controller._pendingPullIntos.length > 0) {
+      if (controller._queueTotalSize === 0) {
+        return;
+      }
+
+      var pullIntoDescriptor = controller._pendingPullIntos[0];
+
+      if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
+        ReadableByteStreamControllerShiftPendingPullInto(controller);
+        ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
+      }
+    }
+  }
+
+  function ReadableByteStreamControllerPullInto(controller, view) {
+    var stream = controller._controlledReadableStream;
+    var elementSize = 1;
+
+    if (view.constructor !== DataView) {
+      elementSize = view.constructor.BYTES_PER_ELEMENT;
+    }
+
+    var ctor = view.constructor;
+    var pullIntoDescriptor = {
+      buffer: view.buffer,
+      byteOffset: view.byteOffset,
+      byteLength: view.byteLength,
+      bytesFilled: 0,
+      elementSize: elementSize,
+      ctor: ctor,
+      readerType: 'byob'
+    };
+
+    if (controller._pendingPullIntos.length > 0) {
+      pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+
+      controller._pendingPullIntos.push(pullIntoDescriptor);
+
+      return ReadableStreamAddReadIntoRequest(stream);
+    }
+
+    if (stream._state === 'closed') {
+      var emptyView = new view.constructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0);
+      return Promise.resolve(CreateIterResultObject(emptyView, true));
+    }
+
+    if (controller._queueTotalSize > 0) {
+      if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
+        var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
+        ReadableByteStreamControllerHandleQueueDrain(controller);
+        return Promise.resolve(CreateIterResultObject(filledView, false));
+      }
+
+      if (controller._closeRequested === true) {
+        var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
+        ReadableByteStreamControllerError(controller, e);
+        return Promise.reject(e);
+      }
+    }
+
+    pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+
+    controller._pendingPullIntos.push(pullIntoDescriptor);
+
+    var promise = ReadableStreamAddReadIntoRequest(stream);
+    ReadableByteStreamControllerCallPullIfNeeded(controller);
+    return promise;
+  }
+
+  function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) {
+    firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer);
+    assert(firstDescriptor.bytesFilled === 0, 'bytesFilled must be 0');
+    var stream = controller._controlledReadableStream;
+
+    if (ReadableStreamHasBYOBReader(stream) === true) {
+      while (ReadableStreamGetNumReadIntoRequests(stream) > 0) {
+        var pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller);
+        ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor);
+      }
+    }
+  }
+
+  function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) {
+    if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) {
+      throw new RangeError('bytesWritten out of range');
+    }
+
+    ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor);
+
+    if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
+      return;
+    }
+
+    ReadableByteStreamControllerShiftPendingPullInto(controller);
+    var remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize;
+
+    if (remainderSize > 0) {
+      var end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+      var remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end);
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength);
+    }
+
+    pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+    pullIntoDescriptor.bytesFilled -= remainderSize;
+    ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
+    ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
+  }
+
+  function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) {
+    var firstDescriptor = controller._pendingPullIntos[0];
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state === 'closed') {
+      if (bytesWritten !== 0) {
+        throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream');
+      }
+
+      ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
+    } else {
+      assert(stream._state === 'readable');
+      ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
+    }
+  }
+
+  function ReadableByteStreamControllerShiftPendingPullInto(controller) {
+    var descriptor = controller._pendingPullIntos.shift();
+
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    return descriptor;
+  }
+
+  function ReadableByteStreamControllerShouldCallPull(controller) {
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state !== 'readable') {
+      return false;
+    }
+
+    if (controller._closeRequested === true) {
+      return false;
+    }
+
+    if (controller._started === false) {
+      return false;
+    }
+
+    if (ReadableStreamHasDefaultReader(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      return true;
+    }
+
+    if (ReadableStreamHasBYOBReader(stream) === true && ReadableStreamGetNumReadIntoRequests(stream) > 0) {
+      return true;
+    }
+
+    if (ReadableByteStreamControllerGetDesiredSize(controller) > 0) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function ReadableByteStreamControllerClose(controller) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+
+    if (controller._queueTotalSize > 0) {
+      controller._closeRequested = true;
+      return;
+    }
+
+    if (controller._pendingPullIntos.length > 0) {
+      var firstPendingPullInto = controller._pendingPullIntos[0];
+
+      if (firstPendingPullInto.bytesFilled > 0) {
+        var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
+        ReadableByteStreamControllerError(controller, e);
+        throw e;
+      }
+    }
+
+    ReadableStreamClose(stream);
+  }
+
+  function ReadableByteStreamControllerEnqueue(controller, chunk) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+    var buffer = chunk.buffer;
+    var byteOffset = chunk.byteOffset;
+    var byteLength = chunk.byteLength;
+    var transferredBuffer = TransferArrayBuffer(buffer);
+
+    if (ReadableStreamHasDefaultReader(stream) === true) {
+      if (ReadableStreamGetNumReadRequests(stream) === 0) {
+        ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+      } else {
+        assert(controller._queue.length === 0);
+        var transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength);
+        ReadableStreamFulfillReadRequest(stream, transferredView, false);
+      }
+    } else if (ReadableStreamHasBYOBReader(stream) === true) {
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+      ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
+    } else {
+      assert(IsReadableStreamLocked(stream) === false, 'stream must not be locked');
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+    }
+  }
+
+  function ReadableByteStreamControllerError(controller, e) {
+    var stream = controller._controlledReadableStream;
+    assert(stream._state === 'readable');
+    ReadableByteStreamControllerClearPendingPullIntos(controller);
+    ResetQueue(controller);
+    ReadableStreamError(stream, e);
+  }
+
+  function ReadableByteStreamControllerGetDesiredSize(controller) {
+    var stream = controller._controlledReadableStream;
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  function ReadableByteStreamControllerRespond(controller, bytesWritten) {
+    bytesWritten = Number(bytesWritten);
+
+    if (IsFiniteNonNegativeNumber(bytesWritten) === false) {
+      throw new RangeError('bytesWritten must be a finite');
+    }
+
+    assert(controller._pendingPullIntos.length > 0);
+    ReadableByteStreamControllerRespondInternal(controller, bytesWritten);
+  }
+
+  function ReadableByteStreamControllerRespondWithNewView(controller, view) {
+    assert(controller._pendingPullIntos.length > 0);
+    var firstDescriptor = controller._pendingPullIntos[0];
+
+    if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) {
+      throw new RangeError('The region specified by view does not match byobRequest');
+    }
+
+    if (firstDescriptor.byteLength !== view.byteLength) {
+      throw new RangeError('The buffer of view has different capacity than byobRequest');
+    }
+
+    firstDescriptor.buffer = view.buffer;
+    ReadableByteStreamControllerRespondInternal(controller, view.byteLength);
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('ReadableStream.prototype.' + name + ' can only be used on a ReadableStream');
+  }
+
+  function readerLockException(name) {
+    return new TypeError('Cannot ' + name + ' a stream using a released reader');
+  }
+
+  function defaultReaderBrandCheckException(name) {
+    return new TypeError('ReadableStreamDefaultReader.prototype.' + name + ' can only be used on a ReadableStreamDefaultReader');
+  }
+
+  function defaultReaderClosedPromiseInitialize(reader) {
+    reader._closedPromise = new Promise(function (resolve, reject) {
+      reader._closedPromise_resolve = resolve;
+      reader._closedPromise_reject = reject;
+    });
+  }
+
+  function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) {
+    reader._closedPromise = Promise.reject(reason);
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseInitializeAsResolved(reader) {
+    reader._closedPromise = Promise.resolve(undefined);
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseReject(reader, reason) {
+    assert(reader._closedPromise_resolve !== undefined);
+    assert(reader._closedPromise_reject !== undefined);
+
+    reader._closedPromise_reject(reason);
+
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseResetToRejected(reader, reason) {
+    assert(reader._closedPromise_resolve === undefined);
+    assert(reader._closedPromise_reject === undefined);
+    reader._closedPromise = Promise.reject(reason);
+  }
+
+  function defaultReaderClosedPromiseResolve(reader) {
+    assert(reader._closedPromise_resolve !== undefined);
+    assert(reader._closedPromise_reject !== undefined);
+
+    reader._closedPromise_resolve(undefined);
+
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function byobReaderBrandCheckException(name) {
+    return new TypeError('ReadableStreamBYOBReader.prototype.' + name + ' can only be used on a ReadableStreamBYOBReader');
+  }
+
+  function defaultControllerBrandCheckException(name) {
+    return new TypeError('ReadableStreamDefaultController.prototype.' + name + ' can only be used on a ReadableStreamDefaultController');
+  }
+
+  function byobRequestBrandCheckException(name) {
+    return new TypeError('ReadableStreamBYOBRequest.prototype.' + name + ' can only be used on a ReadableStreamBYOBRequest');
+  }
+
+  function byteStreamControllerBrandCheckException(name) {
+    return new TypeError('ReadableByteStreamController.prototype.' + name + ' can only be used on a ReadableByteStreamController');
+  }
+
+  function ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise) {
+    try {
+      Promise.prototype.then.call(promise, undefined, function () {});
+    } catch (e) {}
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var transformStream = __w_pdfjs_require__(6);
+
+  var readableStream = __w_pdfjs_require__(4);
+
+  var writableStream = __w_pdfjs_require__(2);
+
+  exports.TransformStream = transformStream.TransformStream;
+  exports.ReadableStream = readableStream.ReadableStream;
+  exports.IsReadableStreamDisturbed = readableStream.IsReadableStreamDisturbed;
+  exports.ReadableStreamDefaultControllerClose = readableStream.ReadableStreamDefaultControllerClose;
+  exports.ReadableStreamDefaultControllerEnqueue = readableStream.ReadableStreamDefaultControllerEnqueue;
+  exports.ReadableStreamDefaultControllerError = readableStream.ReadableStreamDefaultControllerError;
+  exports.ReadableStreamDefaultControllerGetDesiredSize = readableStream.ReadableStreamDefaultControllerGetDesiredSize;
+  exports.AcquireWritableStreamDefaultWriter = writableStream.AcquireWritableStreamDefaultWriter;
+  exports.IsWritableStream = writableStream.IsWritableStream;
+  exports.IsWritableStreamLocked = writableStream.IsWritableStreamLocked;
+  exports.WritableStream = writableStream.WritableStream;
+  exports.WritableStreamAbort = writableStream.WritableStreamAbort;
+  exports.WritableStreamDefaultControllerError = writableStream.WritableStreamDefaultControllerError;
+  exports.WritableStreamDefaultWriterCloseWithErrorPropagation = writableStream.WritableStreamDefaultWriterCloseWithErrorPropagation;
+  exports.WritableStreamDefaultWriterRelease = writableStream.WritableStreamDefaultWriterRelease;
+  exports.WritableStreamDefaultWriterWrite = writableStream.WritableStreamDefaultWriterWrite;
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(1),
+      assert = _require.assert;
+
+  var _require2 = __w_pdfjs_require__(0),
+      InvokeOrNoop = _require2.InvokeOrNoop,
+      PromiseInvokeOrPerformFallback = _require2.PromiseInvokeOrPerformFallback,
+      PromiseInvokeOrNoop = _require2.PromiseInvokeOrNoop,
+      typeIsObject = _require2.typeIsObject;
+
+  var _require3 = __w_pdfjs_require__(4),
+      ReadableStream = _require3.ReadableStream,
+      ReadableStreamDefaultControllerClose = _require3.ReadableStreamDefaultControllerClose,
+      ReadableStreamDefaultControllerEnqueue = _require3.ReadableStreamDefaultControllerEnqueue,
+      ReadableStreamDefaultControllerError = _require3.ReadableStreamDefaultControllerError,
+      ReadableStreamDefaultControllerGetDesiredSize = _require3.ReadableStreamDefaultControllerGetDesiredSize;
+
+  var _require4 = __w_pdfjs_require__(2),
+      WritableStream = _require4.WritableStream,
+      WritableStreamDefaultControllerError = _require4.WritableStreamDefaultControllerError;
+
+  function TransformStreamCloseReadable(transformStream) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    if (transformStream._readableClosed === true) {
+      throw new TypeError('Readable side is already closed');
+    }
+
+    TransformStreamCloseReadableInternal(transformStream);
+  }
+
+  function TransformStreamEnqueueToReadable(transformStream, chunk) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    if (transformStream._readableClosed === true) {
+      throw new TypeError('Readable side is already closed');
+    }
+
+    var controller = transformStream._readableController;
+
+    try {
+      ReadableStreamDefaultControllerEnqueue(controller, chunk);
+    } catch (e) {
+      transformStream._readableClosed = true;
+      TransformStreamErrorIfNeeded(transformStream, e);
+      throw transformStream._storedError;
+    }
+
+    var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
+    var maybeBackpressure = desiredSize <= 0;
+
+    if (maybeBackpressure === true && transformStream._backpressure === false) {
+      TransformStreamSetBackpressure(transformStream, true);
+    }
+  }
+
+  function TransformStreamError(transformStream, e) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    TransformStreamErrorInternal(transformStream, e);
+  }
+
+  function TransformStreamCloseReadableInternal(transformStream) {
+    assert(transformStream._errored === false);
+    assert(transformStream._readableClosed === false);
+
+    try {
+      ReadableStreamDefaultControllerClose(transformStream._readableController);
+    } catch (e) {
+      assert(false);
+    }
+
+    transformStream._readableClosed = true;
+  }
+
+  function TransformStreamErrorIfNeeded(transformStream, e) {
+    if (transformStream._errored === false) {
+      TransformStreamErrorInternal(transformStream, e);
+    }
+  }
+
+  function TransformStreamErrorInternal(transformStream, e) {
+    assert(transformStream._errored === false);
+    transformStream._errored = true;
+    transformStream._storedError = e;
+
+    if (transformStream._writableDone === false) {
+      WritableStreamDefaultControllerError(transformStream._writableController, e);
+    }
+
+    if (transformStream._readableClosed === false) {
+      ReadableStreamDefaultControllerError(transformStream._readableController, e);
+    }
+  }
+
+  function TransformStreamReadableReadyPromise(transformStream) {
+    assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+
+    if (transformStream._backpressure === false) {
+      return Promise.resolve();
+    }
+
+    assert(transformStream._backpressure === true, '_backpressure should have been initialized');
+    return transformStream._backpressureChangePromise;
+  }
+
+  function TransformStreamSetBackpressure(transformStream, backpressure) {
+    assert(transformStream._backpressure !== backpressure, 'TransformStreamSetBackpressure() should be called only when backpressure is changed');
+
+    if (transformStream._backpressureChangePromise !== undefined) {
+      transformStream._backpressureChangePromise_resolve(backpressure);
+    }
+
+    transformStream._backpressureChangePromise = new Promise(function (resolve) {
+      transformStream._backpressureChangePromise_resolve = resolve;
+    });
+
+    transformStream._backpressureChangePromise.then(function (resolution) {
+      assert(resolution !== backpressure, '_backpressureChangePromise should be fulfilled only when backpressure is changed');
+    });
+
+    transformStream._backpressure = backpressure;
+  }
+
+  function TransformStreamDefaultTransform(chunk, transformStreamController) {
+    var transformStream = transformStreamController._controlledTransformStream;
+    TransformStreamEnqueueToReadable(transformStream, chunk);
+    return Promise.resolve();
+  }
+
+  function TransformStreamTransform(transformStream, chunk) {
+    assert(transformStream._errored === false);
+    assert(transformStream._transforming === false);
+    assert(transformStream._backpressure === false);
+    transformStream._transforming = true;
+    var transformer = transformStream._transformer;
+    var controller = transformStream._transformStreamController;
+    var transformPromise = PromiseInvokeOrPerformFallback(transformer, 'transform', [chunk, controller], TransformStreamDefaultTransform, [chunk, controller]);
+    return transformPromise.then(function () {
+      transformStream._transforming = false;
+      return TransformStreamReadableReadyPromise(transformStream);
+    }, function (e) {
+      TransformStreamErrorIfNeeded(transformStream, e);
+      return Promise.reject(e);
+    });
+  }
+
+  function IsTransformStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsTransformStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  var TransformStreamSink = function () {
+    function TransformStreamSink(transformStream, startPromise) {
+      _classCallCheck(this, TransformStreamSink);
+
+      this._transformStream = transformStream;
+      this._startPromise = startPromise;
+    }
+
+    _createClass(TransformStreamSink, [{
+      key: 'start',
+      value: function start(c) {
+        var transformStream = this._transformStream;
+        transformStream._writableController = c;
+        return this._startPromise.then(function () {
+          return TransformStreamReadableReadyPromise(transformStream);
+        });
+      }
+    }, {
+      key: 'write',
+      value: function write(chunk) {
+        var transformStream = this._transformStream;
+        return TransformStreamTransform(transformStream, chunk);
+      }
+    }, {
+      key: 'abort',
+      value: function abort() {
+        var transformStream = this._transformStream;
+        transformStream._writableDone = true;
+        TransformStreamErrorInternal(transformStream, new TypeError('Writable side aborted'));
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        var transformStream = this._transformStream;
+        assert(transformStream._transforming === false);
+        transformStream._writableDone = true;
+        var flushPromise = PromiseInvokeOrNoop(transformStream._transformer, 'flush', [transformStream._transformStreamController]);
+        return flushPromise.then(function () {
+          if (transformStream._errored === true) {
+            return Promise.reject(transformStream._storedError);
+          }
+
+          if (transformStream._readableClosed === false) {
+            TransformStreamCloseReadableInternal(transformStream);
+          }
+
+          return Promise.resolve();
+        })["catch"](function (r) {
+          TransformStreamErrorIfNeeded(transformStream, r);
+          return Promise.reject(transformStream._storedError);
+        });
+      }
+    }]);
+
+    return TransformStreamSink;
+  }();
+
+  var TransformStreamSource = function () {
+    function TransformStreamSource(transformStream, startPromise) {
+      _classCallCheck(this, TransformStreamSource);
+
+      this._transformStream = transformStream;
+      this._startPromise = startPromise;
+    }
+
+    _createClass(TransformStreamSource, [{
+      key: 'start',
+      value: function start(c) {
+        var transformStream = this._transformStream;
+        transformStream._readableController = c;
+        return this._startPromise.then(function () {
+          assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+
+          if (transformStream._backpressure === true) {
+            return Promise.resolve();
+          }
+
+          assert(transformStream._backpressure === false, '_backpressure should have been initialized');
+          return transformStream._backpressureChangePromise;
+        });
+      }
+    }, {
+      key: 'pull',
+      value: function pull() {
+        var transformStream = this._transformStream;
+        assert(transformStream._backpressure === true, 'pull() should be never called while _backpressure is false');
+        assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+        TransformStreamSetBackpressure(transformStream, false);
+        return transformStream._backpressureChangePromise;
+      }
+    }, {
+      key: 'cancel',
+      value: function cancel() {
+        var transformStream = this._transformStream;
+        transformStream._readableClosed = true;
+        TransformStreamErrorInternal(transformStream, new TypeError('Readable side canceled'));
+      }
+    }]);
+
+    return TransformStreamSource;
+  }();
+
+  var TransformStreamDefaultController = function () {
+    function TransformStreamDefaultController(transformStream) {
+      _classCallCheck(this, TransformStreamDefaultController);
+
+      if (IsTransformStream(transformStream) === false) {
+        throw new TypeError('TransformStreamDefaultController can only be ' + 'constructed with a TransformStream instance');
+      }
+
+      if (transformStream._transformStreamController !== undefined) {
+        throw new TypeError('TransformStreamDefaultController instances can ' + 'only be created by the TransformStream constructor');
+      }
+
+      this._controlledTransformStream = transformStream;
+    }
+
+    _createClass(TransformStreamDefaultController, [{
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('enqueue');
+        }
+
+        TransformStreamEnqueueToReadable(this._controlledTransformStream, chunk);
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('close');
+        }
+
+        TransformStreamCloseReadable(this._controlledTransformStream);
+      }
+    }, {
+      key: 'error',
+      value: function error(reason) {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('error');
+        }
+
+        TransformStreamError(this._controlledTransformStream, reason);
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('desiredSize');
+        }
+
+        var transformStream = this._controlledTransformStream;
+        var readableController = transformStream._readableController;
+        return ReadableStreamDefaultControllerGetDesiredSize(readableController);
+      }
+    }]);
+
+    return TransformStreamDefaultController;
+  }();
+
+  var TransformStream = function () {
+    function TransformStream() {
+      var transformer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      _classCallCheck(this, TransformStream);
+
+      this._transformer = transformer;
+      var readableStrategy = transformer.readableStrategy,
+          writableStrategy = transformer.writableStrategy;
+      this._transforming = false;
+      this._errored = false;
+      this._storedError = undefined;
+      this._writableController = undefined;
+      this._readableController = undefined;
+      this._transformStreamController = undefined;
+      this._writableDone = false;
+      this._readableClosed = false;
+      this._backpressure = undefined;
+      this._backpressureChangePromise = undefined;
+      this._backpressureChangePromise_resolve = undefined;
+      this._transformStreamController = new TransformStreamDefaultController(this);
+      var startPromise_resolve = void 0;
+      var startPromise = new Promise(function (resolve) {
+        startPromise_resolve = resolve;
+      });
+      var source = new TransformStreamSource(this, startPromise);
+      this._readable = new ReadableStream(source, readableStrategy);
+      var sink = new TransformStreamSink(this, startPromise);
+      this._writable = new WritableStream(sink, writableStrategy);
+      assert(this._writableController !== undefined);
+      assert(this._readableController !== undefined);
+      var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(this._readableController);
+      TransformStreamSetBackpressure(this, desiredSize <= 0);
+      var transformStream = this;
+      var startResult = InvokeOrNoop(transformer, 'start', [transformStream._transformStreamController]);
+      startPromise_resolve(startResult);
+      startPromise["catch"](function (e) {
+        if (transformStream._errored === false) {
+          transformStream._errored = true;
+          transformStream._storedError = e;
+        }
+      });
+    }
+
+    _createClass(TransformStream, [{
+      key: 'readable',
+      get: function get() {
+        if (IsTransformStream(this) === false) {
+          throw streamBrandCheckException('readable');
+        }
+
+        return this._readable;
+      }
+    }, {
+      key: 'writable',
+      get: function get() {
+        if (IsTransformStream(this) === false) {
+          throw streamBrandCheckException('writable');
+        }
+
+        return this._writable;
+      }
+    }]);
+
+    return TransformStream;
+  }();
+
+  module.exports = {
+    TransformStream: TransformStream
+  };
+
+  function defaultControllerBrandCheckException(name) {
+    return new TypeError('TransformStreamDefaultController.prototype.' + name + ' can only be used on a TransformStreamDefaultController');
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('TransformStream.prototype.' + name + ' can only be used on a TransformStream');
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  module.exports = __w_pdfjs_require__(5);
+}]));
+
+/***/ }),
+/* 145 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+{
+  var isURLSupported = false;
+
+  try {
+    if (typeof URL === 'function' && _typeof(URL.prototype) === 'object' && 'origin' in URL.prototype) {
+      var u = new URL('b', 'http://a');
+      u.pathname = 'c%20d';
+      isURLSupported = u.href === 'http://a/c%20d';
+    }
+  } catch (ex) {}
+
+  if (isURLSupported) {
+    exports.URL = URL;
+  } else {
+    var PolyfillURL = __w_pdfjs_require__(146).URL;
+
+    var OriginalURL = __w_pdfjs_require__(3).URL;
+
+    if (OriginalURL) {
+      PolyfillURL.createObjectURL = function (blob) {
+        return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
+      };
+
+      PolyfillURL.revokeObjectURL = function (url) {
+        OriginalURL.revokeObjectURL(url);
+      };
+    }
+
+    exports.URL = PolyfillURL;
+  }
+}
+
+/***/ }),
+/* 146 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+(function URLConstructorClosure() {
+  'use strict';
+
+  var relative = Object.create(null);
+  relative['ftp'] = 21;
+  relative['file'] = 0;
+  relative['gopher'] = 70;
+  relative['http'] = 80;
+  relative['https'] = 443;
+  relative['ws'] = 80;
+  relative['wss'] = 443;
+  var relativePathDotMapping = Object.create(null);
+  relativePathDotMapping['%2e'] = '.';
+  relativePathDotMapping['.%2e'] = '..';
+  relativePathDotMapping['%2e.'] = '..';
+  relativePathDotMapping['%2e%2e'] = '..';
+
+  function isRelativeScheme(scheme) {
+    return relative[scheme] !== undefined;
+  }
+
+  function invalid() {
+    clear.call(this);
+    this._isInvalid = true;
+  }
+
+  function IDNAToASCII(h) {
+    if (h === '') {
+      invalid.call(this);
+    }
+
+    return h.toLowerCase();
+  }
+
+  function percentEscape(c) {
+    var unicode = c.charCodeAt(0);
+
+    if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1) {
+      return c;
+    }
+
+    return encodeURIComponent(c);
+  }
+
+  function percentEscapeQuery(c) {
+    var unicode = c.charCodeAt(0);
+
+    if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1) {
+      return c;
+    }
+
+    return encodeURIComponent(c);
+  }
+
+  var EOF,
+      ALPHA = /[a-zA-Z]/,
+      ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
+
+  function parse(input, stateOverride, base) {
+    function err(message) {
+      errors.push(message);
+    }
+
+    var state = stateOverride || 'scheme start',
+        cursor = 0,
+        buffer = '',
+        seenAt = false,
+        seenBracket = false,
+        errors = [];
+
+    loop: while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) {
+      var c = input[cursor];
+
+      switch (state) {
+        case 'scheme start':
+          if (c && ALPHA.test(c)) {
+            buffer += c.toLowerCase();
+            state = 'scheme';
+          } else if (!stateOverride) {
+            buffer = '';
+            state = 'no scheme';
+            continue;
+          } else {
+            err('Invalid scheme.');
+            break loop;
+          }
+
+          break;
+
+        case 'scheme':
+          if (c && ALPHANUMERIC.test(c)) {
+            buffer += c.toLowerCase();
+          } else if (c === ':') {
+            this._scheme = buffer;
+            buffer = '';
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            if (isRelativeScheme(this._scheme)) {
+              this._isRelative = true;
+            }
+
+            if (this._scheme === 'file') {
+              state = 'relative';
+            } else if (this._isRelative && base && base._scheme === this._scheme) {
+              state = 'relative or authority';
+            } else if (this._isRelative) {
+              state = 'authority first slash';
+            } else {
+              state = 'scheme data';
+            }
+          } else if (!stateOverride) {
+            buffer = '';
+            cursor = 0;
+            state = 'no scheme';
+            continue;
+          } else if (c === EOF) {
+            break loop;
+          } else {
+            err('Code point not allowed in scheme: ' + c);
+            break loop;
+          }
+
+          break;
+
+        case 'scheme data':
+          if (c === '?') {
+            this._query = '?';
+            state = 'query';
+          } else if (c === '#') {
+            this._fragment = '#';
+            state = 'fragment';
+          } else {
+            if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+              this._schemeData += percentEscape(c);
+            }
+          }
+
+          break;
+
+        case 'no scheme':
+          if (!base || !isRelativeScheme(base._scheme)) {
+            err('Missing scheme.');
+            invalid.call(this);
+          } else {
+            state = 'relative';
+            continue;
+          }
+
+          break;
+
+        case 'relative or authority':
+          if (c === '/' && input[cursor + 1] === '/') {
+            state = 'authority ignore slashes';
+          } else {
+            err('Expected /, got: ' + c);
+            state = 'relative';
+            continue;
+          }
+
+          break;
+
+        case 'relative':
+          this._isRelative = true;
+
+          if (this._scheme !== 'file') {
+            this._scheme = base._scheme;
+          }
+
+          if (c === EOF) {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            this._username = base._username;
+            this._password = base._password;
+            break loop;
+          } else if (c === '/' || c === '\\') {
+            if (c === '\\') {
+              err('\\ is an invalid code point.');
+            }
+
+            state = 'relative slash';
+          } else if (c === '?') {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = '?';
+            this._username = base._username;
+            this._password = base._password;
+            state = 'query';
+          } else if (c === '#') {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            this._fragment = '#';
+            this._username = base._username;
+            this._password = base._password;
+            state = 'fragment';
+          } else {
+            var nextC = input[cursor + 1];
+            var nextNextC = input[cursor + 2];
+
+            if (this._scheme !== 'file' || !ALPHA.test(c) || nextC !== ':' && nextC !== '|' || nextNextC !== EOF && nextNextC !== '/' && nextNextC !== '\\' && nextNextC !== '?' && nextNextC !== '#') {
+              this._host = base._host;
+              this._port = base._port;
+              this._username = base._username;
+              this._password = base._password;
+              this._path = base._path.slice();
+
+              this._path.pop();
+            }
+
+            state = 'relative path';
+            continue;
+          }
+
+          break;
+
+        case 'relative slash':
+          if (c === '/' || c === '\\') {
+            if (c === '\\') {
+              err('\\ is an invalid code point.');
+            }
+
+            if (this._scheme === 'file') {
+              state = 'file host';
+            } else {
+              state = 'authority ignore slashes';
+            }
+          } else {
+            if (this._scheme !== 'file') {
+              this._host = base._host;
+              this._port = base._port;
+              this._username = base._username;
+              this._password = base._password;
+            }
+
+            state = 'relative path';
+            continue;
+          }
+
+          break;
+
+        case 'authority first slash':
+          if (c === '/') {
+            state = 'authority second slash';
+          } else {
+            err('Expected \'/\', got: ' + c);
+            state = 'authority ignore slashes';
+            continue;
+          }
+
+          break;
+
+        case 'authority second slash':
+          state = 'authority ignore slashes';
+
+          if (c !== '/') {
+            err('Expected \'/\', got: ' + c);
+            continue;
+          }
+
+          break;
+
+        case 'authority ignore slashes':
+          if (c !== '/' && c !== '\\') {
+            state = 'authority';
+            continue;
+          } else {
+            err('Expected authority, got: ' + c);
+          }
+
+          break;
+
+        case 'authority':
+          if (c === '@') {
+            if (seenAt) {
+              err('@ already seen.');
+              buffer += '%40';
+            }
+
+            seenAt = true;
+
+            for (var i = 0; i < buffer.length; i++) {
+              var cp = buffer[i];
+
+              if (cp === '\t' || cp === '\n' || cp === '\r') {
+                err('Invalid whitespace in authority.');
+                continue;
+              }
+
+              if (cp === ':' && this._password === null) {
+                this._password = '';
+                continue;
+              }
+
+              var tempC = percentEscape(cp);
+
+              if (this._password !== null) {
+                this._password += tempC;
+              } else {
+                this._username += tempC;
+              }
+            }
+
+            buffer = '';
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            cursor -= buffer.length;
+            buffer = '';
+            state = 'host';
+            continue;
+          } else {
+            buffer += c;
+          }
+
+          break;
+
+        case 'file host':
+          if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) {
+              state = 'relative path';
+            } else if (buffer.length === 0) {
+              state = 'relative path start';
+            } else {
+              this._host = IDNAToASCII.call(this, buffer);
+              buffer = '';
+              state = 'relative path start';
+            }
+
+            continue;
+          } else if (c === '\t' || c === '\n' || c === '\r') {
+            err('Invalid whitespace in file host.');
+          } else {
+            buffer += c;
+          }
+
+          break;
+
+        case 'host':
+        case 'hostname':
+          if (c === ':' && !seenBracket) {
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'port';
+
+            if (stateOverride === 'hostname') {
+              break loop;
+            }
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'relative path start';
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            continue;
+          } else if (c !== '\t' && c !== '\n' && c !== '\r') {
+            if (c === '[') {
+              seenBracket = true;
+            } else if (c === ']') {
+              seenBracket = false;
+            }
+
+            buffer += c;
+          } else {
+            err('Invalid code point in host/hostname: ' + c);
+          }
+
+          break;
+
+        case 'port':
+          if (/[0-9]/.test(c)) {
+            buffer += c;
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#' || stateOverride) {
+            if (buffer !== '') {
+              var temp = parseInt(buffer, 10);
+
+              if (temp !== relative[this._scheme]) {
+                this._port = temp + '';
+              }
+
+              buffer = '';
+            }
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            state = 'relative path start';
+            continue;
+          } else if (c === '\t' || c === '\n' || c === '\r') {
+            err('Invalid code point in port: ' + c);
+          } else {
+            invalid.call(this);
+          }
+
+          break;
+
+        case 'relative path start':
+          if (c === '\\') {
+            err('\'\\\' not allowed in path.');
+          }
+
+          state = 'relative path';
+
+          if (c !== '/' && c !== '\\') {
+            continue;
+          }
+
+          break;
+
+        case 'relative path':
+          if (c === EOF || c === '/' || c === '\\' || !stateOverride && (c === '?' || c === '#')) {
+            if (c === '\\') {
+              err('\\ not allowed in relative path.');
+            }
+
+            var tmp;
+
+            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
+              buffer = tmp;
+            }
+
+            if (buffer === '..') {
+              this._path.pop();
+
+              if (c !== '/' && c !== '\\') {
+                this._path.push('');
+              }
+            } else if (buffer === '.' && c !== '/' && c !== '\\') {
+              this._path.push('');
+            } else if (buffer !== '.') {
+              if (this._scheme === 'file' && this._path.length === 0 && buffer.length === 2 && ALPHA.test(buffer[0]) && buffer[1] === '|') {
+                buffer = buffer[0] + ':';
+              }
+
+              this._path.push(buffer);
+            }
+
+            buffer = '';
+
+            if (c === '?') {
+              this._query = '?';
+              state = 'query';
+            } else if (c === '#') {
+              this._fragment = '#';
+              state = 'fragment';
+            }
+          } else if (c !== '\t' && c !== '\n' && c !== '\r') {
+            buffer += percentEscape(c);
+          }
+
+          break;
+
+        case 'query':
+          if (!stateOverride && c === '#') {
+            this._fragment = '#';
+            state = 'fragment';
+          } else if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+            this._query += percentEscapeQuery(c);
+          }
+
+          break;
+
+        case 'fragment':
+          if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+            this._fragment += c;
+          }
+
+          break;
+      }
+
+      cursor++;
+    }
+  }
+
+  function clear() {
+    this._scheme = '';
+    this._schemeData = '';
+    this._username = '';
+    this._password = null;
+    this._host = '';
+    this._port = '';
+    this._path = [];
+    this._query = '';
+    this._fragment = '';
+    this._isInvalid = false;
+    this._isRelative = false;
+  }
+
+  function JURL(url, base) {
+    if (base !== undefined && !(base instanceof JURL)) {
+      base = new JURL(String(base));
+    }
+
+    this._url = url;
+    clear.call(this);
+    var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
+    parse.call(this, input, null, base);
+  }
+
+  JURL.prototype = {
+    toString: function toString() {
+      return this.href;
+    },
+
+    get href() {
+      if (this._isInvalid) {
+        return this._url;
+      }
+
+      var authority = '';
+
+      if (this._username !== '' || this._password !== null) {
+        authority = this._username + (this._password !== null ? ':' + this._password : '') + '@';
+      }
+
+      return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment;
+    },
+
+    set href(value) {
+      clear.call(this);
+      parse.call(this, value);
+    },
+
+    get protocol() {
+      return this._scheme + ':';
+    },
+
+    set protocol(value) {
+      if (this._isInvalid) {
+        return;
+      }
+
+      parse.call(this, value + ':', 'scheme start');
+    },
+
+    get host() {
+      return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
+    },
+
+    set host(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'host');
+    },
+
+    get hostname() {
+      return this._host;
+    },
+
+    set hostname(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'hostname');
+    },
+
+    get port() {
+      return this._port;
+    },
+
+    set port(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'port');
+    },
+
+    get pathname() {
+      return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
+    },
+
+    set pathname(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      this._path = [];
+      parse.call(this, value, 'relative path start');
+    },
+
+    get search() {
+      return this._isInvalid || !this._query || this._query === '?' ? '' : this._query;
+    },
+
+    set search(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      this._query = '?';
+
+      if (value[0] === '?') {
+        value = value.slice(1);
+      }
+
+      parse.call(this, value, 'query');
+    },
+
+    get hash() {
+      return this._isInvalid || !this._fragment || this._fragment === '#' ? '' : this._fragment;
+    },
+
+    set hash(value) {
+      if (this._isInvalid) {
+        return;
+      }
+
+      this._fragment = '#';
+
+      if (value[0] === '#') {
+        value = value.slice(1);
+      }
+
+      parse.call(this, value, 'fragment');
+    },
+
+    get origin() {
+      var host;
+
+      if (this._isInvalid || !this._scheme) {
+        return '';
+      }
+
+      switch (this._scheme) {
+        case 'data':
+        case 'file':
+        case 'javascript':
+        case 'mailto':
+          return 'null';
+
+        case 'blob':
+          try {
+            return new JURL(this._schemeData).origin || 'null';
+          } catch (_) {}
+
+          return 'null';
+      }
+
+      host = this.host;
+
+      if (!host) {
+        return '';
+      }
+
+      return this._scheme + '://' + host;
+    }
+
+  };
+  exports.URL = JURL;
+})();
+
+/***/ }),
+/* 147 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getDocument = getDocument;
+exports.setPDFNetworkStreamFactory = setPDFNetworkStreamFactory;
+exports.build = exports.version = exports.PDFPageProxy = exports.PDFDocumentProxy = exports.PDFWorker = exports.PDFDataRangeTransport = exports.LoopbackPort = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+var _display_utils = __w_pdfjs_require__(151);
+
+var _font_loader = __w_pdfjs_require__(152);
+
+var _api_compatibility = __w_pdfjs_require__(153);
+
+var _canvas = __w_pdfjs_require__(154);
+
+var _global_scope = _interopRequireDefault(__w_pdfjs_require__(3));
+
+var _worker_options = __w_pdfjs_require__(156);
+
+var _message_handler = __w_pdfjs_require__(157);
+
+var _metadata = __w_pdfjs_require__(158);
+
+var _transport_stream = __w_pdfjs_require__(160);
+
+var _webgl = __w_pdfjs_require__(161);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var DEFAULT_RANGE_CHUNK_SIZE = 65536;
+var isWorkerDisabled = false;
+var fallbackWorkerSrc;
+var fakeWorkerFilesLoader = null;
+{
+  var useRequireEnsure = false;
+
+  if (typeof window === 'undefined') {
+    isWorkerDisabled = true;
+
+    if (typeof require.ensure === 'undefined') {
+      require.ensure = require('node-ensure');
+    }
+
+    useRequireEnsure = true;
+  } else if (typeof require !== 'undefined' && typeof require.ensure === 'function') {
+    useRequireEnsure = true;
+  }
+
+  if (typeof requirejs !== 'undefined' && requirejs.toUrl) {
+    fallbackWorkerSrc = requirejs.toUrl('pdfjs-dist/build/pdf.worker.js');
+  }
+
+  var dynamicLoaderSupported = typeof requirejs !== 'undefined' && requirejs.load;
+  fakeWorkerFilesLoader = useRequireEnsure ? function () {
+    return new Promise(function (resolve, reject) {
+      require.ensure([], function () {
+        try {
+          var worker;
+          worker = require('./pdf.worker.js');
+          resolve(worker.WorkerMessageHandler);
+        } catch (ex) {
+          reject(ex);
+        }
+      }, reject, 'pdfjsWorker');
+    });
+  } : dynamicLoaderSupported ? function () {
+    return new Promise(function (resolve, reject) {
+      requirejs(['pdfjs-dist/build/pdf.worker'], function (worker) {
+        try {
+          resolve(worker.WorkerMessageHandler);
+        } catch (ex) {
+          reject(ex);
+        }
+      }, reject);
+    });
+  } : null;
+
+  if (!fallbackWorkerSrc && (typeof document === "undefined" ? "undefined" : _typeof(document)) === 'object' && 'currentScript' in document) {
+    var pdfjsFilePath = document.currentScript && document.currentScript.src;
+
+    if (pdfjsFilePath) {
+      fallbackWorkerSrc = pdfjsFilePath.replace(/(\.(?:min\.)?js)(\?.*)?$/i, '.worker$1$2');
+    }
+  }
+}
+var createPDFNetworkStream;
+
+function setPDFNetworkStreamFactory(pdfNetworkStreamFactory) {
+  createPDFNetworkStream = pdfNetworkStreamFactory;
+}
+
+function getDocument(src) {
+  var task = new PDFDocumentLoadingTask();
+  var source;
+
+  if (typeof src === 'string') {
+    source = {
+      url: src
+    };
+  } else if ((0, _util.isArrayBuffer)(src)) {
+    source = {
+      data: src
+    };
+  } else if (src instanceof PDFDataRangeTransport) {
+    source = {
+      range: src
+    };
+  } else {
+    if (_typeof(src) !== 'object') {
+      throw new Error('Invalid parameter in getDocument, ' + 'need either Uint8Array, string or a parameter object');
+    }
+
+    if (!src.url && !src.data && !src.range) {
+      throw new Error('Invalid parameter object: need either .data, .range or .url');
+    }
+
+    source = src;
+  }
+
+  var params = Object.create(null);
+  var rangeTransport = null,
+      worker = null;
+
+  for (var key in source) {
+    if (key === 'url' && typeof window !== 'undefined') {
+      params[key] = new _util.URL(source[key], window.location).href;
+      continue;
+    } else if (key === 'range') {
+      rangeTransport = source[key];
+      continue;
+    } else if (key === 'worker') {
+      worker = source[key];
+      continue;
+    } else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
+      var pdfBytes = source[key];
+
+      if (typeof pdfBytes === 'string') {
+        params[key] = (0, _util.stringToBytes)(pdfBytes);
+      } else if (_typeof(pdfBytes) === 'object' && pdfBytes !== null && !isNaN(pdfBytes.length)) {
+        params[key] = new Uint8Array(pdfBytes);
+      } else if ((0, _util.isArrayBuffer)(pdfBytes)) {
+        params[key] = new Uint8Array(pdfBytes);
+      } else {
+        throw new Error('Invalid PDF binary data: either typed array, ' + 'string or array-like object is expected in the ' + 'data property.');
+      }
+
+      continue;
+    }
+
+    params[key] = source[key];
+  }
+
+  params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
+  params.CMapReaderFactory = params.CMapReaderFactory || _display_utils.DOMCMapReaderFactory;
+  params.ignoreErrors = params.stopAtErrors !== true;
+  params.pdfBug = params.pdfBug === true;
+  var NativeImageDecoderValues = Object.values(_util.NativeImageDecoding);
+
+  if (params.nativeImageDecoderSupport === undefined || !NativeImageDecoderValues.includes(params.nativeImageDecoderSupport)) {
+    params.nativeImageDecoderSupport = _api_compatibility.apiCompatibilityParams.nativeImageDecoderSupport || _util.NativeImageDecoding.DECODE;
+  }
+
+  if (!Number.isInteger(params.maxImageSize)) {
+    params.maxImageSize = -1;
+  }
+
+  if (typeof params.isEvalSupported !== 'boolean') {
+    params.isEvalSupported = true;
+  }
+
+  if (typeof params.disableFontFace !== 'boolean') {
+    params.disableFontFace = _api_compatibility.apiCompatibilityParams.disableFontFace || false;
+  }
+
+  if (typeof params.disableRange !== 'boolean') {
+    params.disableRange = false;
+  }
+
+  if (typeof params.disableStream !== 'boolean') {
+    params.disableStream = false;
+  }
+
+  if (typeof params.disableAutoFetch !== 'boolean') {
+    params.disableAutoFetch = false;
+  }
+
+  if (typeof params.disableCreateObjectURL !== 'boolean') {
+    params.disableCreateObjectURL = _api_compatibility.apiCompatibilityParams.disableCreateObjectURL || false;
+  }
+
+  (0, _util.setVerbosityLevel)(params.verbosity);
+
+  if (!worker) {
+    var workerParams = {
+      postMessageTransfers: params.postMessageTransfers,
+      verbosity: params.verbosity,
+      port: _worker_options.GlobalWorkerOptions.workerPort
+    };
+    worker = workerParams.port ? PDFWorker.fromPort(workerParams) : new PDFWorker(workerParams);
+    task._worker = worker;
+  }
+
+  var docId = task.docId;
+  worker.promise.then(function () {
+    if (task.destroyed) {
+      throw new Error('Loading aborted');
+    }
+
+    return _fetchDocument(worker, params, rangeTransport, docId).then(function (workerId) {
+      if (task.destroyed) {
+        throw new Error('Loading aborted');
+      }
+
+      var networkStream;
+
+      if (rangeTransport) {
+        networkStream = new _transport_stream.PDFDataTransportStream({
+          length: params.length,
+          initialData: params.initialData,
+          progressiveDone: params.progressiveDone,
+          disableRange: params.disableRange,
+          disableStream: params.disableStream
+        }, rangeTransport);
+      } else if (!params.data) {
+        networkStream = createPDFNetworkStream({
+          url: params.url,
+          length: params.length,
+          httpHeaders: params.httpHeaders,
+          withCredentials: params.withCredentials,
+          rangeChunkSize: params.rangeChunkSize,
+          disableRange: params.disableRange,
+          disableStream: params.disableStream
+        });
+      }
+
+      var messageHandler = new _message_handler.MessageHandler(docId, workerId, worker.port);
+      messageHandler.postMessageTransfers = worker.postMessageTransfers;
+      var transport = new WorkerTransport(messageHandler, task, networkStream, params);
+      task._transport = transport;
+      messageHandler.send('Ready', null);
+    });
+  })["catch"](task._capability.reject);
+  return task;
+}
+
+function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
+  if (worker.destroyed) {
+    return Promise.reject(new Error('Worker was destroyed'));
+  }
+
+  if (pdfDataRangeTransport) {
+    source.length = pdfDataRangeTransport.length;
+    source.initialData = pdfDataRangeTransport.initialData;
+    source.progressiveDone = pdfDataRangeTransport.progressiveDone;
+  }
+
+  return worker.messageHandler.sendWithPromise('GetDocRequest', {
+    docId: docId,
+    apiVersion: '2.2.228',
+    source: {
+      data: source.data,
+      url: source.url,
+      password: source.password,
+      disableAutoFetch: source.disableAutoFetch,
+      rangeChunkSize: source.rangeChunkSize,
+      length: source.length
+    },
+    maxImageSize: source.maxImageSize,
+    disableFontFace: source.disableFontFace,
+    disableCreateObjectURL: source.disableCreateObjectURL,
+    postMessageTransfers: worker.postMessageTransfers,
+    docBaseUrl: source.docBaseUrl,
+    nativeImageDecoderSupport: source.nativeImageDecoderSupport,
+    ignoreErrors: source.ignoreErrors,
+    isEvalSupported: source.isEvalSupported
+  }).then(function (workerId) {
+    if (worker.destroyed) {
+      throw new Error('Worker was destroyed');
+    }
+
+    return workerId;
+  });
+}
+
+var PDFDocumentLoadingTask = function PDFDocumentLoadingTaskClosure() {
+  var nextDocumentId = 0;
+
+  var PDFDocumentLoadingTask =
+  /*#__PURE__*/
+  function () {
+    function PDFDocumentLoadingTask() {
+      _classCallCheck(this, PDFDocumentLoadingTask);
+
+      this._capability = (0, _util.createPromiseCapability)();
+      this._transport = null;
+      this._worker = null;
+      this.docId = 'd' + nextDocumentId++;
+      this.destroyed = false;
+      this.onPassword = null;
+      this.onProgress = null;
+      this.onUnsupportedFeature = null;
+    }
+
+    _createClass(PDFDocumentLoadingTask, [{
+      key: "destroy",
+      value: function destroy() {
+        var _this = this;
+
+        this.destroyed = true;
+        var transportDestroyed = !this._transport ? Promise.resolve() : this._transport.destroy();
+        return transportDestroyed.then(function () {
+          _this._transport = null;
+
+          if (_this._worker) {
+            _this._worker.destroy();
+
+            _this._worker = null;
+          }
+        });
+      }
+    }, {
+      key: "then",
+      value: function then(onFulfilled, onRejected) {
+        (0, _display_utils.deprecated)('PDFDocumentLoadingTask.then method, ' + 'use the `promise` getter instead.');
+        return this.promise.then.apply(this.promise, arguments);
+      }
+    }, {
+      key: "promise",
+      get: function get() {
+        return this._capability.promise;
+      }
+    }]);
+
+    return PDFDocumentLoadingTask;
+  }();
+
+  return PDFDocumentLoadingTask;
+}();
+
+var PDFDataRangeTransport =
+/*#__PURE__*/
+function () {
+  function PDFDataRangeTransport(length, initialData) {
+    var progressiveDone = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+    _classCallCheck(this, PDFDataRangeTransport);
+
+    this.length = length;
+    this.initialData = initialData;
+    this.progressiveDone = progressiveDone;
+    this._rangeListeners = [];
+    this._progressListeners = [];
+    this._progressiveReadListeners = [];
+    this._progressiveDoneListeners = [];
+    this._readyCapability = (0, _util.createPromiseCapability)();
+  }
+
+  _createClass(PDFDataRangeTransport, [{
+    key: "addRangeListener",
+    value: function addRangeListener(listener) {
+      this._rangeListeners.push(listener);
+    }
+  }, {
+    key: "addProgressListener",
+    value: function addProgressListener(listener) {
+      this._progressListeners.push(listener);
+    }
+  }, {
+    key: "addProgressiveReadListener",
+    value: function addProgressiveReadListener(listener) {
+      this._progressiveReadListeners.push(listener);
+    }
+  }, {
+    key: "addProgressiveDoneListener",
+    value: function addProgressiveDoneListener(listener) {
+      this._progressiveDoneListeners.push(listener);
+    }
+  }, {
+    key: "onDataRange",
+    value: function onDataRange(begin, chunk) {
+      var _iteratorNormalCompletion = true;
+      var _didIteratorError = false;
+      var _iteratorError = undefined;
+
+      try {
+        for (var _iterator = this._rangeListeners[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+          var listener = _step.value;
+          listener(begin, chunk);
+        }
+      } catch (err) {
+        _didIteratorError = true;
+        _iteratorError = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+            _iterator["return"]();
+          }
+        } finally {
+          if (_didIteratorError) {
+            throw _iteratorError;
+          }
+        }
+      }
+    }
+  }, {
+    key: "onDataProgress",
+    value: function onDataProgress(loaded, total) {
+      var _this2 = this;
+
+      this._readyCapability.promise.then(function () {
+        var _iteratorNormalCompletion2 = true;
+        var _didIteratorError2 = false;
+        var _iteratorError2 = undefined;
+
+        try {
+          for (var _iterator2 = _this2._progressListeners[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+            var listener = _step2.value;
+            listener(loaded, total);
+          }
+        } catch (err) {
+          _didIteratorError2 = true;
+          _iteratorError2 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
+              _iterator2["return"]();
+            }
+          } finally {
+            if (_didIteratorError2) {
+              throw _iteratorError2;
+            }
+          }
+        }
+      });
+    }
+  }, {
+    key: "onDataProgressiveRead",
+    value: function onDataProgressiveRead(chunk) {
+      var _this3 = this;
+
+      this._readyCapability.promise.then(function () {
+        var _iteratorNormalCompletion3 = true;
+        var _didIteratorError3 = false;
+        var _iteratorError3 = undefined;
+
+        try {
+          for (var _iterator3 = _this3._progressiveReadListeners[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+            var listener = _step3.value;
+            listener(chunk);
+          }
+        } catch (err) {
+          _didIteratorError3 = true;
+          _iteratorError3 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
+              _iterator3["return"]();
+            }
+          } finally {
+            if (_didIteratorError3) {
+              throw _iteratorError3;
+            }
+          }
+        }
+      });
+    }
+  }, {
+    key: "onDataProgressiveDone",
+    value: function onDataProgressiveDone() {
+      var _this4 = this;
+
+      this._readyCapability.promise.then(function () {
+        var _iteratorNormalCompletion4 = true;
+        var _didIteratorError4 = false;
+        var _iteratorError4 = undefined;
+
+        try {
+          for (var _iterator4 = _this4._progressiveDoneListeners[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+            var listener = _step4.value;
+            listener();
+          }
+        } catch (err) {
+          _didIteratorError4 = true;
+          _iteratorError4 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
+              _iterator4["return"]();
+            }
+          } finally {
+            if (_didIteratorError4) {
+              throw _iteratorError4;
+            }
+          }
+        }
+      });
+    }
+  }, {
+    key: "transportReady",
+    value: function transportReady() {
+      this._readyCapability.resolve();
+    }
+  }, {
+    key: "requestDataRange",
+    value: function requestDataRange(begin, end) {
+      (0, _util.unreachable)('Abstract method PDFDataRangeTransport.requestDataRange');
+    }
+  }, {
+    key: "abort",
+    value: function abort() {}
+  }]);
+
+  return PDFDataRangeTransport;
+}();
+
+exports.PDFDataRangeTransport = PDFDataRangeTransport;
+
+var PDFDocumentProxy =
+/*#__PURE__*/
+function () {
+  function PDFDocumentProxy(pdfInfo, transport) {
+    _classCallCheck(this, PDFDocumentProxy);
+
+    this._pdfInfo = pdfInfo;
+    this._transport = transport;
+  }
+
+  _createClass(PDFDocumentProxy, [{
+    key: "getPage",
+    value: function getPage(pageNumber) {
+      return this._transport.getPage(pageNumber);
+    }
+  }, {
+    key: "getPageIndex",
+    value: function getPageIndex(ref) {
+      return this._transport.getPageIndex(ref);
+    }
+  }, {
+    key: "getDestinations",
+    value: function getDestinations() {
+      return this._transport.getDestinations();
+    }
+  }, {
+    key: "getDestination",
+    value: function getDestination(id) {
+      return this._transport.getDestination(id);
+    }
+  }, {
+    key: "getPageLabels",
+    value: function getPageLabels() {
+      return this._transport.getPageLabels();
+    }
+  }, {
+    key: "getPageLayout",
+    value: function getPageLayout() {
+      return this._transport.getPageLayout();
+    }
+  }, {
+    key: "getPageMode",
+    value: function getPageMode() {
+      return this._transport.getPageMode();
+    }
+  }, {
+    key: "getViewerPreferences",
+    value: function getViewerPreferences() {
+      return this._transport.getViewerPreferences();
+    }
+  }, {
+    key: "getOpenActionDestination",
+    value: function getOpenActionDestination() {
+      return this._transport.getOpenActionDestination();
+    }
+  }, {
+    key: "getAttachments",
+    value: function getAttachments() {
+      return this._transport.getAttachments();
+    }
+  }, {
+    key: "getJavaScript",
+    value: function getJavaScript() {
+      return this._transport.getJavaScript();
+    }
+  }, {
+    key: "getOutline",
+    value: function getOutline() {
+      return this._transport.getOutline();
+    }
+  }, {
+    key: "getPermissions",
+    value: function getPermissions() {
+      return this._transport.getPermissions();
+    }
+  }, {
+    key: "getMetadata",
+    value: function getMetadata() {
+      return this._transport.getMetadata();
+    }
+  }, {
+    key: "getData",
+    value: function getData() {
+      return this._transport.getData();
+    }
+  }, {
+    key: "getDownloadInfo",
+    value: function getDownloadInfo() {
+      return this._transport.downloadInfoCapability.promise;
+    }
+  }, {
+    key: "getStats",
+    value: function getStats() {
+      return this._transport.getStats();
+    }
+  }, {
+    key: "cleanup",
+    value: function cleanup() {
+      this._transport.startCleanup();
+    }
+  }, {
+    key: "destroy",
+    value: function destroy() {
+      return this.loadingTask.destroy();
+    }
+  }, {
+    key: "numPages",
+    get: function get() {
+      return this._pdfInfo.numPages;
+    }
+  }, {
+    key: "fingerprint",
+    get: function get() {
+      return this._pdfInfo.fingerprint;
+    }
+  }, {
+    key: "loadingParams",
+    get: function get() {
+      return this._transport.loadingParams;
+    }
+  }, {
+    key: "loadingTask",
+    get: function get() {
+      return this._transport.loadingTask;
+    }
+  }]);
+
+  return PDFDocumentProxy;
+}();
+
+exports.PDFDocumentProxy = PDFDocumentProxy;
+
+var PDFPageProxy =
+/*#__PURE__*/
+function () {
+  function PDFPageProxy(pageIndex, pageInfo, transport) {
+    var pdfBug = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+
+    _classCallCheck(this, PDFPageProxy);
+
+    this.pageIndex = pageIndex;
+    this._pageInfo = pageInfo;
+    this._transport = transport;
+    this._stats = pdfBug ? new _display_utils.StatTimer() : _display_utils.DummyStatTimer;
+    this._pdfBug = pdfBug;
+    this.commonObjs = transport.commonObjs;
+    this.objs = new PDFObjects();
+    this.cleanupAfterRender = false;
+    this.pendingCleanup = false;
+    this.intentStates = Object.create(null);
+    this.destroyed = false;
+  }
+
+  _createClass(PDFPageProxy, [{
+    key: "getViewport",
+    value: function getViewport() {
+      var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          scale = _ref.scale,
+          _ref$rotation = _ref.rotation,
+          rotation = _ref$rotation === void 0 ? this.rotate : _ref$rotation,
+          _ref$dontFlip = _ref.dontFlip,
+          dontFlip = _ref$dontFlip === void 0 ? false : _ref$dontFlip;
+
+      if (arguments.length > 1 || typeof arguments[0] === 'number') {
+        (0, _display_utils.deprecated)('getViewport is called with obsolete arguments.');
+        scale = arguments[0];
+        rotation = typeof arguments[1] === 'number' ? arguments[1] : this.rotate;
+        dontFlip = typeof arguments[2] === 'boolean' ? arguments[2] : false;
+      }
+
+      return new _display_utils.PageViewport({
+        viewBox: this.view,
+        scale: scale,
+        rotation: rotation,
+        dontFlip: dontFlip
+      });
+    }
+  }, {
+    key: "getAnnotations",
+    value: function getAnnotations() {
+      var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          _ref2$intent = _ref2.intent,
+          intent = _ref2$intent === void 0 ? null : _ref2$intent;
+
+      if (!this.annotationsPromise || this.annotationsIntent !== intent) {
+        this.annotationsPromise = this._transport.getAnnotations(this.pageIndex, intent);
+        this.annotationsIntent = intent;
+      }
+
+      return this.annotationsPromise;
+    }
+  }, {
+    key: "render",
+    value: function render(_ref3) {
+      var _this5 = this;
+
+      var canvasContext = _ref3.canvasContext,
+          viewport = _ref3.viewport,
+          _ref3$intent = _ref3.intent,
+          intent = _ref3$intent === void 0 ? 'display' : _ref3$intent,
+          _ref3$enableWebGL = _ref3.enableWebGL,
+          enableWebGL = _ref3$enableWebGL === void 0 ? false : _ref3$enableWebGL,
+          _ref3$renderInteracti = _ref3.renderInteractiveForms,
+          renderInteractiveForms = _ref3$renderInteracti === void 0 ? false : _ref3$renderInteracti,
+          _ref3$transform = _ref3.transform,
+          transform = _ref3$transform === void 0 ? null : _ref3$transform,
+          _ref3$imageLayer = _ref3.imageLayer,
+          imageLayer = _ref3$imageLayer === void 0 ? null : _ref3$imageLayer,
+          _ref3$canvasFactory = _ref3.canvasFactory,
+          canvasFactory = _ref3$canvasFactory === void 0 ? null : _ref3$canvasFactory,
+          _ref3$background = _ref3.background,
+          background = _ref3$background === void 0 ? null : _ref3$background;
+      var stats = this._stats;
+      stats.time('Overall');
+      this.pendingCleanup = false;
+      var renderingIntent = intent === 'print' ? 'print' : 'display';
+      var canvasFactoryInstance = canvasFactory || new _display_utils.DOMCanvasFactory();
+      var webGLContext = new _webgl.WebGLContext({
+        enable: enableWebGL
+      });
+
+      if (!this.intentStates[renderingIntent]) {
+        this.intentStates[renderingIntent] = Object.create(null);
+      }
+
+      var intentState = this.intentStates[renderingIntent];
+
+      if (!intentState.displayReadyCapability) {
+        intentState.receivingOperatorList = true;
+        intentState.displayReadyCapability = (0, _util.createPromiseCapability)();
+        intentState.operatorList = {
+          fnArray: [],
+          argsArray: [],
+          lastChunk: false
+        };
+        stats.time('Page Request');
+
+        this._transport.messageHandler.send('RenderPageRequest', {
+          pageIndex: this.pageNumber - 1,
+          intent: renderingIntent,
+          renderInteractiveForms: renderInteractiveForms === true
+        });
+      }
+
+      var complete = function complete(error) {
+        var i = intentState.renderTasks.indexOf(internalRenderTask);
+
+        if (i >= 0) {
+          intentState.renderTasks.splice(i, 1);
+        }
+
+        if (_this5.cleanupAfterRender || renderingIntent === 'print') {
+          _this5.pendingCleanup = true;
+        }
+
+        _this5._tryCleanup();
+
+        if (error) {
+          internalRenderTask.capability.reject(error);
+        } else {
+          internalRenderTask.capability.resolve();
+        }
+
+        stats.timeEnd('Rendering');
+        stats.timeEnd('Overall');
+      };
+
+      var internalRenderTask = new InternalRenderTask({
+        callback: complete,
+        params: {
+          canvasContext: canvasContext,
+          viewport: viewport,
+          transform: transform,
+          imageLayer: imageLayer,
+          background: background
+        },
+        objs: this.objs,
+        commonObjs: this.commonObjs,
+        operatorList: intentState.operatorList,
+        pageNumber: this.pageNumber,
+        canvasFactory: canvasFactoryInstance,
+        webGLContext: webGLContext,
+        useRequestAnimationFrame: renderingIntent !== 'print',
+        pdfBug: this._pdfBug
+      });
+
+      if (!intentState.renderTasks) {
+        intentState.renderTasks = [];
+      }
+
+      intentState.renderTasks.push(internalRenderTask);
+      var renderTask = internalRenderTask.task;
+      intentState.displayReadyCapability.promise.then(function (transparency) {
+        if (_this5.pendingCleanup) {
+          complete();
+          return;
+        }
+
+        stats.time('Rendering');
+        internalRenderTask.initializeGraphics(transparency);
+        internalRenderTask.operatorListChanged();
+      })["catch"](complete);
+      return renderTask;
+    }
+  }, {
+    key: "getOperatorList",
+    value: function getOperatorList() {
+      function operatorListChanged() {
+        if (intentState.operatorList.lastChunk) {
+          intentState.opListReadCapability.resolve(intentState.operatorList);
+          var i = intentState.renderTasks.indexOf(opListTask);
+
+          if (i >= 0) {
+            intentState.renderTasks.splice(i, 1);
+          }
+        }
+      }
+
+      var renderingIntent = 'oplist';
+
+      if (!this.intentStates[renderingIntent]) {
+        this.intentStates[renderingIntent] = Object.create(null);
+      }
+
+      var intentState = this.intentStates[renderingIntent];
+      var opListTask;
+
+      if (!intentState.opListReadCapability) {
+        opListTask = {};
+        opListTask.operatorListChanged = operatorListChanged;
+        intentState.receivingOperatorList = true;
+        intentState.opListReadCapability = (0, _util.createPromiseCapability)();
+        intentState.renderTasks = [];
+        intentState.renderTasks.push(opListTask);
+        intentState.operatorList = {
+          fnArray: [],
+          argsArray: [],
+          lastChunk: false
+        };
+
+        this._stats.time('Page Request');
+
+        this._transport.messageHandler.send('RenderPageRequest', {
+          pageIndex: this.pageIndex,
+          intent: renderingIntent
+        });
+      }
+
+      return intentState.opListReadCapability.promise;
+    }
+  }, {
+    key: "streamTextContent",
+    value: function streamTextContent() {
+      var _ref4 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          _ref4$normalizeWhites = _ref4.normalizeWhitespace,
+          normalizeWhitespace = _ref4$normalizeWhites === void 0 ? false : _ref4$normalizeWhites,
+          _ref4$disableCombineT = _ref4.disableCombineTextItems,
+          disableCombineTextItems = _ref4$disableCombineT === void 0 ? false : _ref4$disableCombineT;
+
+      var TEXT_CONTENT_CHUNK_SIZE = 100;
+      return this._transport.messageHandler.sendWithStream('GetTextContent', {
+        pageIndex: this.pageNumber - 1,
+        normalizeWhitespace: normalizeWhitespace === true,
+        combineTextItems: disableCombineTextItems !== true
+      }, {
+        highWaterMark: TEXT_CONTENT_CHUNK_SIZE,
+        size: function size(textContent) {
+          return textContent.items.length;
+        }
+      });
+    }
+  }, {
+    key: "getTextContent",
+    value: function getTextContent() {
+      var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+      var readableStream = this.streamTextContent(params);
+      return new Promise(function (resolve, reject) {
+        function pump() {
+          reader.read().then(function (_ref5) {
+            var _textContent$items;
+
+            var value = _ref5.value,
+                done = _ref5.done;
+
+            if (done) {
+              resolve(textContent);
+              return;
+            }
+
+            Object.assign(textContent.styles, value.styles);
+
+            (_textContent$items = textContent.items).push.apply(_textContent$items, _toConsumableArray(value.items));
+
+            pump();
+          }, reject);
+        }
+
+        var reader = readableStream.getReader();
+        var textContent = {
+          items: [],
+          styles: Object.create(null)
+        };
+        pump();
+      });
+    }
+  }, {
+    key: "_destroy",
+    value: function _destroy() {
+      this.destroyed = true;
+      this._transport.pageCache[this.pageIndex] = null;
+      var waitOn = [];
+      Object.keys(this.intentStates).forEach(function (intent) {
+        if (intent === 'oplist') {
+          return;
+        }
+
+        var intentState = this.intentStates[intent];
+        intentState.renderTasks.forEach(function (renderTask) {
+          var renderCompleted = renderTask.capability.promise["catch"](function () {});
+          waitOn.push(renderCompleted);
+          renderTask.cancel();
+        });
+      }, this);
+      this.objs.clear();
+      this.annotationsPromise = null;
+      this.pendingCleanup = false;
+      return Promise.all(waitOn);
+    }
+  }, {
+    key: "cleanup",
+    value: function cleanup() {
+      var resetStats = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+      this.pendingCleanup = true;
+
+      this._tryCleanup(resetStats);
+    }
+  }, {
+    key: "_tryCleanup",
+    value: function _tryCleanup() {
+      var resetStats = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+      if (!this.pendingCleanup || Object.keys(this.intentStates).some(function (intent) {
+        var intentState = this.intentStates[intent];
+        return intentState.renderTasks.length !== 0 || intentState.receivingOperatorList;
+      }, this)) {
+        return;
+      }
+
+      Object.keys(this.intentStates).forEach(function (intent) {
+        delete this.intentStates[intent];
+      }, this);
+      this.objs.clear();
+      this.annotationsPromise = null;
+
+      if (resetStats && this._stats instanceof _display_utils.StatTimer) {
+        this._stats = new _display_utils.StatTimer();
+      }
+
+      this.pendingCleanup = false;
+    }
+  }, {
+    key: "_startRenderPage",
+    value: function _startRenderPage(transparency, intent) {
+      var intentState = this.intentStates[intent];
+
+      if (intentState.displayReadyCapability) {
+        intentState.displayReadyCapability.resolve(transparency);
+      }
+    }
+  }, {
+    key: "_renderPageChunk",
+    value: function _renderPageChunk(operatorListChunk, intent) {
+      var intentState = this.intentStates[intent];
+
+      for (var i = 0, ii = operatorListChunk.length; i < ii; i++) {
+        intentState.operatorList.fnArray.push(operatorListChunk.fnArray[i]);
+        intentState.operatorList.argsArray.push(operatorListChunk.argsArray[i]);
+      }
+
+      intentState.operatorList.lastChunk = operatorListChunk.lastChunk;
+
+      for (var _i = 0; _i < intentState.renderTasks.length; _i++) {
+        intentState.renderTasks[_i].operatorListChanged();
+      }
+
+      if (operatorListChunk.lastChunk) {
+        intentState.receivingOperatorList = false;
+
+        this._tryCleanup();
+      }
+    }
+  }, {
+    key: "pageNumber",
+    get: function get() {
+      return this.pageIndex + 1;
+    }
+  }, {
+    key: "rotate",
+    get: function get() {
+      return this._pageInfo.rotate;
+    }
+  }, {
+    key: "ref",
+    get: function get() {
+      return this._pageInfo.ref;
+    }
+  }, {
+    key: "userUnit",
+    get: function get() {
+      return this._pageInfo.userUnit;
+    }
+  }, {
+    key: "view",
+    get: function get() {
+      return this._pageInfo.view;
+    }
+  }, {
+    key: "stats",
+    get: function get() {
+      return this._stats instanceof _display_utils.StatTimer ? this._stats : null;
+    }
+  }]);
+
+  return PDFPageProxy;
+}();
+
+exports.PDFPageProxy = PDFPageProxy;
+
+var LoopbackPort =
+/*#__PURE__*/
+function () {
+  function LoopbackPort() {
+    var defer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
+
+    _classCallCheck(this, LoopbackPort);
+
+    this._listeners = [];
+    this._defer = defer;
+    this._deferred = Promise.resolve(undefined);
+  }
+
+  _createClass(LoopbackPort, [{
+    key: "postMessage",
+    value: function postMessage(obj, transfers) {
+      var _this6 = this;
+
+      function cloneValue(value) {
+        if (_typeof(value) !== 'object' || value === null) {
+          return value;
+        }
+
+        if (cloned.has(value)) {
+          return cloned.get(value);
+        }
+
+        var buffer, result;
+
+        if ((buffer = value.buffer) && (0, _util.isArrayBuffer)(buffer)) {
+          var transferable = transfers && transfers.includes(buffer);
+
+          if (value === buffer) {
+            result = value;
+          } else if (transferable) {
+            result = new value.constructor(buffer, value.byteOffset, value.byteLength);
+          } else {
+            result = new value.constructor(value);
+          }
+
+          cloned.set(value, result);
+          return result;
+        }
+
+        result = Array.isArray(value) ? [] : {};
+        cloned.set(value, result);
+
+        for (var i in value) {
+          var desc = void 0,
+              p = value;
+
+          while (!(desc = Object.getOwnPropertyDescriptor(p, i))) {
+            p = Object.getPrototypeOf(p);
+          }
+
+          if (typeof desc.value === 'undefined' || typeof desc.value === 'function') {
+            continue;
+          }
+
+          result[i] = cloneValue(desc.value);
+        }
+
+        return result;
+      }
+
+      if (!this._defer) {
+        this._listeners.forEach(function (listener) {
+          listener.call(this, {
+            data: obj
+          });
+        }, this);
+
+        return;
+      }
+
+      var cloned = new WeakMap();
+      var e = {
+        data: cloneValue(obj)
+      };
+
+      this._deferred.then(function () {
+        _this6._listeners.forEach(function (listener) {
+          listener.call(this, e);
+        }, _this6);
+      });
+    }
+  }, {
+    key: "addEventListener",
+    value: function addEventListener(name, listener) {
+      this._listeners.push(listener);
+    }
+  }, {
+    key: "removeEventListener",
+    value: function removeEventListener(name, listener) {
+      var i = this._listeners.indexOf(listener);
+
+      this._listeners.splice(i, 1);
+    }
+  }, {
+    key: "terminate",
+    value: function terminate() {
+      this._listeners.length = 0;
+    }
+  }]);
+
+  return LoopbackPort;
+}();
+
+exports.LoopbackPort = LoopbackPort;
+
+var PDFWorker = function PDFWorkerClosure() {
+  var pdfWorkerPorts = new WeakMap();
+  var nextFakeWorkerId = 0;
+  var fakeWorkerFilesLoadedCapability;
+
+  function _getWorkerSrc() {
+    if (_worker_options.GlobalWorkerOptions.workerSrc) {
+      return _worker_options.GlobalWorkerOptions.workerSrc;
+    }
+
+    if (typeof fallbackWorkerSrc !== 'undefined') {
+      return fallbackWorkerSrc;
+    }
+
+    throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
+  }
+
+  function getMainThreadWorkerMessageHandler() {
+    try {
+      if (typeof window !== 'undefined') {
+        return window.pdfjsWorker && window.pdfjsWorker.WorkerMessageHandler;
+      }
+    } catch (ex) {}
+
+    return null;
+  }
+
+  function setupFakeWorkerGlobal() {
+    if (fakeWorkerFilesLoadedCapability) {
+      return fakeWorkerFilesLoadedCapability.promise;
+    }
+
+    fakeWorkerFilesLoadedCapability = (0, _util.createPromiseCapability)();
+    var mainWorkerMessageHandler = getMainThreadWorkerMessageHandler();
+
+    if (mainWorkerMessageHandler) {
+      fakeWorkerFilesLoadedCapability.resolve(mainWorkerMessageHandler);
+      return fakeWorkerFilesLoadedCapability.promise;
+    }
+
+    var loader = fakeWorkerFilesLoader || function () {
+      return (0, _display_utils.loadScript)(_getWorkerSrc()).then(function () {
+        return window.pdfjsWorker.WorkerMessageHandler;
+      });
+    };
+
+    loader().then(fakeWorkerFilesLoadedCapability.resolve, fakeWorkerFilesLoadedCapability.reject);
+    return fakeWorkerFilesLoadedCapability.promise;
+  }
+
+  function createCDNWrapper(url) {
+    var wrapper = 'importScripts(\'' + url + '\');';
+    return _util.URL.createObjectURL(new Blob([wrapper]));
+  }
+
+  var PDFWorker =
+  /*#__PURE__*/
+  function () {
+    function PDFWorker() {
+      var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          _ref6$name = _ref6.name,
+          name = _ref6$name === void 0 ? null : _ref6$name,
+          _ref6$port = _ref6.port,
+          port = _ref6$port === void 0 ? null : _ref6$port,
+          _ref6$postMessageTran = _ref6.postMessageTransfers,
+          postMessageTransfers = _ref6$postMessageTran === void 0 ? true : _ref6$postMessageTran,
+          _ref6$verbosity = _ref6.verbosity,
+          verbosity = _ref6$verbosity === void 0 ? (0, _util.getVerbosityLevel)() : _ref6$verbosity;
+
+      _classCallCheck(this, PDFWorker);
+
+      if (port && pdfWorkerPorts.has(port)) {
+        throw new Error('Cannot use more than one PDFWorker per port');
+      }
+
+      this.name = name;
+      this.destroyed = false;
+      this.postMessageTransfers = postMessageTransfers !== false;
+      this.verbosity = verbosity;
+      this._readyCapability = (0, _util.createPromiseCapability)();
+      this._port = null;
+      this._webWorker = null;
+      this._messageHandler = null;
+
+      if (port) {
+        pdfWorkerPorts.set(port, this);
+
+        this._initializeFromPort(port);
+
+        return;
+      }
+
+      this._initialize();
+    }
+
+    _createClass(PDFWorker, [{
+      key: "_initializeFromPort",
+      value: function _initializeFromPort(port) {
+        this._port = port;
+        this._messageHandler = new _message_handler.MessageHandler('main', 'worker', port);
+
+        this._messageHandler.on('ready', function () {});
+
+        this._readyCapability.resolve();
+      }
+    }, {
+      key: "_initialize",
+      value: function _initialize() {
+        var _this7 = this;
+
+        if (typeof Worker !== 'undefined' && !isWorkerDisabled && !getMainThreadWorkerMessageHandler()) {
+          var workerSrc = _getWorkerSrc();
+
+          try {
+            if (!(0, _util.isSameOrigin)(window.location.href, workerSrc)) {
+              workerSrc = createCDNWrapper(new _util.URL(workerSrc, window.location).href);
+            }
+
+            var worker = new Worker(workerSrc);
+            var messageHandler = new _message_handler.MessageHandler('main', 'worker', worker);
+
+            var terminateEarly = function terminateEarly() {
+              worker.removeEventListener('error', onWorkerError);
+              messageHandler.destroy();
+              worker.terminate();
+
+              if (_this7.destroyed) {
+                _this7._readyCapability.reject(new Error('Worker was destroyed'));
+              } else {
+                _this7._setupFakeWorker();
+              }
+            };
+
+            var onWorkerError = function onWorkerError() {
+              if (!_this7._webWorker) {
+                terminateEarly();
+              }
+            };
+
+            worker.addEventListener('error', onWorkerError);
+            messageHandler.on('test', function (data) {
+              worker.removeEventListener('error', onWorkerError);
+
+              if (_this7.destroyed) {
+                terminateEarly();
+                return;
+              }
+
+              if (data && data.supportTypedArray) {
+                _this7._messageHandler = messageHandler;
+                _this7._port = worker;
+                _this7._webWorker = worker;
+
+                if (!data.supportTransfers) {
+                  _this7.postMessageTransfers = false;
+                }
+
+                _this7._readyCapability.resolve();
+
+                messageHandler.send('configure', {
+                  verbosity: _this7.verbosity
+                });
+              } else {
+                _this7._setupFakeWorker();
+
+                messageHandler.destroy();
+                worker.terminate();
+              }
+            });
+            messageHandler.on('ready', function (data) {
+              worker.removeEventListener('error', onWorkerError);
+
+              if (_this7.destroyed) {
+                terminateEarly();
+                return;
+              }
+
+              try {
+                sendTest();
+              } catch (e) {
+                _this7._setupFakeWorker();
+              }
+            });
+
+            var sendTest = function sendTest() {
+              var testObj = new Uint8Array([_this7.postMessageTransfers ? 255 : 0]);
+
+              try {
+                messageHandler.send('test', testObj, [testObj.buffer]);
+              } catch (ex) {
+                (0, _util.info)('Cannot use postMessage transfers');
+                testObj[0] = 0;
+                messageHandler.send('test', testObj);
+              }
+            };
+
+            sendTest();
+            return;
+          } catch (e) {
+            (0, _util.info)('The worker has been disabled.');
+          }
+        }
+
+        this._setupFakeWorker();
+      }
+    }, {
+      key: "_setupFakeWorker",
+      value: function _setupFakeWorker() {
+        var _this8 = this;
+
+        if (!isWorkerDisabled) {
+          (0, _util.warn)('Setting up fake worker.');
+          isWorkerDisabled = true;
+        }
+
+        setupFakeWorkerGlobal().then(function (WorkerMessageHandler) {
+          if (_this8.destroyed) {
+            _this8._readyCapability.reject(new Error('Worker was destroyed'));
+
+            return;
+          }
+
+          var port = new LoopbackPort();
+          _this8._port = port;
+          var id = 'fake' + nextFakeWorkerId++;
+          var workerHandler = new _message_handler.MessageHandler(id + '_worker', id, port);
+          WorkerMessageHandler.setup(workerHandler, port);
+          var messageHandler = new _message_handler.MessageHandler(id, id + '_worker', port);
+          _this8._messageHandler = messageHandler;
+
+          _this8._readyCapability.resolve();
+        })["catch"](function (reason) {
+          _this8._readyCapability.reject(new Error("Setting up fake worker failed: \"".concat(reason.message, "\".")));
+        });
+      }
+    }, {
+      key: "destroy",
+      value: function destroy() {
+        this.destroyed = true;
+
+        if (this._webWorker) {
+          this._webWorker.terminate();
+
+          this._webWorker = null;
+        }
+
+        pdfWorkerPorts["delete"](this._port);
+        this._port = null;
+
+        if (this._messageHandler) {
+          this._messageHandler.destroy();
+
+          this._messageHandler = null;
+        }
+      }
+    }, {
+      key: "promise",
+      get: function get() {
+        return this._readyCapability.promise;
+      }
+    }, {
+      key: "port",
+      get: function get() {
+        return this._port;
+      }
+    }, {
+      key: "messageHandler",
+      get: function get() {
+        return this._messageHandler;
+      }
+    }], [{
+      key: "fromPort",
+      value: function fromPort(params) {
+        if (!params || !params.port) {
+          throw new Error('PDFWorker.fromPort - invalid method signature.');
+        }
+
+        if (pdfWorkerPorts.has(params.port)) {
+          return pdfWorkerPorts.get(params.port);
+        }
+
+        return new PDFWorker(params);
+      }
+    }, {
+      key: "getWorkerSrc",
+      value: function getWorkerSrc() {
+        return _getWorkerSrc();
+      }
+    }]);
+
+    return PDFWorker;
+  }();
+
+  return PDFWorker;
+}();
+
+exports.PDFWorker = PDFWorker;
+
+var WorkerTransport =
+/*#__PURE__*/
+function () {
+  function WorkerTransport(messageHandler, loadingTask, networkStream, params) {
+    _classCallCheck(this, WorkerTransport);
+
+    this.messageHandler = messageHandler;
+    this.loadingTask = loadingTask;
+    this.commonObjs = new PDFObjects();
+    this.fontLoader = new _font_loader.FontLoader({
+      docId: loadingTask.docId,
+      onUnsupportedFeature: this._onUnsupportedFeature.bind(this)
+    });
+    this._params = params;
+    this.CMapReaderFactory = new params.CMapReaderFactory({
+      baseUrl: params.cMapUrl,
+      isCompressed: params.cMapPacked
+    });
+    this.destroyed = false;
+    this.destroyCapability = null;
+    this._passwordCapability = null;
+    this._networkStream = networkStream;
+    this._fullReader = null;
+    this._lastProgress = null;
+    this.pageCache = [];
+    this.pagePromises = [];
+    this.downloadInfoCapability = (0, _util.createPromiseCapability)();
+    this.setupMessageHandler();
+  }
+
+  _createClass(WorkerTransport, [{
+    key: "destroy",
+    value: function destroy() {
+      var _this9 = this;
+
+      if (this.destroyCapability) {
+        return this.destroyCapability.promise;
+      }
+
+      this.destroyed = true;
+      this.destroyCapability = (0, _util.createPromiseCapability)();
+
+      if (this._passwordCapability) {
+        this._passwordCapability.reject(new Error('Worker was destroyed during onPassword callback'));
+      }
+
+      var waitOn = [];
+      this.pageCache.forEach(function (page) {
+        if (page) {
+          waitOn.push(page._destroy());
+        }
+      });
+      this.pageCache.length = 0;
+      this.pagePromises.length = 0;
+      var terminated = this.messageHandler.sendWithPromise('Terminate', null);
+      waitOn.push(terminated);
+      Promise.all(waitOn).then(function () {
+        _this9.fontLoader.clear();
+
+        if (_this9._networkStream) {
+          _this9._networkStream.cancelAllRequests();
+        }
+
+        if (_this9.messageHandler) {
+          _this9.messageHandler.destroy();
+
+          _this9.messageHandler = null;
+        }
+
+        _this9.destroyCapability.resolve();
+      }, this.destroyCapability.reject);
+      return this.destroyCapability.promise;
+    }
+  }, {
+    key: "setupMessageHandler",
+    value: function setupMessageHandler() {
+      var messageHandler = this.messageHandler,
+          loadingTask = this.loadingTask;
+      messageHandler.on('GetReader', function (data, sink) {
+        var _this10 = this;
+
+        (0, _util.assert)(this._networkStream);
+        this._fullReader = this._networkStream.getFullReader();
+
+        this._fullReader.onProgress = function (evt) {
+          _this10._lastProgress = {
+            loaded: evt.loaded,
+            total: evt.total
+          };
+        };
+
+        sink.onPull = function () {
+          _this10._fullReader.read().then(function (_ref7) {
+            var value = _ref7.value,
+                done = _ref7.done;
+
+            if (done) {
+              sink.close();
+              return;
+            }
+
+            (0, _util.assert)((0, _util.isArrayBuffer)(value));
+            sink.enqueue(new Uint8Array(value), 1, [value]);
+          })["catch"](function (reason) {
+            sink.error(reason);
+          });
+        };
+
+        sink.onCancel = function (reason) {
+          _this10._fullReader.cancel(reason);
+        };
+      }, this);
+      messageHandler.on('ReaderHeadersReady', function (data) {
+        var _this11 = this;
+
+        var headersCapability = (0, _util.createPromiseCapability)();
+        var fullReader = this._fullReader;
+        fullReader.headersReady.then(function () {
+          if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
+            if (_this11._lastProgress && loadingTask.onProgress) {
+              loadingTask.onProgress(_this11._lastProgress);
+            }
+
+            fullReader.onProgress = function (evt) {
+              if (loadingTask.onProgress) {
+                loadingTask.onProgress({
+                  loaded: evt.loaded,
+                  total: evt.total
+                });
+              }
+            };
+          }
+
+          headersCapability.resolve({
+            isStreamingSupported: fullReader.isStreamingSupported,
+            isRangeSupported: fullReader.isRangeSupported,
+            contentLength: fullReader.contentLength
+          });
+        }, headersCapability.reject);
+        return headersCapability.promise;
+      }, this);
+      messageHandler.on('GetRangeReader', function (data, sink) {
+        (0, _util.assert)(this._networkStream);
+
+        var rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
+
+        if (!rangeReader) {
+          sink.close();
+          return;
+        }
+
+        sink.onPull = function () {
+          rangeReader.read().then(function (_ref8) {
+            var value = _ref8.value,
+                done = _ref8.done;
+
+            if (done) {
+              sink.close();
+              return;
+            }
+
+            (0, _util.assert)((0, _util.isArrayBuffer)(value));
+            sink.enqueue(new Uint8Array(value), 1, [value]);
+          })["catch"](function (reason) {
+            sink.error(reason);
+          });
+        };
+
+        sink.onCancel = function (reason) {
+          rangeReader.cancel(reason);
+        };
+      }, this);
+      messageHandler.on('GetDoc', function (_ref9) {
+        var pdfInfo = _ref9.pdfInfo;
+        this._numPages = pdfInfo.numPages;
+
+        loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));
+      }, this);
+      messageHandler.on('PasswordRequest', function (exception) {
+        var _this12 = this;
+
+        this._passwordCapability = (0, _util.createPromiseCapability)();
+
+        if (loadingTask.onPassword) {
+          var updatePassword = function updatePassword(password) {
+            _this12._passwordCapability.resolve({
+              password: password
+            });
+          };
+
+          try {
+            loadingTask.onPassword(updatePassword, exception.code);
+          } catch (ex) {
+            this._passwordCapability.reject(ex);
+          }
+        } else {
+          this._passwordCapability.reject(new _util.PasswordException(exception.message, exception.code));
+        }
+
+        return this._passwordCapability.promise;
+      }, this);
+      messageHandler.on('PasswordException', function (exception) {
+        loadingTask._capability.reject(new _util.PasswordException(exception.message, exception.code));
+      }, this);
+      messageHandler.on('InvalidPDF', function (exception) {
+        loadingTask._capability.reject(new _util.InvalidPDFException(exception.message));
+      }, this);
+      messageHandler.on('MissingPDF', function (exception) {
+        loadingTask._capability.reject(new _util.MissingPDFException(exception.message));
+      }, this);
+      messageHandler.on('UnexpectedResponse', function (exception) {
+        loadingTask._capability.reject(new _util.UnexpectedResponseException(exception.message, exception.status));
+      }, this);
+      messageHandler.on('UnknownError', function (exception) {
+        loadingTask._capability.reject(new _util.UnknownErrorException(exception.message, exception.details));
+      }, this);
+      messageHandler.on('DataLoaded', function (data) {
+        if (loadingTask.onProgress) {
+          loadingTask.onProgress({
+            loaded: data.length,
+            total: data.length
+          });
+        }
+
+        this.downloadInfoCapability.resolve(data);
+      }, this);
+      messageHandler.on('StartRenderPage', function (data) {
+        if (this.destroyed) {
+          return;
+        }
+
+        var page = this.pageCache[data.pageIndex];
+
+        page._stats.timeEnd('Page Request');
+
+        page._startRenderPage(data.transparency, data.intent);
+      }, this);
+      messageHandler.on('RenderPageChunk', function (data) {
+        if (this.destroyed) {
+          return;
+        }
+
+        var page = this.pageCache[data.pageIndex];
+
+        page._renderPageChunk(data.operatorList, data.intent);
+      }, this);
+      messageHandler.on('commonobj', function (data) {
+        var _this13 = this;
+
+        if (this.destroyed) {
+          return;
+        }
+
+        var _data = _slicedToArray(data, 3),
+            id = _data[0],
+            type = _data[1],
+            exportedData = _data[2];
+
+        if (this.commonObjs.has(id)) {
+          return;
+        }
+
+        switch (type) {
+          case 'Font':
+            var params = this._params;
+
+            if ('error' in exportedData) {
+              var exportedError = exportedData.error;
+              (0, _util.warn)("Error during font loading: ".concat(exportedError));
+              this.commonObjs.resolve(id, exportedError);
+              break;
+            }
+
+            var fontRegistry = null;
+
+            if (params.pdfBug && _global_scope["default"].FontInspector && _global_scope["default"].FontInspector.enabled) {
+              fontRegistry = {
+                registerFont: function registerFont(font, url) {
+                  _global_scope["default"]['FontInspector'].fontAdded(font, url);
+                }
+              };
+            }
+
+            var font = new _font_loader.FontFaceObject(exportedData, {
+              isEvalSupported: params.isEvalSupported,
+              disableFontFace: params.disableFontFace,
+              ignoreErrors: params.ignoreErrors,
+              onUnsupportedFeature: this._onUnsupportedFeature.bind(this),
+              fontRegistry: fontRegistry
+            });
+            this.fontLoader.bind(font).then(function () {
+              _this13.commonObjs.resolve(id, font);
+            }, function (reason) {
+              messageHandler.sendWithPromise('FontFallback', {
+                id: id
+              })["finally"](function () {
+                _this13.commonObjs.resolve(id, font);
+              });
+            });
+            break;
+
+          case 'FontPath':
+          case 'FontType3Res':
+            this.commonObjs.resolve(id, exportedData);
+            break;
+
+          default:
+            throw new Error("Got unknown common object type ".concat(type));
+        }
+      }, this);
+      messageHandler.on('obj', function (data) {
+        if (this.destroyed) {
+          return undefined;
+        }
+
+        var _data2 = _slicedToArray(data, 4),
+            id = _data2[0],
+            pageIndex = _data2[1],
+            type = _data2[2],
+            imageData = _data2[3];
+
+        var pageProxy = this.pageCache[pageIndex];
+
+        if (pageProxy.objs.has(id)) {
+          return undefined;
+        }
+
+        switch (type) {
+          case 'JpegStream':
+            return new Promise(function (resolve, reject) {
+              var img = new Image();
+
+              img.onload = function () {
+                resolve(img);
+              };
+
+              img.onerror = function () {
+                reject(new Error('Error during JPEG image loading'));
+                (0, _display_utils.releaseImageResources)(img);
+              };
+
+              img.src = imageData;
+            }).then(function (img) {
+              pageProxy.objs.resolve(id, img);
+            });
+
+          case 'Image':
+            pageProxy.objs.resolve(id, imageData);
+            var MAX_IMAGE_SIZE_TO_STORE = 8000000;
+
+            if (imageData && 'data' in imageData && imageData.data.length > MAX_IMAGE_SIZE_TO_STORE) {
+              pageProxy.cleanupAfterRender = true;
+            }
+
+            break;
+
+          default:
+            throw new Error("Got unknown object type ".concat(type));
+        }
+
+        return undefined;
+      }, this);
+      messageHandler.on('DocProgress', function (data) {
+        if (this.destroyed) {
+          return;
+        }
+
+        if (loadingTask.onProgress) {
+          loadingTask.onProgress({
+            loaded: data.loaded,
+            total: data.total
+          });
+        }
+      }, this);
+      messageHandler.on('PageError', function (data) {
+        if (this.destroyed) {
+          return;
+        }
+
+        var page = this.pageCache[data.pageIndex];
+        var intentState = page.intentStates[data.intent];
+
+        if (intentState.displayReadyCapability) {
+          intentState.displayReadyCapability.reject(new Error(data.error));
+        } else {
+          throw new Error(data.error);
+        }
+
+        if (intentState.operatorList) {
+          intentState.operatorList.lastChunk = true;
+
+          for (var i = 0; i < intentState.renderTasks.length; i++) {
+            intentState.renderTasks[i].operatorListChanged();
+          }
+        }
+      }, this);
+      messageHandler.on('UnsupportedFeature', this._onUnsupportedFeature, this);
+      messageHandler.on('JpegDecode', function (data) {
+        if (this.destroyed) {
+          return Promise.reject(new Error('Worker was destroyed'));
+        }
+
+        if (typeof document === 'undefined') {
+          return Promise.reject(new Error('"document" is not defined.'));
+        }
+
+        var _data3 = _slicedToArray(data, 2),
+            imageUrl = _data3[0],
+            components = _data3[1];
+
+        if (components !== 3 && components !== 1) {
+          return Promise.reject(new Error('Only 3 components or 1 component can be returned'));
+        }
+
+        return new Promise(function (resolve, reject) {
+          var img = new Image();
+
+          img.onload = function () {
+            var width = img.width,
+                height = img.height;
+            var size = width * height;
+            var rgbaLength = size * 4;
+            var buf = new Uint8ClampedArray(size * components);
+            var tmpCanvas = document.createElement('canvas');
+            tmpCanvas.width = width;
+            tmpCanvas.height = height;
+            var tmpCtx = tmpCanvas.getContext('2d');
+            tmpCtx.drawImage(img, 0, 0);
+            var data = tmpCtx.getImageData(0, 0, width, height).data;
+
+            if (components === 3) {
+              for (var i = 0, j = 0; i < rgbaLength; i += 4, j += 3) {
+                buf[j] = data[i];
+                buf[j + 1] = data[i + 1];
+                buf[j + 2] = data[i + 2];
+              }
+            } else if (components === 1) {
+              for (var _i2 = 0, _j = 0; _i2 < rgbaLength; _i2 += 4, _j++) {
+                buf[_j] = data[_i2];
+              }
+            }
+
+            resolve({
+              data: buf,
+              width: width,
+              height: height
+            });
+            (0, _display_utils.releaseImageResources)(img);
+            tmpCanvas.width = 0;
+            tmpCanvas.height = 0;
+            tmpCanvas = null;
+            tmpCtx = null;
+          };
+
+          img.onerror = function () {
+            reject(new Error('JpegDecode failed to load image'));
+            (0, _display_utils.releaseImageResources)(img);
+          };
+
+          img.src = imageUrl;
+        });
+      }, this);
+      messageHandler.on('FetchBuiltInCMap', function (data) {
+        if (this.destroyed) {
+          return Promise.reject(new Error('Worker was destroyed'));
+        }
+
+        return this.CMapReaderFactory.fetch({
+          name: data.name
+        });
+      }, this);
+    }
+  }, {
+    key: "_onUnsupportedFeature",
+    value: function _onUnsupportedFeature(_ref10) {
+      var featureId = _ref10.featureId;
+
+      if (this.destroyed) {
+        return;
+      }
+
+      if (this.loadingTask.onUnsupportedFeature) {
+        this.loadingTask.onUnsupportedFeature(featureId);
+      }
+    }
+  }, {
+    key: "getData",
+    value: function getData() {
+      return this.messageHandler.sendWithPromise('GetData', null);
+    }
+  }, {
+    key: "getPage",
+    value: function getPage(pageNumber) {
+      var _this14 = this;
+
+      if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) {
+        return Promise.reject(new Error('Invalid page request'));
+      }
+
+      var pageIndex = pageNumber - 1;
+
+      if (pageIndex in this.pagePromises) {
+        return this.pagePromises[pageIndex];
+      }
+
+      var promise = this.messageHandler.sendWithPromise('GetPage', {
+        pageIndex: pageIndex
+      }).then(function (pageInfo) {
+        if (_this14.destroyed) {
+          throw new Error('Transport destroyed');
+        }
+
+        var page = new PDFPageProxy(pageIndex, pageInfo, _this14, _this14._params.pdfBug);
+        _this14.pageCache[pageIndex] = page;
+        return page;
+      });
+      this.pagePromises[pageIndex] = promise;
+      return promise;
+    }
+  }, {
+    key: "getPageIndex",
+    value: function getPageIndex(ref) {
+      return this.messageHandler.sendWithPromise('GetPageIndex', {
+        ref: ref
+      })["catch"](function (reason) {
+        return Promise.reject(new Error(reason));
+      });
+    }
+  }, {
+    key: "getAnnotations",
+    value: function getAnnotations(pageIndex, intent) {
+      return this.messageHandler.sendWithPromise('GetAnnotations', {
+        pageIndex: pageIndex,
+        intent: intent
+      });
+    }
+  }, {
+    key: "getDestinations",
+    value: function getDestinations() {
+      return this.messageHandler.sendWithPromise('GetDestinations', null);
+    }
+  }, {
+    key: "getDestination",
+    value: function getDestination(id) {
+      if (typeof id !== 'string') {
+        return Promise.reject(new Error('Invalid destination request.'));
+      }
+
+      return this.messageHandler.sendWithPromise('GetDestination', {
+        id: id
+      });
+    }
+  }, {
+    key: "getPageLabels",
+    value: function getPageLabels() {
+      return this.messageHandler.sendWithPromise('GetPageLabels', null);
+    }
+  }, {
+    key: "getPageLayout",
+    value: function getPageLayout() {
+      return this.messageHandler.sendWithPromise('GetPageLayout', null);
+    }
+  }, {
+    key: "getPageMode",
+    value: function getPageMode() {
+      return this.messageHandler.sendWithPromise('GetPageMode', null);
+    }
+  }, {
+    key: "getViewerPreferences",
+    value: function getViewerPreferences() {
+      return this.messageHandler.sendWithPromise('GetViewerPreferences', null);
+    }
+  }, {
+    key: "getOpenActionDestination",
+    value: function getOpenActionDestination() {
+      return this.messageHandler.sendWithPromise('GetOpenActionDestination', null);
+    }
+  }, {
+    key: "getAttachments",
+    value: function getAttachments() {
+      return this.messageHandler.sendWithPromise('GetAttachments', null);
+    }
+  }, {
+    key: "getJavaScript",
+    value: function getJavaScript() {
+      return this.messageHandler.sendWithPromise('GetJavaScript', null);
+    }
+  }, {
+    key: "getOutline",
+    value: function getOutline() {
+      return this.messageHandler.sendWithPromise('GetOutline', null);
+    }
+  }, {
+    key: "getPermissions",
+    value: function getPermissions() {
+      return this.messageHandler.sendWithPromise('GetPermissions', null);
+    }
+  }, {
+    key: "getMetadata",
+    value: function getMetadata() {
+      var _this15 = this;
+
+      return this.messageHandler.sendWithPromise('GetMetadata', null).then(function (results) {
+        return {
+          info: results[0],
+          metadata: results[1] ? new _metadata.Metadata(results[1]) : null,
+          contentDispositionFilename: _this15._fullReader ? _this15._fullReader.filename : null
+        };
+      });
+    }
+  }, {
+    key: "getStats",
+    value: function getStats() {
+      return this.messageHandler.sendWithPromise('GetStats', null);
+    }
+  }, {
+    key: "startCleanup",
+    value: function startCleanup() {
+      var _this16 = this;
+
+      this.messageHandler.sendWithPromise('Cleanup', null).then(function () {
+        for (var i = 0, ii = _this16.pageCache.length; i < ii; i++) {
+          var page = _this16.pageCache[i];
+
+          if (page) {
+            page.cleanup();
+          }
+        }
+
+        _this16.commonObjs.clear();
+
+        _this16.fontLoader.clear();
+      });
+    }
+  }, {
+    key: "loadingParams",
+    get: function get() {
+      var params = this._params;
+      return (0, _util.shadow)(this, 'loadingParams', {
+        disableAutoFetch: params.disableAutoFetch,
+        disableCreateObjectURL: params.disableCreateObjectURL,
+        disableFontFace: params.disableFontFace,
+        nativeImageDecoderSupport: params.nativeImageDecoderSupport
+      });
+    }
+  }]);
+
+  return WorkerTransport;
+}();
+
+var PDFObjects =
+/*#__PURE__*/
+function () {
+  function PDFObjects() {
+    _classCallCheck(this, PDFObjects);
+
+    this._objs = Object.create(null);
+  }
+
+  _createClass(PDFObjects, [{
+    key: "_ensureObj",
+    value: function _ensureObj(objId) {
+      if (this._objs[objId]) {
+        return this._objs[objId];
+      }
+
+      return this._objs[objId] = {
+        capability: (0, _util.createPromiseCapability)(),
+        data: null,
+        resolved: false
+      };
+    }
+  }, {
+    key: "get",
+    value: function get(objId) {
+      var callback = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
+      if (callback) {
+        this._ensureObj(objId).capability.promise.then(callback);
+
+        return null;
+      }
+
+      var obj = this._objs[objId];
+
+      if (!obj || !obj.resolved) {
+        throw new Error("Requesting object that isn't resolved yet ".concat(objId, "."));
+      }
+
+      return obj.data;
+    }
+  }, {
+    key: "has",
+    value: function has(objId) {
+      var obj = this._objs[objId];
+      return obj ? obj.resolved : false;
+    }
+  }, {
+    key: "resolve",
+    value: function resolve(objId, data) {
+      var obj = this._ensureObj(objId);
+
+      obj.resolved = true;
+      obj.data = data;
+      obj.capability.resolve(data);
+    }
+  }, {
+    key: "clear",
+    value: function clear() {
+      for (var objId in this._objs) {
+        var data = this._objs[objId].data;
+
+        if (typeof Image !== 'undefined' && data instanceof Image) {
+          (0, _display_utils.releaseImageResources)(data);
+        }
+      }
+
+      this._objs = Object.create(null);
+    }
+  }]);
+
+  return PDFObjects;
+}();
+
+var RenderTask =
+/*#__PURE__*/
+function () {
+  function RenderTask(internalRenderTask) {
+    _classCallCheck(this, RenderTask);
+
+    this._internalRenderTask = internalRenderTask;
+    this.onContinue = null;
+  }
+
+  _createClass(RenderTask, [{
+    key: "cancel",
+    value: function cancel() {
+      this._internalRenderTask.cancel();
+    }
+  }, {
+    key: "then",
+    value: function then(onFulfilled, onRejected) {
+      (0, _display_utils.deprecated)('RenderTask.then method, use the `promise` getter instead.');
+      return this.promise.then.apply(this.promise, arguments);
+    }
+  }, {
+    key: "promise",
+    get: function get() {
+      return this._internalRenderTask.capability.promise;
+    }
+  }]);
+
+  return RenderTask;
+}();
+
+var InternalRenderTask = function InternalRenderTaskClosure() {
+  var canvasInRendering = new WeakSet();
+
+  var InternalRenderTask =
+  /*#__PURE__*/
+  function () {
+    function InternalRenderTask(_ref11) {
+      var callback = _ref11.callback,
+          params = _ref11.params,
+          objs = _ref11.objs,
+          commonObjs = _ref11.commonObjs,
+          operatorList = _ref11.operatorList,
+          pageNumber = _ref11.pageNumber,
+          canvasFactory = _ref11.canvasFactory,
+          webGLContext = _ref11.webGLContext,
+          _ref11$useRequestAnim = _ref11.useRequestAnimationFrame,
+          useRequestAnimationFrame = _ref11$useRequestAnim === void 0 ? false : _ref11$useRequestAnim,
+          _ref11$pdfBug = _ref11.pdfBug,
+          pdfBug = _ref11$pdfBug === void 0 ? false : _ref11$pdfBug;
+
+      _classCallCheck(this, InternalRenderTask);
+
+      this.callback = callback;
+      this.params = params;
+      this.objs = objs;
+      this.commonObjs = commonObjs;
+      this.operatorListIdx = null;
+      this.operatorList = operatorList;
+      this.pageNumber = pageNumber;
+      this.canvasFactory = canvasFactory;
+      this.webGLContext = webGLContext;
+      this._pdfBug = pdfBug;
+      this.running = false;
+      this.graphicsReadyCallback = null;
+      this.graphicsReady = false;
+      this._useRequestAnimationFrame = useRequestAnimationFrame === true && typeof window !== 'undefined';
+      this.cancelled = false;
+      this.capability = (0, _util.createPromiseCapability)();
+      this.task = new RenderTask(this);
+      this._continueBound = this._continue.bind(this);
+      this._scheduleNextBound = this._scheduleNext.bind(this);
+      this._nextBound = this._next.bind(this);
+      this._canvas = params.canvasContext.canvas;
+    }
+
+    _createClass(InternalRenderTask, [{
+      key: "initializeGraphics",
+      value: function initializeGraphics() {
+        var transparency = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+        if (this.cancelled) {
+          return;
+        }
+
+        if (this._canvas) {
+          if (canvasInRendering.has(this._canvas)) {
+            throw new Error('Cannot use the same canvas during multiple render() operations. ' + 'Use different canvas or ensure previous operations were ' + 'cancelled or completed.');
+          }
+
+          canvasInRendering.add(this._canvas);
+        }
+
+        if (this._pdfBug && _global_scope["default"].StepperManager && _global_scope["default"].StepperManager.enabled) {
+          this.stepper = _global_scope["default"].StepperManager.create(this.pageNumber - 1);
+          this.stepper.init(this.operatorList);
+          this.stepper.nextBreakPoint = this.stepper.getNextBreakPoint();
+        }
+
+        var _this$params = this.params,
+            canvasContext = _this$params.canvasContext,
+            viewport = _this$params.viewport,
+            transform = _this$params.transform,
+            imageLayer = _this$params.imageLayer,
+            background = _this$params.background;
+        this.gfx = new _canvas.CanvasGraphics(canvasContext, this.commonObjs, this.objs, this.canvasFactory, this.webGLContext, imageLayer);
+        this.gfx.beginDrawing({
+          transform: transform,
+          viewport: viewport,
+          transparency: transparency,
+          background: background
+        });
+        this.operatorListIdx = 0;
+        this.graphicsReady = true;
+
+        if (this.graphicsReadyCallback) {
+          this.graphicsReadyCallback();
+        }
+      }
+    }, {
+      key: "cancel",
+      value: function cancel() {
+        var error = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
+        this.running = false;
+        this.cancelled = true;
+
+        if (this.gfx) {
+          this.gfx.endDrawing();
+        }
+
+        if (this._canvas) {
+          canvasInRendering["delete"](this._canvas);
+        }
+
+        this.callback(error || new _display_utils.RenderingCancelledException("Rendering cancelled, page ".concat(this.pageNumber), 'canvas'));
+      }
+    }, {
+      key: "operatorListChanged",
+      value: function operatorListChanged() {
+        if (!this.graphicsReady) {
+          if (!this.graphicsReadyCallback) {
+            this.graphicsReadyCallback = this._continueBound;
+          }
+
+          return;
+        }
+
+        if (this.stepper) {
+          this.stepper.updateOperatorList(this.operatorList);
+        }
+
+        if (this.running) {
+          return;
+        }
+
+        this._continue();
+      }
+    }, {
+      key: "_continue",
+      value: function _continue() {
+        this.running = true;
+
+        if (this.cancelled) {
+          return;
+        }
+
+        if (this.task.onContinue) {
+          this.task.onContinue(this._scheduleNextBound);
+        } else {
+          this._scheduleNext();
+        }
+      }
+    }, {
+      key: "_scheduleNext",
+      value: function _scheduleNext() {
+        var _this17 = this;
+
+        if (this._useRequestAnimationFrame) {
+          window.requestAnimationFrame(function () {
+            _this17._nextBound()["catch"](_this17.cancel.bind(_this17));
+          });
+        } else {
+          Promise.resolve().then(this._nextBound)["catch"](this.cancel.bind(this));
+        }
+      }
+    }, {
+      key: "_next",
+      value: function () {
+        var _next2 = _asyncToGenerator(
+        /*#__PURE__*/
+        _regenerator["default"].mark(function _callee() {
+          return _regenerator["default"].wrap(function _callee$(_context) {
+            while (1) {
+              switch (_context.prev = _context.next) {
+                case 0:
+                  if (!this.cancelled) {
+                    _context.next = 2;
+                    break;
+                  }
+
+                  return _context.abrupt("return");
+
+                case 2:
+                  this.operatorListIdx = this.gfx.executeOperatorList(this.operatorList, this.operatorListIdx, this._continueBound, this.stepper);
+
+                  if (this.operatorListIdx === this.operatorList.argsArray.length) {
+                    this.running = false;
+
+                    if (this.operatorList.lastChunk) {
+                      this.gfx.endDrawing();
+
+                      if (this._canvas) {
+                        canvasInRendering["delete"](this._canvas);
+                      }
+
+                      this.callback();
+                    }
+                  }
+
+                case 4:
+                case "end":
+                  return _context.stop();
+              }
+            }
+          }, _callee, this);
+        }));
+
+        function _next() {
+          return _next2.apply(this, arguments);
+        }
+
+        return _next;
+      }()
+    }]);
+
+    return InternalRenderTask;
+  }();
+
+  return InternalRenderTask;
+}();
+
+var version = '2.2.228';
+exports.version = version;
+var build = 'd7afb74a';
+exports.build = build;
+
+/***/ }),
+/* 148 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = __w_pdfjs_require__(149);
+
+/***/ }),
+/* 149 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(module) {
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var runtime = function (exports) {
+  "use strict";
+
+  var Op = Object.prototype;
+  var hasOwn = Op.hasOwnProperty;
+  var undefined;
+  var $Symbol = typeof Symbol === "function" ? Symbol : {};
+  var iteratorSymbol = $Symbol.iterator || "@@iterator";
+  var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
+  var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
+
+  function wrap(innerFn, outerFn, self, tryLocsList) {
+    var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
+    var generator = Object.create(protoGenerator.prototype);
+    var context = new Context(tryLocsList || []);
+    generator._invoke = makeInvokeMethod(innerFn, self, context);
+    return generator;
+  }
+
+  exports.wrap = wrap;
+
+  function tryCatch(fn, obj, arg) {
+    try {
+      return {
+        type: "normal",
+        arg: fn.call(obj, arg)
+      };
+    } catch (err) {
+      return {
+        type: "throw",
+        arg: err
+      };
+    }
+  }
+
+  var GenStateSuspendedStart = "suspendedStart";
+  var GenStateSuspendedYield = "suspendedYield";
+  var GenStateExecuting = "executing";
+  var GenStateCompleted = "completed";
+  var ContinueSentinel = {};
+
+  function Generator() {}
+
+  function GeneratorFunction() {}
+
+  function GeneratorFunctionPrototype() {}
+
+  var IteratorPrototype = {};
+
+  IteratorPrototype[iteratorSymbol] = function () {
+    return this;
+  };
+
+  var getProto = Object.getPrototypeOf;
+  var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
+
+  if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
+    IteratorPrototype = NativeIteratorPrototype;
+  }
+
+  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
+  GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
+  GeneratorFunctionPrototype.constructor = GeneratorFunction;
+  GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction";
+
+  function defineIteratorMethods(prototype) {
+    ["next", "throw", "return"].forEach(function (method) {
+      prototype[method] = function (arg) {
+        return this._invoke(method, arg);
+      };
+    });
+  }
+
+  exports.isGeneratorFunction = function (genFun) {
+    var ctor = typeof genFun === "function" && genFun.constructor;
+    return ctor ? ctor === GeneratorFunction || (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
+  };
+
+  exports.mark = function (genFun) {
+    if (Object.setPrototypeOf) {
+      Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
+    } else {
+      genFun.__proto__ = GeneratorFunctionPrototype;
+
+      if (!(toStringTagSymbol in genFun)) {
+        genFun[toStringTagSymbol] = "GeneratorFunction";
+      }
+    }
+
+    genFun.prototype = Object.create(Gp);
+    return genFun;
+  };
+
+  exports.awrap = function (arg) {
+    return {
+      __await: arg
+    };
+  };
+
+  function AsyncIterator(generator) {
+    function invoke(method, arg, resolve, reject) {
+      var record = tryCatch(generator[method], generator, arg);
+
+      if (record.type === "throw") {
+        reject(record.arg);
+      } else {
+        var result = record.arg;
+        var value = result.value;
+
+        if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) {
+          return Promise.resolve(value.__await).then(function (value) {
+            invoke("next", value, resolve, reject);
+          }, function (err) {
+            invoke("throw", err, resolve, reject);
+          });
+        }
+
+        return Promise.resolve(value).then(function (unwrapped) {
+          result.value = unwrapped;
+          resolve(result);
+        }, function (error) {
+          return invoke("throw", error, resolve, reject);
+        });
+      }
+    }
+
+    var previousPromise;
+
+    function enqueue(method, arg) {
+      function callInvokeWithMethodAndArg() {
+        return new Promise(function (resolve, reject) {
+          invoke(method, arg, resolve, reject);
+        });
+      }
+
+      return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
+    }
+
+    this._invoke = enqueue;
+  }
+
+  defineIteratorMethods(AsyncIterator.prototype);
+
+  AsyncIterator.prototype[asyncIteratorSymbol] = function () {
+    return this;
+  };
+
+  exports.AsyncIterator = AsyncIterator;
+
+  exports.async = function (innerFn, outerFn, self, tryLocsList) {
+    var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
+    return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
+      return result.done ? result.value : iter.next();
+    });
+  };
+
+  function makeInvokeMethod(innerFn, self, context) {
+    var state = GenStateSuspendedStart;
+    return function invoke(method, arg) {
+      if (state === GenStateExecuting) {
+        throw new Error("Generator is already running");
+      }
+
+      if (state === GenStateCompleted) {
+        if (method === "throw") {
+          throw arg;
+        }
+
+        return doneResult();
+      }
+
+      context.method = method;
+      context.arg = arg;
+
+      while (true) {
+        var delegate = context.delegate;
+
+        if (delegate) {
+          var delegateResult = maybeInvokeDelegate(delegate, context);
+
+          if (delegateResult) {
+            if (delegateResult === ContinueSentinel) continue;
+            return delegateResult;
+          }
+        }
+
+        if (context.method === "next") {
+          context.sent = context._sent = context.arg;
+        } else if (context.method === "throw") {
+          if (state === GenStateSuspendedStart) {
+            state = GenStateCompleted;
+            throw context.arg;
+          }
+
+          context.dispatchException(context.arg);
+        } else if (context.method === "return") {
+          context.abrupt("return", context.arg);
+        }
+
+        state = GenStateExecuting;
+        var record = tryCatch(innerFn, self, context);
+
+        if (record.type === "normal") {
+          state = context.done ? GenStateCompleted : GenStateSuspendedYield;
+
+          if (record.arg === ContinueSentinel) {
+            continue;
+          }
+
+          return {
+            value: record.arg,
+            done: context.done
+          };
+        } else if (record.type === "throw") {
+          state = GenStateCompleted;
+          context.method = "throw";
+          context.arg = record.arg;
+        }
+      }
+    };
+  }
+
+  function maybeInvokeDelegate(delegate, context) {
+    var method = delegate.iterator[context.method];
+
+    if (method === undefined) {
+      context.delegate = null;
+
+      if (context.method === "throw") {
+        if (delegate.iterator["return"]) {
+          context.method = "return";
+          context.arg = undefined;
+          maybeInvokeDelegate(delegate, context);
+
+          if (context.method === "throw") {
+            return ContinueSentinel;
+          }
+        }
+
+        context.method = "throw";
+        context.arg = new TypeError("The iterator does not provide a 'throw' method");
+      }
+
+      return ContinueSentinel;
+    }
+
+    var record = tryCatch(method, delegate.iterator, context.arg);
+
+    if (record.type === "throw") {
+      context.method = "throw";
+      context.arg = record.arg;
+      context.delegate = null;
+      return ContinueSentinel;
+    }
+
+    var info = record.arg;
+
+    if (!info) {
+      context.method = "throw";
+      context.arg = new TypeError("iterator result is not an object");
+      context.delegate = null;
+      return ContinueSentinel;
+    }
+
+    if (info.done) {
+      context[delegate.resultName] = info.value;
+      context.next = delegate.nextLoc;
+
+      if (context.method !== "return") {
+        context.method = "next";
+        context.arg = undefined;
+      }
+    } else {
+      return info;
+    }
+
+    context.delegate = null;
+    return ContinueSentinel;
+  }
+
+  defineIteratorMethods(Gp);
+  Gp[toStringTagSymbol] = "Generator";
+
+  Gp[iteratorSymbol] = function () {
+    return this;
+  };
+
+  Gp.toString = function () {
+    return "[object Generator]";
+  };
+
+  function pushTryEntry(locs) {
+    var entry = {
+      tryLoc: locs[0]
+    };
+
+    if (1 in locs) {
+      entry.catchLoc = locs[1];
+    }
+
+    if (2 in locs) {
+      entry.finallyLoc = locs[2];
+      entry.afterLoc = locs[3];
+    }
+
+    this.tryEntries.push(entry);
+  }
+
+  function resetTryEntry(entry) {
+    var record = entry.completion || {};
+    record.type = "normal";
+    delete record.arg;
+    entry.completion = record;
+  }
+
+  function Context(tryLocsList) {
+    this.tryEntries = [{
+      tryLoc: "root"
+    }];
+    tryLocsList.forEach(pushTryEntry, this);
+    this.reset(true);
+  }
+
+  exports.keys = function (object) {
+    var keys = [];
+
+    for (var key in object) {
+      keys.push(key);
+    }
+
+    keys.reverse();
+    return function next() {
+      while (keys.length) {
+        var key = keys.pop();
+
+        if (key in object) {
+          next.value = key;
+          next.done = false;
+          return next;
+        }
+      }
+
+      next.done = true;
+      return next;
+    };
+  };
+
+  function values(iterable) {
+    if (iterable) {
+      var iteratorMethod = iterable[iteratorSymbol];
+
+      if (iteratorMethod) {
+        return iteratorMethod.call(iterable);
+      }
+
+      if (typeof iterable.next === "function") {
+        return iterable;
+      }
+
+      if (!isNaN(iterable.length)) {
+        var i = -1,
+            next = function next() {
+          while (++i < iterable.length) {
+            if (hasOwn.call(iterable, i)) {
+              next.value = iterable[i];
+              next.done = false;
+              return next;
+            }
+          }
+
+          next.value = undefined;
+          next.done = true;
+          return next;
+        };
+
+        return next.next = next;
+      }
+    }
+
+    return {
+      next: doneResult
+    };
+  }
+
+  exports.values = values;
+
+  function doneResult() {
+    return {
+      value: undefined,
+      done: true
+    };
+  }
+
+  Context.prototype = {
+    constructor: Context,
+    reset: function reset(skipTempReset) {
+      this.prev = 0;
+      this.next = 0;
+      this.sent = this._sent = undefined;
+      this.done = false;
+      this.delegate = null;
+      this.method = "next";
+      this.arg = undefined;
+      this.tryEntries.forEach(resetTryEntry);
+
+      if (!skipTempReset) {
+        for (var name in this) {
+          if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
+            this[name] = undefined;
+          }
+        }
+      }
+    },
+    stop: function stop() {
+      this.done = true;
+      var rootEntry = this.tryEntries[0];
+      var rootRecord = rootEntry.completion;
+
+      if (rootRecord.type === "throw") {
+        throw rootRecord.arg;
+      }
+
+      return this.rval;
+    },
+    dispatchException: function dispatchException(exception) {
+      if (this.done) {
+        throw exception;
+      }
+
+      var context = this;
+
+      function handle(loc, caught) {
+        record.type = "throw";
+        record.arg = exception;
+        context.next = loc;
+
+        if (caught) {
+          context.method = "next";
+          context.arg = undefined;
+        }
+
+        return !!caught;
+      }
+
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+        var record = entry.completion;
+
+        if (entry.tryLoc === "root") {
+          return handle("end");
+        }
+
+        if (entry.tryLoc <= this.prev) {
+          var hasCatch = hasOwn.call(entry, "catchLoc");
+          var hasFinally = hasOwn.call(entry, "finallyLoc");
+
+          if (hasCatch && hasFinally) {
+            if (this.prev < entry.catchLoc) {
+              return handle(entry.catchLoc, true);
+            } else if (this.prev < entry.finallyLoc) {
+              return handle(entry.finallyLoc);
+            }
+          } else if (hasCatch) {
+            if (this.prev < entry.catchLoc) {
+              return handle(entry.catchLoc, true);
+            }
+          } else if (hasFinally) {
+            if (this.prev < entry.finallyLoc) {
+              return handle(entry.finallyLoc);
+            }
+          } else {
+            throw new Error("try statement without catch or finally");
+          }
+        }
+      }
+    },
+    abrupt: function abrupt(type, arg) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
+          var finallyEntry = entry;
+          break;
+        }
+      }
+
+      if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
+        finallyEntry = null;
+      }
+
+      var record = finallyEntry ? finallyEntry.completion : {};
+      record.type = type;
+      record.arg = arg;
+
+      if (finallyEntry) {
+        this.method = "next";
+        this.next = finallyEntry.finallyLoc;
+        return ContinueSentinel;
+      }
+
+      return this.complete(record);
+    },
+    complete: function complete(record, afterLoc) {
+      if (record.type === "throw") {
+        throw record.arg;
+      }
+
+      if (record.type === "break" || record.type === "continue") {
+        this.next = record.arg;
+      } else if (record.type === "return") {
+        this.rval = this.arg = record.arg;
+        this.method = "return";
+        this.next = "end";
+      } else if (record.type === "normal" && afterLoc) {
+        this.next = afterLoc;
+      }
+
+      return ContinueSentinel;
+    },
+    finish: function finish(finallyLoc) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.finallyLoc === finallyLoc) {
+          this.complete(entry.completion, entry.afterLoc);
+          resetTryEntry(entry);
+          return ContinueSentinel;
+        }
+      }
+    },
+    "catch": function _catch(tryLoc) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.tryLoc === tryLoc) {
+          var record = entry.completion;
+
+          if (record.type === "throw") {
+            var thrown = record.arg;
+            resetTryEntry(entry);
+          }
+
+          return thrown;
+        }
+      }
+
+      throw new Error("illegal catch attempt");
+    },
+    delegateYield: function delegateYield(iterable, resultName, nextLoc) {
+      this.delegate = {
+        iterator: values(iterable),
+        resultName: resultName,
+        nextLoc: nextLoc
+      };
+
+      if (this.method === "next") {
+        this.arg = undefined;
+      }
+
+      return ContinueSentinel;
+    }
+  };
+  return exports;
+}(( false ? undefined : _typeof(module)) === "object" ? module.exports : {});
+
+try {
+  regeneratorRuntime = runtime;
+} catch (accidentalStrictMode) {
+  Function("r", "regeneratorRuntime = r")(runtime);
+}
+/* WEBPACK VAR INJECTION */}.call(this, __w_pdfjs_require__(150)(module)))
+
+/***/ }),
+/* 150 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (module) {
+  if (!module.webpackPolyfill) {
+    module.deprecate = function () {};
+
+    module.paths = [];
+    if (!module.children) module.children = [];
+    Object.defineProperty(module, "loaded", {
+      enumerable: true,
+      get: function get() {
+        return module.l;
+      }
+    });
+    Object.defineProperty(module, "id", {
+      enumerable: true,
+      get: function get() {
+        return module.i;
+      }
+    });
+    module.webpackPolyfill = 1;
+  }
+
+  return module;
+};
+
+/***/ }),
+/* 151 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.addLinkAttributes = addLinkAttributes;
+exports.getFilenameFromUrl = getFilenameFromUrl;
+exports.isFetchSupported = isFetchSupported;
+exports.isValidFetchUrl = isValidFetchUrl;
+exports.loadScript = loadScript;
+exports.deprecated = deprecated;
+exports.releaseImageResources = releaseImageResources;
+exports.PDFDateString = exports.DummyStatTimer = exports.StatTimer = exports.DOMSVGFactory = exports.DOMCMapReaderFactory = exports.DOMCanvasFactory = exports.DEFAULT_LINK_REL = exports.LinkTarget = exports.RenderingCancelledException = exports.PageViewport = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var DEFAULT_LINK_REL = 'noopener noreferrer nofollow';
+exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL;
+var SVG_NS = 'http://www.w3.org/2000/svg';
+
+var DOMCanvasFactory =
+/*#__PURE__*/
+function () {
+  function DOMCanvasFactory() {
+    _classCallCheck(this, DOMCanvasFactory);
+  }
+
+  _createClass(DOMCanvasFactory, [{
+    key: "create",
+    value: function create(width, height) {
+      if (width <= 0 || height <= 0) {
+        throw new Error('Invalid canvas size');
+      }
+
+      var canvas = document.createElement('canvas');
+      var context = canvas.getContext('2d');
+      canvas.width = width;
+      canvas.height = height;
+      return {
+        canvas: canvas,
+        context: context
+      };
+    }
+  }, {
+    key: "reset",
+    value: function reset(canvasAndContext, width, height) {
+      if (!canvasAndContext.canvas) {
+        throw new Error('Canvas is not specified');
+      }
+
+      if (width <= 0 || height <= 0) {
+        throw new Error('Invalid canvas size');
+      }
+
+      canvasAndContext.canvas.width = width;
+      canvasAndContext.canvas.height = height;
+    }
+  }, {
+    key: "destroy",
+    value: function destroy(canvasAndContext) {
+      if (!canvasAndContext.canvas) {
+        throw new Error('Canvas is not specified');
+      }
+
+      canvasAndContext.canvas.width = 0;
+      canvasAndContext.canvas.height = 0;
+      canvasAndContext.canvas = null;
+      canvasAndContext.context = null;
+    }
+  }]);
+
+  return DOMCanvasFactory;
+}();
+
+exports.DOMCanvasFactory = DOMCanvasFactory;
+
+var DOMCMapReaderFactory =
+/*#__PURE__*/
+function () {
+  function DOMCMapReaderFactory(_ref) {
+    var _ref$baseUrl = _ref.baseUrl,
+        baseUrl = _ref$baseUrl === void 0 ? null : _ref$baseUrl,
+        _ref$isCompressed = _ref.isCompressed,
+        isCompressed = _ref$isCompressed === void 0 ? false : _ref$isCompressed;
+
+    _classCallCheck(this, DOMCMapReaderFactory);
+
+    this.baseUrl = baseUrl;
+    this.isCompressed = isCompressed;
+  }
+
+  _createClass(DOMCMapReaderFactory, [{
+    key: "fetch",
+    value: function (_fetch) {
+      function fetch(_x) {
+        return _fetch.apply(this, arguments);
+      }
+
+      fetch.toString = function () {
+        return _fetch.toString();
+      };
+
+      return fetch;
+    }(
+    /*#__PURE__*/
+    function () {
+      var _ref3 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2(_ref2) {
+        var _this = this;
+
+        var name, url, compressionType;
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                name = _ref2.name;
+
+                if (this.baseUrl) {
+                  _context2.next = 3;
+                  break;
+                }
+
+                throw new Error('The CMap "baseUrl" parameter must be specified, ensure that ' + 'the "cMapUrl" and "cMapPacked" API parameters are provided.');
+
+              case 3:
+                if (name) {
+                  _context2.next = 5;
+                  break;
+                }
+
+                throw new Error('CMap name must be specified.');
+
+              case 5:
+                url = this.baseUrl + name + (this.isCompressed ? '.bcmap' : '');
+                compressionType = this.isCompressed ? _util.CMapCompressionType.BINARY : _util.CMapCompressionType.NONE;
+
+                if (!(isFetchSupported() && isValidFetchUrl(url, document.baseURI))) {
+                  _context2.next = 9;
+                  break;
+                }
+
+                return _context2.abrupt("return", fetch(url).then(
+                /*#__PURE__*/
+                function () {
+                  var _ref4 = _asyncToGenerator(
+                  /*#__PURE__*/
+                  _regenerator["default"].mark(function _callee(response) {
+                    var cMapData;
+                    return _regenerator["default"].wrap(function _callee$(_context) {
+                      while (1) {
+                        switch (_context.prev = _context.next) {
+                          case 0:
+                            if (response.ok) {
+                              _context.next = 2;
+                              break;
+                            }
+
+                            throw new Error(response.statusText);
+
+                          case 2:
+                            if (!_this.isCompressed) {
+                              _context.next = 10;
+                              break;
+                            }
+
+                            _context.t0 = Uint8Array;
+                            _context.next = 6;
+                            return response.arrayBuffer();
+
+                          case 6:
+                            _context.t1 = _context.sent;
+                            cMapData = new _context.t0(_context.t1);
+                            _context.next = 15;
+                            break;
+
+                          case 10:
+                            _context.t2 = _util.stringToBytes;
+                            _context.next = 13;
+                            return response.text();
+
+                          case 13:
+                            _context.t3 = _context.sent;
+                            cMapData = (0, _context.t2)(_context.t3);
+
+                          case 15:
+                            return _context.abrupt("return", {
+                              cMapData: cMapData,
+                              compressionType: compressionType
+                            });
+
+                          case 16:
+                          case "end":
+                            return _context.stop();
+                        }
+                      }
+                    }, _callee);
+                  }));
+
+                  return function (_x3) {
+                    return _ref4.apply(this, arguments);
+                  };
+                }())["catch"](function (reason) {
+                  throw new Error("Unable to load ".concat(_this.isCompressed ? 'binary ' : '') + "CMap at: ".concat(url));
+                }));
+
+              case 9:
+                return _context2.abrupt("return", new Promise(function (resolve, reject) {
+                  var request = new XMLHttpRequest();
+                  request.open('GET', url, true);
+
+                  if (_this.isCompressed) {
+                    request.responseType = 'arraybuffer';
+                  }
+
+                  request.onreadystatechange = function () {
+                    if (request.readyState !== XMLHttpRequest.DONE) {
+                      return;
+                    }
+
+                    if (request.status === 200 || request.status === 0) {
+                      var cMapData;
+
+                      if (_this.isCompressed && request.response) {
+                        cMapData = new Uint8Array(request.response);
+                      } else if (!_this.isCompressed && request.responseText) {
+                        cMapData = (0, _util.stringToBytes)(request.responseText);
+                      }
+
+                      if (cMapData) {
+                        resolve({
+                          cMapData: cMapData,
+                          compressionType: compressionType
+                        });
+                        return;
+                      }
+                    }
+
+                    reject(new Error(request.statusText));
+                  };
+
+                  request.send(null);
+                })["catch"](function (reason) {
+                  throw new Error("Unable to load ".concat(_this.isCompressed ? 'binary ' : '') + "CMap at: ".concat(url));
+                }));
+
+              case 10:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      return function (_x2) {
+        return _ref3.apply(this, arguments);
+      };
+    }())
+  }]);
+
+  return DOMCMapReaderFactory;
+}();
+
+exports.DOMCMapReaderFactory = DOMCMapReaderFactory;
+
+var DOMSVGFactory =
+/*#__PURE__*/
+function () {
+  function DOMSVGFactory() {
+    _classCallCheck(this, DOMSVGFactory);
+  }
+
+  _createClass(DOMSVGFactory, [{
+    key: "create",
+    value: function create(width, height) {
+      (0, _util.assert)(width > 0 && height > 0, 'Invalid SVG dimensions');
+      var svg = document.createElementNS(SVG_NS, 'svg:svg');
+      svg.setAttribute('version', '1.1');
+      svg.setAttribute('width', width + 'px');
+      svg.setAttribute('height', height + 'px');
+      svg.setAttribute('preserveAspectRatio', 'none');
+      svg.setAttribute('viewBox', '0 0 ' + width + ' ' + height);
+      return svg;
+    }
+  }, {
+    key: "createElement",
+    value: function createElement(type) {
+      (0, _util.assert)(typeof type === 'string', 'Invalid SVG element type');
+      return document.createElementNS(SVG_NS, type);
+    }
+  }]);
+
+  return DOMSVGFactory;
+}();
+
+exports.DOMSVGFactory = DOMSVGFactory;
+
+var PageViewport =
+/*#__PURE__*/
+function () {
+  function PageViewport(_ref5) {
+    var viewBox = _ref5.viewBox,
+        scale = _ref5.scale,
+        rotation = _ref5.rotation,
+        _ref5$offsetX = _ref5.offsetX,
+        offsetX = _ref5$offsetX === void 0 ? 0 : _ref5$offsetX,
+        _ref5$offsetY = _ref5.offsetY,
+        offsetY = _ref5$offsetY === void 0 ? 0 : _ref5$offsetY,
+        _ref5$dontFlip = _ref5.dontFlip,
+        dontFlip = _ref5$dontFlip === void 0 ? false : _ref5$dontFlip;
+
+    _classCallCheck(this, PageViewport);
+
+    this.viewBox = viewBox;
+    this.scale = scale;
+    this.rotation = rotation;
+    this.offsetX = offsetX;
+    this.offsetY = offsetY;
+    var centerX = (viewBox[2] + viewBox[0]) / 2;
+    var centerY = (viewBox[3] + viewBox[1]) / 2;
+    var rotateA, rotateB, rotateC, rotateD;
+    rotation = rotation % 360;
+    rotation = rotation < 0 ? rotation + 360 : rotation;
+
+    switch (rotation) {
+      case 180:
+        rotateA = -1;
+        rotateB = 0;
+        rotateC = 0;
+        rotateD = 1;
+        break;
+
+      case 90:
+        rotateA = 0;
+        rotateB = 1;
+        rotateC = 1;
+        rotateD = 0;
+        break;
+
+      case 270:
+        rotateA = 0;
+        rotateB = -1;
+        rotateC = -1;
+        rotateD = 0;
+        break;
+
+      default:
+        rotateA = 1;
+        rotateB = 0;
+        rotateC = 0;
+        rotateD = -1;
+        break;
+    }
+
+    if (dontFlip) {
+      rotateC = -rotateC;
+      rotateD = -rotateD;
+    }
+
+    var offsetCanvasX, offsetCanvasY;
+    var width, height;
+
+    if (rotateA === 0) {
+      offsetCanvasX = Math.abs(centerY - viewBox[1]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerX - viewBox[0]) * scale + offsetY;
+      width = Math.abs(viewBox[3] - viewBox[1]) * scale;
+      height = Math.abs(viewBox[2] - viewBox[0]) * scale;
+    } else {
+      offsetCanvasX = Math.abs(centerX - viewBox[0]) * scale + offsetX;
+      offsetCanvasY = Math.abs(centerY - viewBox[1]) * scale + offsetY;
+      width = Math.abs(viewBox[2] - viewBox[0]) * scale;
+      height = Math.abs(viewBox[3] - viewBox[1]) * scale;
+    }
+
+    this.transform = [rotateA * scale, rotateB * scale, rotateC * scale, rotateD * scale, offsetCanvasX - rotateA * scale * centerX - rotateC * scale * centerY, offsetCanvasY - rotateB * scale * centerX - rotateD * scale * centerY];
+    this.width = width;
+    this.height = height;
+  }
+
+  _createClass(PageViewport, [{
+    key: "clone",
+    value: function clone() {
+      var _ref6 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+          _ref6$scale = _ref6.scale,
+          scale = _ref6$scale === void 0 ? this.scale : _ref6$scale,
+          _ref6$rotation = _ref6.rotation,
+          rotation = _ref6$rotation === void 0 ? this.rotation : _ref6$rotation,
+          _ref6$dontFlip = _ref6.dontFlip,
+          dontFlip = _ref6$dontFlip === void 0 ? false : _ref6$dontFlip;
+
+      return new PageViewport({
+        viewBox: this.viewBox.slice(),
+        scale: scale,
+        rotation: rotation,
+        offsetX: this.offsetX,
+        offsetY: this.offsetY,
+        dontFlip: dontFlip
+      });
+    }
+  }, {
+    key: "convertToViewportPoint",
+    value: function convertToViewportPoint(x, y) {
+      return _util.Util.applyTransform([x, y], this.transform);
+    }
+  }, {
+    key: "convertToViewportRectangle",
+    value: function convertToViewportRectangle(rect) {
+      var topLeft = _util.Util.applyTransform([rect[0], rect[1]], this.transform);
+
+      var bottomRight = _util.Util.applyTransform([rect[2], rect[3]], this.transform);
+
+      return [topLeft[0], topLeft[1], bottomRight[0], bottomRight[1]];
+    }
+  }, {
+    key: "convertToPdfPoint",
+    value: function convertToPdfPoint(x, y) {
+      return _util.Util.applyInverseTransform([x, y], this.transform);
+    }
+  }]);
+
+  return PageViewport;
+}();
+
+exports.PageViewport = PageViewport;
+
+var RenderingCancelledException = function RenderingCancelledException() {
+  function RenderingCancelledException(msg, type) {
+    this.message = msg;
+    this.type = type;
+  }
+
+  RenderingCancelledException.prototype = new Error();
+  RenderingCancelledException.prototype.name = 'RenderingCancelledException';
+  RenderingCancelledException.constructor = RenderingCancelledException;
+  return RenderingCancelledException;
+}();
+
+exports.RenderingCancelledException = RenderingCancelledException;
+var LinkTarget = {
+  NONE: 0,
+  SELF: 1,
+  BLANK: 2,
+  PARENT: 3,
+  TOP: 4
+};
+exports.LinkTarget = LinkTarget;
+var LinkTargetStringMap = ['', '_self', '_blank', '_parent', '_top'];
+
+function addLinkAttributes(link) {
+  var _ref7 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+      url = _ref7.url,
+      target = _ref7.target,
+      rel = _ref7.rel;
+
+  link.href = link.title = url ? (0, _util.removeNullCharacters)(url) : '';
+
+  if (url) {
+    var LinkTargetValues = Object.values(LinkTarget);
+    var targetIndex = LinkTargetValues.includes(target) ? target : LinkTarget.NONE;
+    link.target = LinkTargetStringMap[targetIndex];
+    link.rel = typeof rel === 'string' ? rel : DEFAULT_LINK_REL;
+  }
+}
+
+function getFilenameFromUrl(url) {
+  var anchor = url.indexOf('#');
+  var query = url.indexOf('?');
+  var end = Math.min(anchor > 0 ? anchor : url.length, query > 0 ? query : url.length);
+  return url.substring(url.lastIndexOf('/', end) + 1, end);
+}
+
+var StatTimer =
+/*#__PURE__*/
+function () {
+  function StatTimer() {
+    var enable = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
+
+    _classCallCheck(this, StatTimer);
+
+    this.enabled = !!enable;
+    this.started = Object.create(null);
+    this.times = [];
+  }
+
+  _createClass(StatTimer, [{
+    key: "time",
+    value: function time(name) {
+      if (!this.enabled) {
+        return;
+      }
+
+      if (name in this.started) {
+        (0, _util.warn)('Timer is already running for ' + name);
+      }
+
+      this.started[name] = Date.now();
+    }
+  }, {
+    key: "timeEnd",
+    value: function timeEnd(name) {
+      if (!this.enabled) {
+        return;
+      }
+
+      if (!(name in this.started)) {
+        (0, _util.warn)('Timer has not been started for ' + name);
+      }
+
+      this.times.push({
+        'name': name,
+        'start': this.started[name],
+        'end': Date.now()
+      });
+      delete this.started[name];
+    }
+  }, {
+    key: "toString",
+    value: function toString() {
+      var out = '',
+          longest = 0;
+      var _iteratorNormalCompletion = true;
+      var _didIteratorError = false;
+      var _iteratorError = undefined;
+
+      try {
+        for (var _iterator = this.times[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+          var time = _step.value;
+          var name = time.name;
+
+          if (name.length > longest) {
+            longest = name.length;
+          }
+        }
+      } catch (err) {
+        _didIteratorError = true;
+        _iteratorError = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+            _iterator["return"]();
+          }
+        } finally {
+          if (_didIteratorError) {
+            throw _iteratorError;
+          }
+        }
+      }
+
+      var _iteratorNormalCompletion2 = true;
+      var _didIteratorError2 = false;
+      var _iteratorError2 = undefined;
+
+      try {
+        for (var _iterator2 = this.times[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+          var _time = _step2.value;
+          var duration = _time.end - _time.start;
+          out += "".concat(_time.name.padEnd(longest), " ").concat(duration, "ms\n");
+        }
+      } catch (err) {
+        _didIteratorError2 = true;
+        _iteratorError2 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
+            _iterator2["return"]();
+          }
+        } finally {
+          if (_didIteratorError2) {
+            throw _iteratorError2;
+          }
+        }
+      }
+
+      return out;
+    }
+  }]);
+
+  return StatTimer;
+}();
+
+exports.StatTimer = StatTimer;
+
+var DummyStatTimer =
+/*#__PURE__*/
+function () {
+  function DummyStatTimer() {
+    _classCallCheck(this, DummyStatTimer);
+
+    (0, _util.unreachable)('Cannot initialize DummyStatTimer.');
+  }
+
+  _createClass(DummyStatTimer, null, [{
+    key: "time",
+    value: function time(name) {}
+  }, {
+    key: "timeEnd",
+    value: function timeEnd(name) {}
+  }, {
+    key: "toString",
+    value: function toString() {
+      return '';
+    }
+  }]);
+
+  return DummyStatTimer;
+}();
+
+exports.DummyStatTimer = DummyStatTimer;
+
+function isFetchSupported() {
+  return typeof fetch !== 'undefined' && typeof Response !== 'undefined' && 'body' in Response.prototype && typeof ReadableStream !== 'undefined';
+}
+
+function isValidFetchUrl(url, baseUrl) {
+  try {
+    var _ref8 = baseUrl ? new _util.URL(url, baseUrl) : new _util.URL(url),
+        protocol = _ref8.protocol;
+
+    return protocol === 'http:' || protocol === 'https:';
+  } catch (ex) {
+    return false;
+  }
+}
+
+function loadScript(src) {
+  return new Promise(function (resolve, reject) {
+    var script = document.createElement('script');
+    script.src = src;
+    script.onload = resolve;
+
+    script.onerror = function () {
+      reject(new Error("Cannot load script at: ".concat(script.src)));
+    };
+
+    (document.head || document.documentElement).appendChild(script);
+  });
+}
+
+function deprecated(details) {
+  console.log('Deprecated API usage: ' + details);
+}
+
+function releaseImageResources(img) {
+  (0, _util.assert)(img instanceof Image, 'Invalid `img` parameter.');
+  var url = img.src;
+
+  if (typeof url === 'string' && url.startsWith('blob:') && _util.URL.revokeObjectURL) {
+    _util.URL.revokeObjectURL(url);
+  }
+
+  img.removeAttribute('src');
+}
+
+var pdfDateStringRegex;
+
+var PDFDateString =
+/*#__PURE__*/
+function () {
+  function PDFDateString() {
+    _classCallCheck(this, PDFDateString);
+  }
+
+  _createClass(PDFDateString, null, [{
+    key: "toDateObject",
+    value: function toDateObject(input) {
+      if (!input || !(0, _util.isString)(input)) {
+        return null;
+      }
+
+      if (!pdfDateStringRegex) {
+        pdfDateStringRegex = new RegExp('^D:' + '(\\d{4})' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '(\\d{2})?' + '([Z|+|-])?' + '(\\d{2})?' + '\'?' + '(\\d{2})?' + '\'?');
+      }
+
+      var matches = pdfDateStringRegex.exec(input);
+
+      if (!matches) {
+        return null;
+      }
+
+      var year = parseInt(matches[1], 10);
+      var month = parseInt(matches[2], 10);
+      month = month >= 1 && month <= 12 ? month - 1 : 0;
+      var day = parseInt(matches[3], 10);
+      day = day >= 1 && day <= 31 ? day : 1;
+      var hour = parseInt(matches[4], 10);
+      hour = hour >= 0 && hour <= 23 ? hour : 0;
+      var minute = parseInt(matches[5], 10);
+      minute = minute >= 0 && minute <= 59 ? minute : 0;
+      var second = parseInt(matches[6], 10);
+      second = second >= 0 && second <= 59 ? second : 0;
+      var universalTimeRelation = matches[7] || 'Z';
+      var offsetHour = parseInt(matches[8], 10);
+      offsetHour = offsetHour >= 0 && offsetHour <= 23 ? offsetHour : 0;
+      var offsetMinute = parseInt(matches[9], 10) || 0;
+      offsetMinute = offsetMinute >= 0 && offsetMinute <= 59 ? offsetMinute : 0;
+
+      if (universalTimeRelation === '-') {
+        hour += offsetHour;
+        minute += offsetMinute;
+      } else if (universalTimeRelation === '+') {
+        hour -= offsetHour;
+        minute -= offsetMinute;
+      }
+
+      return new Date(Date.UTC(year, month, day, hour, minute, second));
+    }
+  }]);
+
+  return PDFDateString;
+}();
+
+exports.PDFDateString = PDFDateString;
+
+/***/ }),
+/* 152 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.FontLoader = exports.FontFaceObject = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var BaseFontLoader =
+/*#__PURE__*/
+function () {
+  function BaseFontLoader(_ref) {
+    var docId = _ref.docId,
+        onUnsupportedFeature = _ref.onUnsupportedFeature;
+
+    _classCallCheck(this, BaseFontLoader);
+
+    if (this.constructor === BaseFontLoader) {
+      (0, _util.unreachable)('Cannot initialize BaseFontLoader.');
+    }
+
+    this.docId = docId;
+    this._onUnsupportedFeature = onUnsupportedFeature;
+    this.nativeFontFaces = [];
+    this.styleElement = null;
+  }
+
+  _createClass(BaseFontLoader, [{
+    key: "addNativeFontFace",
+    value: function addNativeFontFace(nativeFontFace) {
+      this.nativeFontFaces.push(nativeFontFace);
+      document.fonts.add(nativeFontFace);
+    }
+  }, {
+    key: "insertRule",
+    value: function insertRule(rule) {
+      var styleElement = this.styleElement;
+
+      if (!styleElement) {
+        styleElement = this.styleElement = document.createElement('style');
+        styleElement.id = "PDFJS_FONT_STYLE_TAG_".concat(this.docId);
+        document.documentElement.getElementsByTagName('head')[0].appendChild(styleElement);
+      }
+
+      var styleSheet = styleElement.sheet;
+      styleSheet.insertRule(rule, styleSheet.cssRules.length);
+    }
+  }, {
+    key: "clear",
+    value: function clear() {
+      this.nativeFontFaces.forEach(function (nativeFontFace) {
+        document.fonts["delete"](nativeFontFace);
+      });
+      this.nativeFontFaces.length = 0;
+
+      if (this.styleElement) {
+        this.styleElement.remove();
+        this.styleElement = null;
+      }
+    }
+  }, {
+    key: "bind",
+    value: function () {
+      var _bind = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee(font) {
+        var _this = this;
+
+        var nativeFontFace, rule;
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                if (!(font.attached || font.missingFile)) {
+                  _context.next = 2;
+                  break;
+                }
+
+                return _context.abrupt("return", undefined);
+
+              case 2:
+                font.attached = true;
+
+                if (!this.isFontLoadingAPISupported) {
+                  _context.next = 19;
+                  break;
+                }
+
+                nativeFontFace = font.createNativeFontFace();
+
+                if (!nativeFontFace) {
+                  _context.next = 18;
+                  break;
+                }
+
+                this.addNativeFontFace(nativeFontFace);
+                _context.prev = 7;
+                _context.next = 10;
+                return nativeFontFace.loaded;
+
+              case 10:
+                _context.next = 18;
+                break;
+
+              case 12:
+                _context.prev = 12;
+                _context.t0 = _context["catch"](7);
+
+                this._onUnsupportedFeature({
+                  featureId: _util.UNSUPPORTED_FEATURES.font
+                });
+
+                (0, _util.warn)("Failed to load font '".concat(nativeFontFace.family, "': '").concat(_context.t0, "'."));
+                font.disableFontFace = true;
+                throw _context.t0;
+
+              case 18:
+                return _context.abrupt("return", undefined);
+
+              case 19:
+                rule = font.createFontFaceRule();
+
+                if (!rule) {
+                  _context.next = 25;
+                  break;
+                }
+
+                this.insertRule(rule);
+
+                if (!this.isSyncFontLoadingSupported) {
+                  _context.next = 24;
+                  break;
+                }
+
+                return _context.abrupt("return", undefined);
+
+              case 24:
+                return _context.abrupt("return", new Promise(function (resolve) {
+                  var request = _this._queueLoadingCallback(resolve);
+
+                  _this._prepareFontLoadEvent([rule], [font], request);
+                }));
+
+              case 25:
+                return _context.abrupt("return", undefined);
+
+              case 26:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this, [[7, 12]]);
+      }));
+
+      function bind(_x) {
+        return _bind.apply(this, arguments);
+      }
+
+      return bind;
+    }()
+  }, {
+    key: "_queueLoadingCallback",
+    value: function _queueLoadingCallback(callback) {
+      (0, _util.unreachable)('Abstract method `_queueLoadingCallback`.');
+    }
+  }, {
+    key: "_prepareFontLoadEvent",
+    value: function _prepareFontLoadEvent(rules, fontsToLoad, request) {
+      (0, _util.unreachable)('Abstract method `_prepareFontLoadEvent`.');
+    }
+  }, {
+    key: "isFontLoadingAPISupported",
+    get: function get() {
+      (0, _util.unreachable)('Abstract method `isFontLoadingAPISupported`.');
+    }
+  }, {
+    key: "isSyncFontLoadingSupported",
+    get: function get() {
+      (0, _util.unreachable)('Abstract method `isSyncFontLoadingSupported`.');
+    }
+  }, {
+    key: "_loadTestFont",
+    get: function get() {
+      (0, _util.unreachable)('Abstract method `_loadTestFont`.');
+    }
+  }]);
+
+  return BaseFontLoader;
+}();
+
+var FontLoader;
+exports.FontLoader = FontLoader;
+{
+  exports.FontLoader = FontLoader =
+  /*#__PURE__*/
+  function (_BaseFontLoader) {
+    _inherits(GenericFontLoader, _BaseFontLoader);
+
+    function GenericFontLoader(docId) {
+      var _this2;
+
+      _classCallCheck(this, GenericFontLoader);
+
+      _this2 = _possibleConstructorReturn(this, _getPrototypeOf(GenericFontLoader).call(this, docId));
+      _this2.loadingContext = {
+        requests: [],
+        nextRequestId: 0
+      };
+      _this2.loadTestFontId = 0;
+      return _this2;
+    }
+
+    _createClass(GenericFontLoader, [{
+      key: "_queueLoadingCallback",
+      value: function _queueLoadingCallback(callback) {
+        function completeRequest() {
+          (0, _util.assert)(!request.done, 'completeRequest() cannot be called twice.');
+          request.done = true;
+
+          while (context.requests.length > 0 && context.requests[0].done) {
+            var otherRequest = context.requests.shift();
+            setTimeout(otherRequest.callback, 0);
+          }
+        }
+
+        var context = this.loadingContext;
+        var request = {
+          id: "pdfjs-font-loading-".concat(context.nextRequestId++),
+          done: false,
+          complete: completeRequest,
+          callback: callback
+        };
+        context.requests.push(request);
+        return request;
+      }
+    }, {
+      key: "_prepareFontLoadEvent",
+      value: function _prepareFontLoadEvent(rules, fonts, request) {
+        function int32(data, offset) {
+          return data.charCodeAt(offset) << 24 | data.charCodeAt(offset + 1) << 16 | data.charCodeAt(offset + 2) << 8 | data.charCodeAt(offset + 3) & 0xff;
+        }
+
+        function spliceString(s, offset, remove, insert) {
+          var chunk1 = s.substring(0, offset);
+          var chunk2 = s.substring(offset + remove);
+          return chunk1 + insert + chunk2;
+        }
+
+        var i, ii;
+        var canvas = document.createElement('canvas');
+        canvas.width = 1;
+        canvas.height = 1;
+        var ctx = canvas.getContext('2d');
+        var called = 0;
+
+        function isFontReady(name, callback) {
+          called++;
+
+          if (called > 30) {
+            (0, _util.warn)('Load test font never loaded.');
+            callback();
+            return;
+          }
+
+          ctx.font = '30px ' + name;
+          ctx.fillText('.', 0, 20);
+          var imageData = ctx.getImageData(0, 0, 1, 1);
+
+          if (imageData.data[3] > 0) {
+            callback();
+            return;
+          }
+
+          setTimeout(isFontReady.bind(null, name, callback));
+        }
+
+        var loadTestFontId = "lt".concat(Date.now()).concat(this.loadTestFontId++);
+        var data = this._loadTestFont;
+        var COMMENT_OFFSET = 976;
+        data = spliceString(data, COMMENT_OFFSET, loadTestFontId.length, loadTestFontId);
+        var CFF_CHECKSUM_OFFSET = 16;
+        var XXXX_VALUE = 0x58585858;
+        var checksum = int32(data, CFF_CHECKSUM_OFFSET);
+
+        for (i = 0, ii = loadTestFontId.length - 3; i < ii; i += 4) {
+          checksum = checksum - XXXX_VALUE + int32(loadTestFontId, i) | 0;
+        }
+
+        if (i < loadTestFontId.length) {
+          checksum = checksum - XXXX_VALUE + int32(loadTestFontId + 'XXX', i) | 0;
+        }
+
+        data = spliceString(data, CFF_CHECKSUM_OFFSET, 4, (0, _util.string32)(checksum));
+        var url = "url(data:font/opentype;base64,".concat(btoa(data), ");");
+        var rule = "@font-face {font-family:\"".concat(loadTestFontId, "\";src:").concat(url, "}");
+        this.insertRule(rule);
+        var names = [];
+
+        for (i = 0, ii = fonts.length; i < ii; i++) {
+          names.push(fonts[i].loadedName);
+        }
+
+        names.push(loadTestFontId);
+        var div = document.createElement('div');
+        div.setAttribute('style', 'visibility: hidden;' + 'width: 10px; height: 10px;' + 'position: absolute; top: 0px; left: 0px;');
+
+        for (i = 0, ii = names.length; i < ii; ++i) {
+          var span = document.createElement('span');
+          span.textContent = 'Hi';
+          span.style.fontFamily = names[i];
+          div.appendChild(span);
+        }
+
+        document.body.appendChild(div);
+        isFontReady(loadTestFontId, function () {
+          document.body.removeChild(div);
+          request.complete();
+        });
+      }
+    }, {
+      key: "isFontLoadingAPISupported",
+      get: function get() {
+        var supported = typeof document !== 'undefined' && !!document.fonts;
+
+        if (supported && typeof navigator !== 'undefined') {
+          var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
+
+          if (m && m[1] < 63) {
+            supported = false;
+          }
+        }
+
+        return (0, _util.shadow)(this, 'isFontLoadingAPISupported', supported);
+      }
+    }, {
+      key: "isSyncFontLoadingSupported",
+      get: function get() {
+        var supported = false;
+
+        if (typeof navigator === 'undefined') {
+          supported = true;
+        } else {
+          var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(navigator.userAgent);
+
+          if (m && m[1] >= 14) {
+            supported = true;
+          }
+        }
+
+        return (0, _util.shadow)(this, 'isSyncFontLoadingSupported', supported);
+      }
+    }, {
+      key: "_loadTestFont",
+      get: function get() {
+        var getLoadTestFont = function getLoadTestFont() {
+          return atob('T1RUTwALAIAAAwAwQ0ZGIDHtZg4AAAOYAAAAgUZGVE1lkzZwAAAEHAAAABxHREVGABQA' + 'FQAABDgAAAAeT1MvMlYNYwkAAAEgAAAAYGNtYXABDQLUAAACNAAAAUJoZWFk/xVFDQAA' + 'ALwAAAA2aGhlYQdkA+oAAAD0AAAAJGhtdHgD6AAAAAAEWAAAAAZtYXhwAAJQAAAAARgA' + 'AAAGbmFtZVjmdH4AAAGAAAAAsXBvc3T/hgAzAAADeAAAACAAAQAAAAEAALZRFsRfDzz1' + 'AAsD6AAAAADOBOTLAAAAAM4KHDwAAAAAA+gDIQAAAAgAAgAAAAAAAAABAAADIQAAAFoD' + '6AAAAAAD6AABAAAAAAAAAAAAAAAAAAAAAQAAUAAAAgAAAAQD6AH0AAUAAAKKArwAAACM' + 'AooCvAAAAeAAMQECAAACAAYJAAAAAAAAAAAAAQAAAAAAAAAAAAAAAFBmRWQAwAAuAC4D' + 'IP84AFoDIQAAAAAAAQAAAAAAAAAAACAAIAABAAAADgCuAAEAAAAAAAAAAQAAAAEAAAAA' + 'AAEAAQAAAAEAAAAAAAIAAQAAAAEAAAAAAAMAAQAAAAEAAAAAAAQAAQAAAAEAAAAAAAUA' + 'AQAAAAEAAAAAAAYAAQAAAAMAAQQJAAAAAgABAAMAAQQJAAEAAgABAAMAAQQJAAIAAgAB' + 'AAMAAQQJAAMAAgABAAMAAQQJAAQAAgABAAMAAQQJAAUAAgABAAMAAQQJAAYAAgABWABY' + 'AAAAAAAAAwAAAAMAAAAcAAEAAAAAADwAAwABAAAAHAAEACAAAAAEAAQAAQAAAC7//wAA' + 'AC7////TAAEAAAAAAAABBgAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' + 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAAAAAD/gwAyAAAAAQAAAAAAAAAAAAAAAAAA' + 'AAABAAQEAAEBAQJYAAEBASH4DwD4GwHEAvgcA/gXBIwMAYuL+nz5tQXkD5j3CBLnEQAC' + 'AQEBIVhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYAAABAQAADwACAQEEE/t3' + 'Dov6fAH6fAT+fPp8+nwHDosMCvm1Cvm1DAz6fBQAAAAAAAABAAAAAMmJbzEAAAAAzgTj' + 'FQAAAADOBOQpAAEAAAAAAAAADAAUAAQAAAABAAAAAgABAAAAAAAAAAAD6AAAAAAAAA==');
+        };
+
+        return (0, _util.shadow)(this, '_loadTestFont', getLoadTestFont());
+      }
+    }]);
+
+    return GenericFontLoader;
+  }(BaseFontLoader);
+}
+var IsEvalSupportedCached = {
+  get value() {
+    return (0, _util.shadow)(this, 'value', (0, _util.isEvalSupported)());
+  }
+
+};
+
+var FontFaceObject =
+/*#__PURE__*/
+function () {
+  function FontFaceObject(translatedData, _ref2) {
+    var _ref2$isEvalSupported = _ref2.isEvalSupported,
+        isEvalSupported = _ref2$isEvalSupported === void 0 ? true : _ref2$isEvalSupported,
+        _ref2$disableFontFace = _ref2.disableFontFace,
+        disableFontFace = _ref2$disableFontFace === void 0 ? false : _ref2$disableFontFace,
+        _ref2$ignoreErrors = _ref2.ignoreErrors,
+        ignoreErrors = _ref2$ignoreErrors === void 0 ? false : _ref2$ignoreErrors,
+        _ref2$onUnsupportedFe = _ref2.onUnsupportedFeature,
+        onUnsupportedFeature = _ref2$onUnsupportedFe === void 0 ? null : _ref2$onUnsupportedFe,
+        _ref2$fontRegistry = _ref2.fontRegistry,
+        fontRegistry = _ref2$fontRegistry === void 0 ? null : _ref2$fontRegistry;
+
+    _classCallCheck(this, FontFaceObject);
+
+    this.compiledGlyphs = Object.create(null);
+
+    for (var i in translatedData) {
+      this[i] = translatedData[i];
+    }
+
+    this.isEvalSupported = isEvalSupported !== false;
+    this.disableFontFace = disableFontFace === true;
+    this.ignoreErrors = ignoreErrors === true;
+    this._onUnsupportedFeature = onUnsupportedFeature;
+    this.fontRegistry = fontRegistry;
+  }
+
+  _createClass(FontFaceObject, [{
+    key: "createNativeFontFace",
+    value: function createNativeFontFace() {
+      if (!this.data || this.disableFontFace) {
+        return null;
+      }
+
+      var nativeFontFace = new FontFace(this.loadedName, this.data, {});
+
+      if (this.fontRegistry) {
+        this.fontRegistry.registerFont(this);
+      }
+
+      return nativeFontFace;
+    }
+  }, {
+    key: "createFontFaceRule",
+    value: function createFontFaceRule() {
+      if (!this.data || this.disableFontFace) {
+        return null;
+      }
+
+      var data = (0, _util.bytesToString)(new Uint8Array(this.data));
+      var url = "url(data:".concat(this.mimetype, ";base64,").concat(btoa(data), ");");
+      var rule = "@font-face {font-family:\"".concat(this.loadedName, "\";src:").concat(url, "}");
+
+      if (this.fontRegistry) {
+        this.fontRegistry.registerFont(this, url);
+      }
+
+      return rule;
+    }
+  }, {
+    key: "getPathGenerator",
+    value: function getPathGenerator(objs, character) {
+      if (this.compiledGlyphs[character] !== undefined) {
+        return this.compiledGlyphs[character];
+      }
+
+      var cmds, current;
+
+      try {
+        cmds = objs.get(this.loadedName + '_path_' + character);
+      } catch (ex) {
+        if (!this.ignoreErrors) {
+          throw ex;
+        }
+
+        if (this._onUnsupportedFeature) {
+          this._onUnsupportedFeature({
+            featureId: _util.UNSUPPORTED_FEATURES.font
+          });
+        }
+
+        (0, _util.warn)("getPathGenerator - ignoring character: \"".concat(ex, "\"."));
+        return this.compiledGlyphs[character] = function (c, size) {};
+      }
+
+      if (this.isEvalSupported && IsEvalSupportedCached.value) {
+        var args,
+            js = '';
+
+        for (var i = 0, ii = cmds.length; i < ii; i++) {
+          current = cmds[i];
+
+          if (current.args !== undefined) {
+            args = current.args.join(',');
+          } else {
+            args = '';
+          }
+
+          js += 'c.' + current.cmd + '(' + args + ');\n';
+        }
+
+        return this.compiledGlyphs[character] = new Function('c', 'size', js);
+      }
+
+      return this.compiledGlyphs[character] = function (c, size) {
+        for (var _i = 0, _ii = cmds.length; _i < _ii; _i++) {
+          current = cmds[_i];
+
+          if (current.cmd === 'scale') {
+            current.args = [size, -size];
+          }
+
+          c[current.cmd].apply(c, current.args);
+        }
+      };
+    }
+  }]);
+
+  return FontFaceObject;
+}();
+
+exports.FontFaceObject = FontFaceObject;
+
+/***/ }),
+/* 153 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var compatibilityParams = Object.create(null);
+{
+  var isNodeJS = __w_pdfjs_require__(4);
+
+  var userAgent = typeof navigator !== 'undefined' && navigator.userAgent || '';
+  var isIE = /Trident/.test(userAgent);
+  var isIOSChrome = /CriOS/.test(userAgent);
+
+  (function checkOnBlobSupport() {
+    if (isIE || isIOSChrome) {
+      compatibilityParams.disableCreateObjectURL = true;
+    }
+  })();
+
+  (function checkFontFaceAndImage() {
+    if (isNodeJS()) {
+      compatibilityParams.disableFontFace = true;
+      compatibilityParams.nativeImageDecoderSupport = 'none';
+    }
+  })();
+}
+exports.apiCompatibilityParams = Object.freeze(compatibilityParams);
+
+/***/ }),
+/* 154 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.CanvasGraphics = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+var _pattern_helper = __w_pdfjs_require__(155);
+
+var MIN_FONT_SIZE = 16;
+var MAX_FONT_SIZE = 100;
+var MAX_GROUP_SIZE = 4096;
+var MIN_WIDTH_FACTOR = 0.65;
+var COMPILE_TYPE3_GLYPHS = true;
+var MAX_SIZE_TO_COMPILE = 1000;
+var FULL_CHUNK_HEIGHT = 16;
+var IsLittleEndianCached = {
+  get value() {
+    return (0, _util.shadow)(IsLittleEndianCached, 'value', (0, _util.isLittleEndian)());
+  }
+
+};
+
+function addContextCurrentTransform(ctx) {
+  if (!ctx.mozCurrentTransform) {
+    ctx._originalSave = ctx.save;
+    ctx._originalRestore = ctx.restore;
+    ctx._originalRotate = ctx.rotate;
+    ctx._originalScale = ctx.scale;
+    ctx._originalTranslate = ctx.translate;
+    ctx._originalTransform = ctx.transform;
+    ctx._originalSetTransform = ctx.setTransform;
+    ctx._transformMatrix = ctx._transformMatrix || [1, 0, 0, 1, 0, 0];
+    ctx._transformStack = [];
+    Object.defineProperty(ctx, 'mozCurrentTransform', {
+      get: function getCurrentTransform() {
+        return this._transformMatrix;
+      }
+    });
+    Object.defineProperty(ctx, 'mozCurrentTransformInverse', {
+      get: function getCurrentTransformInverse() {
+        var m = this._transformMatrix;
+        var a = m[0],
+            b = m[1],
+            c = m[2],
+            d = m[3],
+            e = m[4],
+            f = m[5];
+        var ad_bc = a * d - b * c;
+        var bc_ad = b * c - a * d;
+        return [d / ad_bc, b / bc_ad, c / bc_ad, a / ad_bc, (d * e - c * f) / bc_ad, (b * e - a * f) / ad_bc];
+      }
+    });
+
+    ctx.save = function ctxSave() {
+      var old = this._transformMatrix;
+
+      this._transformStack.push(old);
+
+      this._transformMatrix = old.slice(0, 6);
+
+      this._originalSave();
+    };
+
+    ctx.restore = function ctxRestore() {
+      var prev = this._transformStack.pop();
+
+      if (prev) {
+        this._transformMatrix = prev;
+
+        this._originalRestore();
+      }
+    };
+
+    ctx.translate = function ctxTranslate(x, y) {
+      var m = this._transformMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+
+      this._originalTranslate(x, y);
+    };
+
+    ctx.scale = function ctxScale(x, y) {
+      var m = this._transformMatrix;
+      m[0] = m[0] * x;
+      m[1] = m[1] * x;
+      m[2] = m[2] * y;
+      m[3] = m[3] * y;
+
+      this._originalScale(x, y);
+    };
+
+    ctx.transform = function ctxTransform(a, b, c, d, e, f) {
+      var m = this._transformMatrix;
+      this._transformMatrix = [m[0] * a + m[2] * b, m[1] * a + m[3] * b, m[0] * c + m[2] * d, m[1] * c + m[3] * d, m[0] * e + m[2] * f + m[4], m[1] * e + m[3] * f + m[5]];
+
+      ctx._originalTransform(a, b, c, d, e, f);
+    };
+
+    ctx.setTransform = function ctxSetTransform(a, b, c, d, e, f) {
+      this._transformMatrix = [a, b, c, d, e, f];
+
+      ctx._originalSetTransform(a, b, c, d, e, f);
+    };
+
+    ctx.rotate = function ctxRotate(angle) {
+      var cosValue = Math.cos(angle);
+      var sinValue = Math.sin(angle);
+      var m = this._transformMatrix;
+      this._transformMatrix = [m[0] * cosValue + m[2] * sinValue, m[1] * cosValue + m[3] * sinValue, m[0] * -sinValue + m[2] * cosValue, m[1] * -sinValue + m[3] * cosValue, m[4], m[5]];
+
+      this._originalRotate(angle);
+    };
+  }
+}
+
+var CachedCanvases = function CachedCanvasesClosure() {
+  function CachedCanvases(canvasFactory) {
+    this.canvasFactory = canvasFactory;
+    this.cache = Object.create(null);
+  }
+
+  CachedCanvases.prototype = {
+    getCanvas: function CachedCanvases_getCanvas(id, width, height, trackTransform) {
+      var canvasEntry;
+
+      if (this.cache[id] !== undefined) {
+        canvasEntry = this.cache[id];
+        this.canvasFactory.reset(canvasEntry, width, height);
+        canvasEntry.context.setTransform(1, 0, 0, 1, 0, 0);
+      } else {
+        canvasEntry = this.canvasFactory.create(width, height);
+        this.cache[id] = canvasEntry;
+      }
+
+      if (trackTransform) {
+        addContextCurrentTransform(canvasEntry.context);
+      }
+
+      return canvasEntry;
+    },
+    clear: function clear() {
+      for (var id in this.cache) {
+        var canvasEntry = this.cache[id];
+        this.canvasFactory.destroy(canvasEntry);
+        delete this.cache[id];
+      }
+    }
+  };
+  return CachedCanvases;
+}();
+
+function compileType3Glyph(imgData) {
+  var POINT_TO_PROCESS_LIMIT = 1000;
+  var width = imgData.width,
+      height = imgData.height;
+  var i,
+      j,
+      j0,
+      width1 = width + 1;
+  var points = new Uint8Array(width1 * (height + 1));
+  var POINT_TYPES = new Uint8Array([0, 2, 4, 0, 1, 0, 5, 4, 8, 10, 0, 8, 0, 2, 1, 0]);
+  var lineSize = width + 7 & ~7,
+      data0 = imgData.data;
+  var data = new Uint8Array(lineSize * height),
+      pos = 0,
+      ii;
+
+  for (i = 0, ii = data0.length; i < ii; i++) {
+    var mask = 128,
+        elem = data0[i];
+
+    while (mask > 0) {
+      data[pos++] = elem & mask ? 0 : 255;
+      mask >>= 1;
+    }
+  }
+
+  var count = 0;
+  pos = 0;
+
+  if (data[pos] !== 0) {
+    points[0] = 1;
+    ++count;
+  }
+
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j] = data[pos] ? 2 : 1;
+      ++count;
+    }
+
+    pos++;
+  }
+
+  if (data[pos] !== 0) {
+    points[j] = 2;
+    ++count;
+  }
+
+  for (i = 1; i < height; i++) {
+    pos = i * lineSize;
+    j0 = i * width1;
+
+    if (data[pos - lineSize] !== data[pos]) {
+      points[j0] = data[pos] ? 1 : 8;
+      ++count;
+    }
+
+    var sum = (data[pos] ? 4 : 0) + (data[pos - lineSize] ? 8 : 0);
+
+    for (j = 1; j < width; j++) {
+      sum = (sum >> 2) + (data[pos + 1] ? 4 : 0) + (data[pos - lineSize + 1] ? 8 : 0);
+
+      if (POINT_TYPES[sum]) {
+        points[j0 + j] = POINT_TYPES[sum];
+        ++count;
+      }
+
+      pos++;
+    }
+
+    if (data[pos - lineSize] !== data[pos]) {
+      points[j0 + j] = data[pos] ? 2 : 4;
+      ++count;
+    }
+
+    if (count > POINT_TO_PROCESS_LIMIT) {
+      return null;
+    }
+  }
+
+  pos = lineSize * (height - 1);
+  j0 = i * width1;
+
+  if (data[pos] !== 0) {
+    points[j0] = 8;
+    ++count;
+  }
+
+  for (j = 1; j < width; j++) {
+    if (data[pos] !== data[pos + 1]) {
+      points[j0 + j] = data[pos] ? 4 : 8;
+      ++count;
+    }
+
+    pos++;
+  }
+
+  if (data[pos] !== 0) {
+    points[j0 + j] = 4;
+    ++count;
+  }
+
+  if (count > POINT_TO_PROCESS_LIMIT) {
+    return null;
+  }
+
+  var steps = new Int32Array([0, width1, -1, 0, -width1, 0, 0, 0, 1]);
+  var outlines = [];
+
+  for (i = 0; count && i <= height; i++) {
+    var p = i * width1;
+    var end = p + width;
+
+    while (p < end && !points[p]) {
+      p++;
+    }
+
+    if (p === end) {
+      continue;
+    }
+
+    var coords = [p % width1, i];
+    var type = points[p],
+        p0 = p,
+        pp;
+
+    do {
+      var step = steps[type];
+
+      do {
+        p += step;
+      } while (!points[p]);
+
+      pp = points[p];
+
+      if (pp !== 5 && pp !== 10) {
+        type = pp;
+        points[p] = 0;
+      } else {
+        type = pp & 0x33 * type >> 4;
+        points[p] &= type >> 2 | type << 2;
+      }
+
+      coords.push(p % width1);
+      coords.push(p / width1 | 0);
+
+      if (!points[p]) {
+        --count;
+      }
+    } while (p0 !== p);
+
+    outlines.push(coords);
+    --i;
+  }
+
+  var drawOutline = function drawOutline(c) {
+    c.save();
+    c.scale(1 / width, -1 / height);
+    c.translate(0, -height);
+    c.beginPath();
+
+    for (var i = 0, ii = outlines.length; i < ii; i++) {
+      var o = outlines[i];
+      c.moveTo(o[0], o[1]);
+
+      for (var j = 2, jj = o.length; j < jj; j += 2) {
+        c.lineTo(o[j], o[j + 1]);
+      }
+    }
+
+    c.fill();
+    c.beginPath();
+    c.restore();
+  };
+
+  return drawOutline;
+}
+
+var CanvasExtraState = function CanvasExtraStateClosure() {
+  function CanvasExtraState() {
+    this.alphaIsShape = false;
+    this.fontSize = 0;
+    this.fontSizeScale = 1;
+    this.textMatrix = _util.IDENTITY_MATRIX;
+    this.textMatrixScale = 1;
+    this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
+    this.leading = 0;
+    this.x = 0;
+    this.y = 0;
+    this.lineX = 0;
+    this.lineY = 0;
+    this.charSpacing = 0;
+    this.wordSpacing = 0;
+    this.textHScale = 1;
+    this.textRenderingMode = _util.TextRenderingMode.FILL;
+    this.textRise = 0;
+    this.fillColor = '#000000';
+    this.strokeColor = '#000000';
+    this.patternFill = false;
+    this.fillAlpha = 1;
+    this.strokeAlpha = 1;
+    this.lineWidth = 1;
+    this.activeSMask = null;
+    this.resumeSMaskCtx = null;
+  }
+
+  CanvasExtraState.prototype = {
+    clone: function CanvasExtraState_clone() {
+      return Object.create(this);
+    },
+    setCurrentPoint: function CanvasExtraState_setCurrentPoint(x, y) {
+      this.x = x;
+      this.y = y;
+    }
+  };
+  return CanvasExtraState;
+}();
+
+var CanvasGraphics = function CanvasGraphicsClosure() {
+  var EXECUTION_TIME = 15;
+  var EXECUTION_STEPS = 10;
+
+  function CanvasGraphics(canvasCtx, commonObjs, objs, canvasFactory, webGLContext, imageLayer) {
+    this.ctx = canvasCtx;
+    this.current = new CanvasExtraState();
+    this.stateStack = [];
+    this.pendingClip = null;
+    this.pendingEOFill = false;
+    this.res = null;
+    this.xobjs = null;
+    this.commonObjs = commonObjs;
+    this.objs = objs;
+    this.canvasFactory = canvasFactory;
+    this.webGLContext = webGLContext;
+    this.imageLayer = imageLayer;
+    this.groupStack = [];
+    this.processingType3 = null;
+    this.baseTransform = null;
+    this.baseTransformStack = [];
+    this.groupLevel = 0;
+    this.smaskStack = [];
+    this.smaskCounter = 0;
+    this.tempSMask = null;
+    this.cachedCanvases = new CachedCanvases(this.canvasFactory);
+
+    if (canvasCtx) {
+      addContextCurrentTransform(canvasCtx);
+    }
+
+    this._cachedGetSinglePixelWidth = null;
+  }
+
+  function putBinaryImageData(ctx, imgData) {
+    if (typeof ImageData !== 'undefined' && imgData instanceof ImageData) {
+      ctx.putImageData(imgData, 0, 0);
+      return;
+    }
+
+    var height = imgData.height,
+        width = imgData.width;
+    var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+    var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+    var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+    var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+    var srcPos = 0,
+        destPos;
+    var src = imgData.data;
+    var dest = chunkImgData.data;
+    var i, j, thisChunkHeight, elemsInThisChunk;
+
+    if (imgData.kind === _util.ImageKind.GRAYSCALE_1BPP) {
+      var srcLength = src.byteLength;
+      var dest32 = new Uint32Array(dest.buffer, 0, dest.byteLength >> 2);
+      var dest32DataLength = dest32.length;
+      var fullSrcDiff = width + 7 >> 3;
+      var white = 0xFFFFFFFF;
+      var black = IsLittleEndianCached.value ? 0xFF000000 : 0x000000FF;
+
+      for (i = 0; i < totalChunks; i++) {
+        thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+        destPos = 0;
+
+        for (j = 0; j < thisChunkHeight; j++) {
+          var srcDiff = srcLength - srcPos;
+          var k = 0;
+          var kEnd = srcDiff > fullSrcDiff ? width : srcDiff * 8 - 7;
+          var kEndUnrolled = kEnd & ~7;
+          var mask = 0;
+          var srcByte = 0;
+
+          for (; k < kEndUnrolled; k += 8) {
+            srcByte = src[srcPos++];
+            dest32[destPos++] = srcByte & 128 ? white : black;
+            dest32[destPos++] = srcByte & 64 ? white : black;
+            dest32[destPos++] = srcByte & 32 ? white : black;
+            dest32[destPos++] = srcByte & 16 ? white : black;
+            dest32[destPos++] = srcByte & 8 ? white : black;
+            dest32[destPos++] = srcByte & 4 ? white : black;
+            dest32[destPos++] = srcByte & 2 ? white : black;
+            dest32[destPos++] = srcByte & 1 ? white : black;
+          }
+
+          for (; k < kEnd; k++) {
+            if (mask === 0) {
+              srcByte = src[srcPos++];
+              mask = 128;
+            }
+
+            dest32[destPos++] = srcByte & mask ? white : black;
+            mask >>= 1;
+          }
+        }
+
+        while (destPos < dest32DataLength) {
+          dest32[destPos++] = 0;
+        }
+
+        ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+      }
+    } else if (imgData.kind === _util.ImageKind.RGBA_32BPP) {
+      j = 0;
+      elemsInThisChunk = width * FULL_CHUNK_HEIGHT * 4;
+
+      for (i = 0; i < fullChunks; i++) {
+        dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+        srcPos += elemsInThisChunk;
+        ctx.putImageData(chunkImgData, 0, j);
+        j += FULL_CHUNK_HEIGHT;
+      }
+
+      if (i < totalChunks) {
+        elemsInThisChunk = width * partialChunkHeight * 4;
+        dest.set(src.subarray(srcPos, srcPos + elemsInThisChunk));
+        ctx.putImageData(chunkImgData, 0, j);
+      }
+    } else if (imgData.kind === _util.ImageKind.RGB_24BPP) {
+      thisChunkHeight = FULL_CHUNK_HEIGHT;
+      elemsInThisChunk = width * thisChunkHeight;
+
+      for (i = 0; i < totalChunks; i++) {
+        if (i >= fullChunks) {
+          thisChunkHeight = partialChunkHeight;
+          elemsInThisChunk = width * thisChunkHeight;
+        }
+
+        destPos = 0;
+
+        for (j = elemsInThisChunk; j--;) {
+          dest[destPos++] = src[srcPos++];
+          dest[destPos++] = src[srcPos++];
+          dest[destPos++] = src[srcPos++];
+          dest[destPos++] = 255;
+        }
+
+        ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+      }
+    } else {
+      throw new Error("bad image kind: ".concat(imgData.kind));
+    }
+  }
+
+  function putBinaryImageMask(ctx, imgData) {
+    var height = imgData.height,
+        width = imgData.width;
+    var partialChunkHeight = height % FULL_CHUNK_HEIGHT;
+    var fullChunks = (height - partialChunkHeight) / FULL_CHUNK_HEIGHT;
+    var totalChunks = partialChunkHeight === 0 ? fullChunks : fullChunks + 1;
+    var chunkImgData = ctx.createImageData(width, FULL_CHUNK_HEIGHT);
+    var srcPos = 0;
+    var src = imgData.data;
+    var dest = chunkImgData.data;
+
+    for (var i = 0; i < totalChunks; i++) {
+      var thisChunkHeight = i < fullChunks ? FULL_CHUNK_HEIGHT : partialChunkHeight;
+      var destPos = 3;
+
+      for (var j = 0; j < thisChunkHeight; j++) {
+        var mask = 0;
+
+        for (var k = 0; k < width; k++) {
+          if (!mask) {
+            var elem = src[srcPos++];
+            mask = 128;
+          }
+
+          dest[destPos] = elem & mask ? 0 : 255;
+          destPos += 4;
+          mask >>= 1;
+        }
+      }
+
+      ctx.putImageData(chunkImgData, 0, i * FULL_CHUNK_HEIGHT);
+    }
+  }
+
+  function copyCtxState(sourceCtx, destCtx) {
+    var properties = ['strokeStyle', 'fillStyle', 'fillRule', 'globalAlpha', 'lineWidth', 'lineCap', 'lineJoin', 'miterLimit', 'globalCompositeOperation', 'font'];
+
+    for (var i = 0, ii = properties.length; i < ii; i++) {
+      var property = properties[i];
+
+      if (sourceCtx[property] !== undefined) {
+        destCtx[property] = sourceCtx[property];
+      }
+    }
+
+    if (sourceCtx.setLineDash !== undefined) {
+      destCtx.setLineDash(sourceCtx.getLineDash());
+      destCtx.lineDashOffset = sourceCtx.lineDashOffset;
+    }
+  }
+
+  function resetCtxToDefault(ctx) {
+    ctx.strokeStyle = '#000000';
+    ctx.fillStyle = '#000000';
+    ctx.fillRule = 'nonzero';
+    ctx.globalAlpha = 1;
+    ctx.lineWidth = 1;
+    ctx.lineCap = 'butt';
+    ctx.lineJoin = 'miter';
+    ctx.miterLimit = 10;
+    ctx.globalCompositeOperation = 'source-over';
+    ctx.font = '10px sans-serif';
+
+    if (ctx.setLineDash !== undefined) {
+      ctx.setLineDash([]);
+      ctx.lineDashOffset = 0;
+    }
+  }
+
+  function composeSMaskBackdrop(bytes, r0, g0, b0) {
+    var length = bytes.length;
+
+    for (var i = 3; i < length; i += 4) {
+      var alpha = bytes[i];
+
+      if (alpha === 0) {
+        bytes[i - 3] = r0;
+        bytes[i - 2] = g0;
+        bytes[i - 1] = b0;
+      } else if (alpha < 255) {
+        var alpha_ = 255 - alpha;
+        bytes[i - 3] = bytes[i - 3] * alpha + r0 * alpha_ >> 8;
+        bytes[i - 2] = bytes[i - 2] * alpha + g0 * alpha_ >> 8;
+        bytes[i - 1] = bytes[i - 1] * alpha + b0 * alpha_ >> 8;
+      }
+    }
+  }
+
+  function composeSMaskAlpha(maskData, layerData, transferMap) {
+    var length = maskData.length;
+    var scale = 1 / 255;
+
+    for (var i = 3; i < length; i += 4) {
+      var alpha = transferMap ? transferMap[maskData[i]] : maskData[i];
+      layerData[i] = layerData[i] * alpha * scale | 0;
+    }
+  }
+
+  function composeSMaskLuminosity(maskData, layerData, transferMap) {
+    var length = maskData.length;
+
+    for (var i = 3; i < length; i += 4) {
+      var y = maskData[i - 3] * 77 + maskData[i - 2] * 152 + maskData[i - 1] * 28;
+      layerData[i] = transferMap ? layerData[i] * transferMap[y >> 8] >> 8 : layerData[i] * y >> 16;
+    }
+  }
+
+  function genericComposeSMask(maskCtx, layerCtx, width, height, subtype, backdrop, transferMap) {
+    var hasBackdrop = !!backdrop;
+    var r0 = hasBackdrop ? backdrop[0] : 0;
+    var g0 = hasBackdrop ? backdrop[1] : 0;
+    var b0 = hasBackdrop ? backdrop[2] : 0;
+    var composeFn;
+
+    if (subtype === 'Luminosity') {
+      composeFn = composeSMaskLuminosity;
+    } else {
+      composeFn = composeSMaskAlpha;
+    }
+
+    var PIXELS_TO_PROCESS = 1048576;
+    var chunkSize = Math.min(height, Math.ceil(PIXELS_TO_PROCESS / width));
+
+    for (var row = 0; row < height; row += chunkSize) {
+      var chunkHeight = Math.min(chunkSize, height - row);
+      var maskData = maskCtx.getImageData(0, row, width, chunkHeight);
+      var layerData = layerCtx.getImageData(0, row, width, chunkHeight);
+
+      if (hasBackdrop) {
+        composeSMaskBackdrop(maskData.data, r0, g0, b0);
+      }
+
+      composeFn(maskData.data, layerData.data, transferMap);
+      maskCtx.putImageData(layerData, 0, row);
+    }
+  }
+
+  function composeSMask(ctx, smask, layerCtx, webGLContext) {
+    var mask = smask.canvas;
+    var maskCtx = smask.context;
+    ctx.setTransform(smask.scaleX, 0, 0, smask.scaleY, smask.offsetX, smask.offsetY);
+    var backdrop = smask.backdrop || null;
+
+    if (!smask.transferMap && webGLContext.isEnabled) {
+      var composed = webGLContext.composeSMask({
+        layer: layerCtx.canvas,
+        mask: mask,
+        properties: {
+          subtype: smask.subtype,
+          backdrop: backdrop
+        }
+      });
+      ctx.setTransform(1, 0, 0, 1, 0, 0);
+      ctx.drawImage(composed, smask.offsetX, smask.offsetY);
+      return;
+    }
+
+    genericComposeSMask(maskCtx, layerCtx, mask.width, mask.height, smask.subtype, backdrop, smask.transferMap);
+    ctx.drawImage(mask, 0, 0);
+  }
+
+  var LINE_CAP_STYLES = ['butt', 'round', 'square'];
+  var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
+  var NORMAL_CLIP = {};
+  var EO_CLIP = {};
+  CanvasGraphics.prototype = {
+    beginDrawing: function beginDrawing(_ref) {
+      var transform = _ref.transform,
+          viewport = _ref.viewport,
+          _ref$transparency = _ref.transparency,
+          transparency = _ref$transparency === void 0 ? false : _ref$transparency,
+          _ref$background = _ref.background,
+          background = _ref$background === void 0 ? null : _ref$background;
+      var width = this.ctx.canvas.width;
+      var height = this.ctx.canvas.height;
+      this.ctx.save();
+      this.ctx.fillStyle = background || 'rgb(255, 255, 255)';
+      this.ctx.fillRect(0, 0, width, height);
+      this.ctx.restore();
+
+      if (transparency) {
+        var transparentCanvas = this.cachedCanvases.getCanvas('transparent', width, height, true);
+        this.compositeCtx = this.ctx;
+        this.transparentCanvas = transparentCanvas.canvas;
+        this.ctx = transparentCanvas.context;
+        this.ctx.save();
+        this.ctx.transform.apply(this.ctx, this.compositeCtx.mozCurrentTransform);
+      }
+
+      this.ctx.save();
+      resetCtxToDefault(this.ctx);
+
+      if (transform) {
+        this.ctx.transform.apply(this.ctx, transform);
+      }
+
+      this.ctx.transform.apply(this.ctx, viewport.transform);
+      this.baseTransform = this.ctx.mozCurrentTransform.slice();
+
+      if (this.imageLayer) {
+        this.imageLayer.beginLayout();
+      }
+    },
+    executeOperatorList: function CanvasGraphics_executeOperatorList(operatorList, executionStartIdx, continueCallback, stepper) {
+      var argsArray = operatorList.argsArray;
+      var fnArray = operatorList.fnArray;
+      var i = executionStartIdx || 0;
+      var argsArrayLen = argsArray.length;
+
+      if (argsArrayLen === i) {
+        return i;
+      }
+
+      var chunkOperations = argsArrayLen - i > EXECUTION_STEPS && typeof continueCallback === 'function';
+      var endTime = chunkOperations ? Date.now() + EXECUTION_TIME : 0;
+      var steps = 0;
+      var commonObjs = this.commonObjs;
+      var objs = this.objs;
+      var fnId;
+
+      while (true) {
+        if (stepper !== undefined && i === stepper.nextBreakPoint) {
+          stepper.breakIt(i, continueCallback);
+          return i;
+        }
+
+        fnId = fnArray[i];
+
+        if (fnId !== _util.OPS.dependency) {
+          this[fnId].apply(this, argsArray[i]);
+        } else {
+          var _iteratorNormalCompletion = true;
+          var _didIteratorError = false;
+          var _iteratorError = undefined;
+
+          try {
+            for (var _iterator = argsArray[i][Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+              var depObjId = _step.value;
+              var objsPool = depObjId.startsWith('g_') ? commonObjs : objs;
+
+              if (!objsPool.has(depObjId)) {
+                objsPool.get(depObjId, continueCallback);
+                return i;
+              }
+            }
+          } catch (err) {
+            _didIteratorError = true;
+            _iteratorError = err;
+          } finally {
+            try {
+              if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+                _iterator["return"]();
+              }
+            } finally {
+              if (_didIteratorError) {
+                throw _iteratorError;
+              }
+            }
+          }
+        }
+
+        i++;
+
+        if (i === argsArrayLen) {
+          return i;
+        }
+
+        if (chunkOperations && ++steps > EXECUTION_STEPS) {
+          if (Date.now() > endTime) {
+            continueCallback();
+            return i;
+          }
+
+          steps = 0;
+        }
+      }
+    },
+    endDrawing: function CanvasGraphics_endDrawing() {
+      if (this.current.activeSMask !== null) {
+        this.endSMaskGroup();
+      }
+
+      this.ctx.restore();
+
+      if (this.transparentCanvas) {
+        this.ctx = this.compositeCtx;
+        this.ctx.save();
+        this.ctx.setTransform(1, 0, 0, 1, 0, 0);
+        this.ctx.drawImage(this.transparentCanvas, 0, 0);
+        this.ctx.restore();
+        this.transparentCanvas = null;
+      }
+
+      this.cachedCanvases.clear();
+      this.webGLContext.clear();
+
+      if (this.imageLayer) {
+        this.imageLayer.endLayout();
+      }
+    },
+    setLineWidth: function CanvasGraphics_setLineWidth(width) {
+      this.current.lineWidth = width;
+      this.ctx.lineWidth = width;
+    },
+    setLineCap: function CanvasGraphics_setLineCap(style) {
+      this.ctx.lineCap = LINE_CAP_STYLES[style];
+    },
+    setLineJoin: function CanvasGraphics_setLineJoin(style) {
+      this.ctx.lineJoin = LINE_JOIN_STYLES[style];
+    },
+    setMiterLimit: function CanvasGraphics_setMiterLimit(limit) {
+      this.ctx.miterLimit = limit;
+    },
+    setDash: function CanvasGraphics_setDash(dashArray, dashPhase) {
+      var ctx = this.ctx;
+
+      if (ctx.setLineDash !== undefined) {
+        ctx.setLineDash(dashArray);
+        ctx.lineDashOffset = dashPhase;
+      }
+    },
+    setRenderingIntent: function setRenderingIntent(intent) {},
+    setFlatness: function setFlatness(flatness) {},
+    setGState: function CanvasGraphics_setGState(states) {
+      for (var i = 0, ii = states.length; i < ii; i++) {
+        var state = states[i];
+        var key = state[0];
+        var value = state[1];
+
+        switch (key) {
+          case 'LW':
+            this.setLineWidth(value);
+            break;
+
+          case 'LC':
+            this.setLineCap(value);
+            break;
+
+          case 'LJ':
+            this.setLineJoin(value);
+            break;
+
+          case 'ML':
+            this.setMiterLimit(value);
+            break;
+
+          case 'D':
+            this.setDash(value[0], value[1]);
+            break;
+
+          case 'RI':
+            this.setRenderingIntent(value);
+            break;
+
+          case 'FL':
+            this.setFlatness(value);
+            break;
+
+          case 'Font':
+            this.setFont(value[0], value[1]);
+            break;
+
+          case 'CA':
+            this.current.strokeAlpha = state[1];
+            break;
+
+          case 'ca':
+            this.current.fillAlpha = state[1];
+            this.ctx.globalAlpha = state[1];
+            break;
+
+          case 'BM':
+            this.ctx.globalCompositeOperation = value;
+            break;
+
+          case 'SMask':
+            if (this.current.activeSMask) {
+              if (this.stateStack.length > 0 && this.stateStack[this.stateStack.length - 1].activeSMask === this.current.activeSMask) {
+                this.suspendSMaskGroup();
+              } else {
+                this.endSMaskGroup();
+              }
+            }
+
+            this.current.activeSMask = value ? this.tempSMask : null;
+
+            if (this.current.activeSMask) {
+              this.beginSMaskGroup();
+            }
+
+            this.tempSMask = null;
+            break;
+        }
+      }
+    },
+    beginSMaskGroup: function CanvasGraphics_beginSMaskGroup() {
+      var activeSMask = this.current.activeSMask;
+      var drawnWidth = activeSMask.canvas.width;
+      var drawnHeight = activeSMask.canvas.height;
+      var cacheId = 'smaskGroupAt' + this.groupLevel;
+      var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
+      var currentCtx = this.ctx;
+      var currentTransform = currentCtx.mozCurrentTransform;
+      this.ctx.save();
+      var groupCtx = scratchCanvas.context;
+      groupCtx.scale(1 / activeSMask.scaleX, 1 / activeSMask.scaleY);
+      groupCtx.translate(-activeSMask.offsetX, -activeSMask.offsetY);
+      groupCtx.transform.apply(groupCtx, currentTransform);
+      activeSMask.startTransformInverse = groupCtx.mozCurrentTransformInverse;
+      copyCtxState(currentCtx, groupCtx);
+      this.ctx = groupCtx;
+      this.setGState([['BM', 'source-over'], ['ca', 1], ['CA', 1]]);
+      this.groupStack.push(currentCtx);
+      this.groupLevel++;
+    },
+    suspendSMaskGroup: function CanvasGraphics_endSMaskGroup() {
+      var groupCtx = this.ctx;
+      this.groupLevel--;
+      this.ctx = this.groupStack.pop();
+      composeSMask(this.ctx, this.current.activeSMask, groupCtx, this.webGLContext);
+      this.ctx.restore();
+      this.ctx.save();
+      copyCtxState(groupCtx, this.ctx);
+      this.current.resumeSMaskCtx = groupCtx;
+
+      var deltaTransform = _util.Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
+
+      this.ctx.transform.apply(this.ctx, deltaTransform);
+      groupCtx.save();
+      groupCtx.setTransform(1, 0, 0, 1, 0, 0);
+      groupCtx.clearRect(0, 0, groupCtx.canvas.width, groupCtx.canvas.height);
+      groupCtx.restore();
+    },
+    resumeSMaskGroup: function CanvasGraphics_endSMaskGroup() {
+      var groupCtx = this.current.resumeSMaskCtx;
+      var currentCtx = this.ctx;
+      this.ctx = groupCtx;
+      this.groupStack.push(currentCtx);
+      this.groupLevel++;
+    },
+    endSMaskGroup: function CanvasGraphics_endSMaskGroup() {
+      var groupCtx = this.ctx;
+      this.groupLevel--;
+      this.ctx = this.groupStack.pop();
+      composeSMask(this.ctx, this.current.activeSMask, groupCtx, this.webGLContext);
+      this.ctx.restore();
+      copyCtxState(groupCtx, this.ctx);
+
+      var deltaTransform = _util.Util.transform(this.current.activeSMask.startTransformInverse, groupCtx.mozCurrentTransform);
+
+      this.ctx.transform.apply(this.ctx, deltaTransform);
+    },
+    save: function CanvasGraphics_save() {
+      this.ctx.save();
+      var old = this.current;
+      this.stateStack.push(old);
+      this.current = old.clone();
+      this.current.resumeSMaskCtx = null;
+    },
+    restore: function CanvasGraphics_restore() {
+      if (this.current.resumeSMaskCtx) {
+        this.resumeSMaskGroup();
+      }
+
+      if (this.current.activeSMask !== null && (this.stateStack.length === 0 || this.stateStack[this.stateStack.length - 1].activeSMask !== this.current.activeSMask)) {
+        this.endSMaskGroup();
+      }
+
+      if (this.stateStack.length !== 0) {
+        this.current = this.stateStack.pop();
+        this.ctx.restore();
+        this.pendingClip = null;
+        this._cachedGetSinglePixelWidth = null;
+      }
+    },
+    transform: function CanvasGraphics_transform(a, b, c, d, e, f) {
+      this.ctx.transform(a, b, c, d, e, f);
+      this._cachedGetSinglePixelWidth = null;
+    },
+    constructPath: function CanvasGraphics_constructPath(ops, args) {
+      var ctx = this.ctx;
+      var current = this.current;
+      var x = current.x,
+          y = current.y;
+
+      for (var i = 0, j = 0, ii = ops.length; i < ii; i++) {
+        switch (ops[i] | 0) {
+          case _util.OPS.rectangle:
+            x = args[j++];
+            y = args[j++];
+            var width = args[j++];
+            var height = args[j++];
+
+            if (width === 0) {
+              width = this.getSinglePixelWidth();
+            }
+
+            if (height === 0) {
+              height = this.getSinglePixelWidth();
+            }
+
+            var xw = x + width;
+            var yh = y + height;
+            this.ctx.moveTo(x, y);
+            this.ctx.lineTo(xw, y);
+            this.ctx.lineTo(xw, yh);
+            this.ctx.lineTo(x, yh);
+            this.ctx.lineTo(x, y);
+            this.ctx.closePath();
+            break;
+
+          case _util.OPS.moveTo:
+            x = args[j++];
+            y = args[j++];
+            ctx.moveTo(x, y);
+            break;
+
+          case _util.OPS.lineTo:
+            x = args[j++];
+            y = args[j++];
+            ctx.lineTo(x, y);
+            break;
+
+          case _util.OPS.curveTo:
+            x = args[j + 4];
+            y = args[j + 5];
+            ctx.bezierCurveTo(args[j], args[j + 1], args[j + 2], args[j + 3], x, y);
+            j += 6;
+            break;
+
+          case _util.OPS.curveTo2:
+            ctx.bezierCurveTo(x, y, args[j], args[j + 1], args[j + 2], args[j + 3]);
+            x = args[j + 2];
+            y = args[j + 3];
+            j += 4;
+            break;
+
+          case _util.OPS.curveTo3:
+            x = args[j + 2];
+            y = args[j + 3];
+            ctx.bezierCurveTo(args[j], args[j + 1], x, y, x, y);
+            j += 4;
+            break;
+
+          case _util.OPS.closePath:
+            ctx.closePath();
+            break;
+        }
+      }
+
+      current.setCurrentPoint(x, y);
+    },
+    closePath: function CanvasGraphics_closePath() {
+      this.ctx.closePath();
+    },
+    stroke: function CanvasGraphics_stroke(consumePath) {
+      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
+      var ctx = this.ctx;
+      var strokeColor = this.current.strokeColor;
+      ctx.lineWidth = Math.max(this.getSinglePixelWidth() * MIN_WIDTH_FACTOR, this.current.lineWidth);
+      ctx.globalAlpha = this.current.strokeAlpha;
+
+      if (strokeColor && strokeColor.hasOwnProperty('type') && strokeColor.type === 'Pattern') {
+        ctx.save();
+        ctx.strokeStyle = strokeColor.getPattern(ctx, this);
+        ctx.stroke();
+        ctx.restore();
+      } else {
+        ctx.stroke();
+      }
+
+      if (consumePath) {
+        this.consumePath();
+      }
+
+      ctx.globalAlpha = this.current.fillAlpha;
+    },
+    closeStroke: function CanvasGraphics_closeStroke() {
+      this.closePath();
+      this.stroke();
+    },
+    fill: function CanvasGraphics_fill(consumePath) {
+      consumePath = typeof consumePath !== 'undefined' ? consumePath : true;
+      var ctx = this.ctx;
+      var fillColor = this.current.fillColor;
+      var isPatternFill = this.current.patternFill;
+      var needRestore = false;
+
+      if (isPatternFill) {
+        ctx.save();
+
+        if (this.baseTransform) {
+          ctx.setTransform.apply(ctx, this.baseTransform);
+        }
+
+        ctx.fillStyle = fillColor.getPattern(ctx, this);
+        needRestore = true;
+      }
+
+      if (this.pendingEOFill) {
+        ctx.fill('evenodd');
+        this.pendingEOFill = false;
+      } else {
+        ctx.fill();
+      }
+
+      if (needRestore) {
+        ctx.restore();
+      }
+
+      if (consumePath) {
+        this.consumePath();
+      }
+    },
+    eoFill: function CanvasGraphics_eoFill() {
+      this.pendingEOFill = true;
+      this.fill();
+    },
+    fillStroke: function CanvasGraphics_fillStroke() {
+      this.fill(false);
+      this.stroke(false);
+      this.consumePath();
+    },
+    eoFillStroke: function CanvasGraphics_eoFillStroke() {
+      this.pendingEOFill = true;
+      this.fillStroke();
+    },
+    closeFillStroke: function CanvasGraphics_closeFillStroke() {
+      this.closePath();
+      this.fillStroke();
+    },
+    closeEOFillStroke: function CanvasGraphics_closeEOFillStroke() {
+      this.pendingEOFill = true;
+      this.closePath();
+      this.fillStroke();
+    },
+    endPath: function CanvasGraphics_endPath() {
+      this.consumePath();
+    },
+    clip: function CanvasGraphics_clip() {
+      this.pendingClip = NORMAL_CLIP;
+    },
+    eoClip: function CanvasGraphics_eoClip() {
+      this.pendingClip = EO_CLIP;
+    },
+    beginText: function CanvasGraphics_beginText() {
+      this.current.textMatrix = _util.IDENTITY_MATRIX;
+      this.current.textMatrixScale = 1;
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    endText: function CanvasGraphics_endText() {
+      var paths = this.pendingTextPaths;
+      var ctx = this.ctx;
+
+      if (paths === undefined) {
+        ctx.beginPath();
+        return;
+      }
+
+      ctx.save();
+      ctx.beginPath();
+
+      for (var i = 0; i < paths.length; i++) {
+        var path = paths[i];
+        ctx.setTransform.apply(ctx, path.transform);
+        ctx.translate(path.x, path.y);
+        path.addToPath(ctx, path.fontSize);
+      }
+
+      ctx.restore();
+      ctx.clip();
+      ctx.beginPath();
+      delete this.pendingTextPaths;
+    },
+    setCharSpacing: function CanvasGraphics_setCharSpacing(spacing) {
+      this.current.charSpacing = spacing;
+    },
+    setWordSpacing: function CanvasGraphics_setWordSpacing(spacing) {
+      this.current.wordSpacing = spacing;
+    },
+    setHScale: function CanvasGraphics_setHScale(scale) {
+      this.current.textHScale = scale / 100;
+    },
+    setLeading: function CanvasGraphics_setLeading(leading) {
+      this.current.leading = -leading;
+    },
+    setFont: function CanvasGraphics_setFont(fontRefName, size) {
+      var fontObj = this.commonObjs.get(fontRefName);
+      var current = this.current;
+
+      if (!fontObj) {
+        throw new Error("Can't find font for ".concat(fontRefName));
+      }
+
+      current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : _util.FONT_IDENTITY_MATRIX;
+
+      if (current.fontMatrix[0] === 0 || current.fontMatrix[3] === 0) {
+        (0, _util.warn)('Invalid font matrix for font ' + fontRefName);
+      }
+
+      if (size < 0) {
+        size = -size;
+        current.fontDirection = -1;
+      } else {
+        current.fontDirection = 1;
+      }
+
+      this.current.font = fontObj;
+      this.current.fontSize = size;
+
+      if (fontObj.isType3Font) {
+        return;
+      }
+
+      var name = fontObj.loadedName || 'sans-serif';
+      var bold = fontObj.black ? '900' : fontObj.bold ? 'bold' : 'normal';
+      var italic = fontObj.italic ? 'italic' : 'normal';
+      var typeface = "\"".concat(name, "\", ").concat(fontObj.fallbackName);
+      var browserFontSize = size < MIN_FONT_SIZE ? MIN_FONT_SIZE : size > MAX_FONT_SIZE ? MAX_FONT_SIZE : size;
+      this.current.fontSizeScale = size / browserFontSize;
+      this.ctx.font = "".concat(italic, " ").concat(bold, " ").concat(browserFontSize, "px ").concat(typeface);
+    },
+    setTextRenderingMode: function CanvasGraphics_setTextRenderingMode(mode) {
+      this.current.textRenderingMode = mode;
+    },
+    setTextRise: function CanvasGraphics_setTextRise(rise) {
+      this.current.textRise = rise;
+    },
+    moveText: function CanvasGraphics_moveText(x, y) {
+      this.current.x = this.current.lineX += x;
+      this.current.y = this.current.lineY += y;
+    },
+    setLeadingMoveText: function CanvasGraphics_setLeadingMoveText(x, y) {
+      this.setLeading(-y);
+      this.moveText(x, y);
+    },
+    setTextMatrix: function CanvasGraphics_setTextMatrix(a, b, c, d, e, f) {
+      this.current.textMatrix = [a, b, c, d, e, f];
+      this.current.textMatrixScale = Math.sqrt(a * a + b * b);
+      this.current.x = this.current.lineX = 0;
+      this.current.y = this.current.lineY = 0;
+    },
+    nextLine: function CanvasGraphics_nextLine() {
+      this.moveText(0, this.current.leading);
+    },
+    paintChar: function paintChar(character, x, y, patternTransform) {
+      var ctx = this.ctx;
+      var current = this.current;
+      var font = current.font;
+      var textRenderingMode = current.textRenderingMode;
+      var fontSize = current.fontSize / current.fontSizeScale;
+      var fillStrokeMode = textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+      var isAddToPathSet = !!(textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
+      var patternFill = current.patternFill && font.data;
+      var addToPath;
+
+      if (font.disableFontFace || isAddToPathSet || patternFill) {
+        addToPath = font.getPathGenerator(this.commonObjs, character);
+      }
+
+      if (font.disableFontFace || patternFill) {
+        ctx.save();
+        ctx.translate(x, y);
+        ctx.beginPath();
+        addToPath(ctx, fontSize);
+
+        if (patternTransform) {
+          ctx.setTransform.apply(ctx, patternTransform);
+        }
+
+        if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          ctx.fill();
+        }
+
+        if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          ctx.stroke();
+        }
+
+        ctx.restore();
+      } else {
+        if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          ctx.fillText(character, x, y);
+        }
+
+        if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          ctx.strokeText(character, x, y);
+        }
+      }
+
+      if (isAddToPathSet) {
+        var paths = this.pendingTextPaths || (this.pendingTextPaths = []);
+        paths.push({
+          transform: ctx.mozCurrentTransform,
+          x: x,
+          y: y,
+          fontSize: fontSize,
+          addToPath: addToPath
+        });
+      }
+    },
+
+    get isFontSubpixelAAEnabled() {
+      var _this$cachedCanvases$ = this.cachedCanvases.getCanvas('isFontSubpixelAAEnabled', 10, 10),
+          ctx = _this$cachedCanvases$.context;
+
+      ctx.scale(1.5, 1);
+      ctx.fillText('I', 0, 10);
+      var data = ctx.getImageData(0, 0, 10, 10).data;
+      var enabled = false;
+
+      for (var i = 3; i < data.length; i += 4) {
+        if (data[i] > 0 && data[i] < 255) {
+          enabled = true;
+          break;
+        }
+      }
+
+      return (0, _util.shadow)(this, 'isFontSubpixelAAEnabled', enabled);
+    },
+
+    showText: function CanvasGraphics_showText(glyphs) {
+      var current = this.current;
+      var font = current.font;
+
+      if (font.isType3Font) {
+        return this.showType3Text(glyphs);
+      }
+
+      var fontSize = current.fontSize;
+
+      if (fontSize === 0) {
+        return undefined;
+      }
+
+      var ctx = this.ctx;
+      var fontSizeScale = current.fontSizeScale;
+      var charSpacing = current.charSpacing;
+      var wordSpacing = current.wordSpacing;
+      var fontDirection = current.fontDirection;
+      var textHScale = current.textHScale * fontDirection;
+      var glyphsLength = glyphs.length;
+      var vertical = font.vertical;
+      var spacingDir = vertical ? 1 : -1;
+      var defaultVMetrics = font.defaultVMetrics;
+      var widthAdvanceScale = fontSize * current.fontMatrix[0];
+      var simpleFillText = current.textRenderingMode === _util.TextRenderingMode.FILL && !font.disableFontFace && !current.patternFill;
+      ctx.save();
+      var patternTransform;
+
+      if (current.patternFill) {
+        ctx.save();
+        var pattern = current.fillColor.getPattern(ctx, this);
+        patternTransform = ctx.mozCurrentTransform;
+        ctx.restore();
+        ctx.fillStyle = pattern;
+      }
+
+      ctx.transform.apply(ctx, current.textMatrix);
+      ctx.translate(current.x, current.y + current.textRise);
+
+      if (fontDirection > 0) {
+        ctx.scale(textHScale, -1);
+      } else {
+        ctx.scale(textHScale, 1);
+      }
+
+      var lineWidth = current.lineWidth;
+      var scale = current.textMatrixScale;
+
+      if (scale === 0 || lineWidth === 0) {
+        var fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+
+        if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          this._cachedGetSinglePixelWidth = null;
+          lineWidth = this.getSinglePixelWidth() * MIN_WIDTH_FACTOR;
+        }
+      } else {
+        lineWidth /= scale;
+      }
+
+      if (fontSizeScale !== 1.0) {
+        ctx.scale(fontSizeScale, fontSizeScale);
+        lineWidth /= fontSizeScale;
+      }
+
+      ctx.lineWidth = lineWidth;
+      var x = 0,
+          i;
+
+      for (i = 0; i < glyphsLength; ++i) {
+        var glyph = glyphs[i];
+
+        if ((0, _util.isNum)(glyph)) {
+          x += spacingDir * glyph * fontSize / 1000;
+          continue;
+        }
+
+        var restoreNeeded = false;
+        var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+        var character = glyph.fontChar;
+        var accent = glyph.accent;
+        var scaledX, scaledY, scaledAccentX, scaledAccentY;
+        var width = glyph.width;
+
+        if (vertical) {
+          var vmetric, vx, vy;
+          vmetric = glyph.vmetric || defaultVMetrics;
+          vx = glyph.vmetric ? vmetric[1] : width * 0.5;
+          vx = -vx * widthAdvanceScale;
+          vy = vmetric[2] * widthAdvanceScale;
+          width = vmetric ? -vmetric[0] : width;
+          scaledX = vx / fontSizeScale;
+          scaledY = (x + vy) / fontSizeScale;
+        } else {
+          scaledX = x / fontSizeScale;
+          scaledY = 0;
+        }
+
+        if (font.remeasure && width > 0) {
+          var measuredWidth = ctx.measureText(character).width * 1000 / fontSize * fontSizeScale;
+
+          if (width < measuredWidth && this.isFontSubpixelAAEnabled) {
+            var characterScaleX = width / measuredWidth;
+            restoreNeeded = true;
+            ctx.save();
+            ctx.scale(characterScaleX, 1);
+            scaledX /= characterScaleX;
+          } else if (width !== measuredWidth) {
+            scaledX += (width - measuredWidth) / 2000 * fontSize / fontSizeScale;
+          }
+        }
+
+        if (glyph.isInFont || font.missingFile) {
+          if (simpleFillText && !accent) {
+            ctx.fillText(character, scaledX, scaledY);
+          } else {
+            this.paintChar(character, scaledX, scaledY, patternTransform);
+
+            if (accent) {
+              scaledAccentX = scaledX + accent.offset.x / fontSizeScale;
+              scaledAccentY = scaledY - accent.offset.y / fontSizeScale;
+              this.paintChar(accent.fontChar, scaledAccentX, scaledAccentY, patternTransform);
+            }
+          }
+        }
+
+        var charWidth = width * widthAdvanceScale + spacing * fontDirection;
+        x += charWidth;
+
+        if (restoreNeeded) {
+          ctx.restore();
+        }
+      }
+
+      if (vertical) {
+        current.y -= x * textHScale;
+      } else {
+        current.x += x * textHScale;
+      }
+
+      ctx.restore();
+    },
+    showType3Text: function CanvasGraphics_showType3Text(glyphs) {
+      var ctx = this.ctx;
+      var current = this.current;
+      var font = current.font;
+      var fontSize = current.fontSize;
+      var fontDirection = current.fontDirection;
+      var spacingDir = font.vertical ? 1 : -1;
+      var charSpacing = current.charSpacing;
+      var wordSpacing = current.wordSpacing;
+      var textHScale = current.textHScale * fontDirection;
+      var fontMatrix = current.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+      var glyphsLength = glyphs.length;
+      var isTextInvisible = current.textRenderingMode === _util.TextRenderingMode.INVISIBLE;
+      var i, glyph, width, spacingLength;
+
+      if (isTextInvisible || fontSize === 0) {
+        return;
+      }
+
+      this._cachedGetSinglePixelWidth = null;
+      ctx.save();
+      ctx.transform.apply(ctx, current.textMatrix);
+      ctx.translate(current.x, current.y);
+      ctx.scale(textHScale, fontDirection);
+
+      for (i = 0; i < glyphsLength; ++i) {
+        glyph = glyphs[i];
+
+        if ((0, _util.isNum)(glyph)) {
+          spacingLength = spacingDir * glyph * fontSize / 1000;
+          this.ctx.translate(spacingLength, 0);
+          current.x += spacingLength * textHScale;
+          continue;
+        }
+
+        var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+        var operatorList = font.charProcOperatorList[glyph.operatorListId];
+
+        if (!operatorList) {
+          (0, _util.warn)("Type3 character \"".concat(glyph.operatorListId, "\" is not available."));
+          continue;
+        }
+
+        this.processingType3 = glyph;
+        this.save();
+        ctx.scale(fontSize, fontSize);
+        ctx.transform.apply(ctx, fontMatrix);
+        this.executeOperatorList(operatorList);
+        this.restore();
+
+        var transformed = _util.Util.applyTransform([glyph.width, 0], fontMatrix);
+
+        width = transformed[0] * fontSize + spacing;
+        ctx.translate(width, 0);
+        current.x += width * textHScale;
+      }
+
+      ctx.restore();
+      this.processingType3 = null;
+    },
+    setCharWidth: function CanvasGraphics_setCharWidth(xWidth, yWidth) {},
+    setCharWidthAndBounds: function CanvasGraphics_setCharWidthAndBounds(xWidth, yWidth, llx, lly, urx, ury) {
+      this.ctx.rect(llx, lly, urx - llx, ury - lly);
+      this.clip();
+      this.endPath();
+    },
+    getColorN_Pattern: function CanvasGraphics_getColorN_Pattern(IR) {
+      var _this = this;
+
+      var pattern;
+
+      if (IR[0] === 'TilingPattern') {
+        var color = IR[1];
+        var baseTransform = this.baseTransform || this.ctx.mozCurrentTransform.slice();
+        var canvasGraphicsFactory = {
+          createCanvasGraphics: function createCanvasGraphics(ctx) {
+            return new CanvasGraphics(ctx, _this.commonObjs, _this.objs, _this.canvasFactory, _this.webGLContext);
+          }
+        };
+        pattern = new _pattern_helper.TilingPattern(IR, color, this.ctx, canvasGraphicsFactory, baseTransform);
+      } else {
+        pattern = (0, _pattern_helper.getShadingPatternFromIR)(IR);
+      }
+
+      return pattern;
+    },
+    setStrokeColorN: function CanvasGraphics_setStrokeColorN() {
+      this.current.strokeColor = this.getColorN_Pattern(arguments);
+    },
+    setFillColorN: function CanvasGraphics_setFillColorN() {
+      this.current.fillColor = this.getColorN_Pattern(arguments);
+      this.current.patternFill = true;
+    },
+    setStrokeRGBColor: function CanvasGraphics_setStrokeRGBColor(r, g, b) {
+      var color = _util.Util.makeCssRgb(r, g, b);
+
+      this.ctx.strokeStyle = color;
+      this.current.strokeColor = color;
+    },
+    setFillRGBColor: function CanvasGraphics_setFillRGBColor(r, g, b) {
+      var color = _util.Util.makeCssRgb(r, g, b);
+
+      this.ctx.fillStyle = color;
+      this.current.fillColor = color;
+      this.current.patternFill = false;
+    },
+    shadingFill: function CanvasGraphics_shadingFill(patternIR) {
+      var ctx = this.ctx;
+      this.save();
+      var pattern = (0, _pattern_helper.getShadingPatternFromIR)(patternIR);
+      ctx.fillStyle = pattern.getPattern(ctx, this, true);
+      var inv = ctx.mozCurrentTransformInverse;
+
+      if (inv) {
+        var canvas = ctx.canvas;
+        var width = canvas.width;
+        var height = canvas.height;
+
+        var bl = _util.Util.applyTransform([0, 0], inv);
+
+        var br = _util.Util.applyTransform([0, height], inv);
+
+        var ul = _util.Util.applyTransform([width, 0], inv);
+
+        var ur = _util.Util.applyTransform([width, height], inv);
+
+        var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
+        var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
+        var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
+        var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
+        this.ctx.fillRect(x0, y0, x1 - x0, y1 - y0);
+      } else {
+        this.ctx.fillRect(-1e10, -1e10, 2e10, 2e10);
+      }
+
+      this.restore();
+    },
+    beginInlineImage: function CanvasGraphics_beginInlineImage() {
+      (0, _util.unreachable)('Should not call beginInlineImage');
+    },
+    beginImageData: function CanvasGraphics_beginImageData() {
+      (0, _util.unreachable)('Should not call beginImageData');
+    },
+    paintFormXObjectBegin: function CanvasGraphics_paintFormXObjectBegin(matrix, bbox) {
+      this.save();
+      this.baseTransformStack.push(this.baseTransform);
+
+      if (Array.isArray(matrix) && matrix.length === 6) {
+        this.transform.apply(this, matrix);
+      }
+
+      this.baseTransform = this.ctx.mozCurrentTransform;
+
+      if (bbox) {
+        var width = bbox[2] - bbox[0];
+        var height = bbox[3] - bbox[1];
+        this.ctx.rect(bbox[0], bbox[1], width, height);
+        this.clip();
+        this.endPath();
+      }
+    },
+    paintFormXObjectEnd: function CanvasGraphics_paintFormXObjectEnd() {
+      this.restore();
+      this.baseTransform = this.baseTransformStack.pop();
+    },
+    beginGroup: function CanvasGraphics_beginGroup(group) {
+      this.save();
+      var currentCtx = this.ctx;
+
+      if (!group.isolated) {
+        (0, _util.info)('TODO: Support non-isolated groups.');
+      }
+
+      if (group.knockout) {
+        (0, _util.warn)('Knockout groups not supported.');
+      }
+
+      var currentTransform = currentCtx.mozCurrentTransform;
+
+      if (group.matrix) {
+        currentCtx.transform.apply(currentCtx, group.matrix);
+      }
+
+      if (!group.bbox) {
+        throw new Error('Bounding box is required.');
+      }
+
+      var bounds = _util.Util.getAxialAlignedBoundingBox(group.bbox, currentCtx.mozCurrentTransform);
+
+      var canvasBounds = [0, 0, currentCtx.canvas.width, currentCtx.canvas.height];
+      bounds = _util.Util.intersect(bounds, canvasBounds) || [0, 0, 0, 0];
+      var offsetX = Math.floor(bounds[0]);
+      var offsetY = Math.floor(bounds[1]);
+      var drawnWidth = Math.max(Math.ceil(bounds[2]) - offsetX, 1);
+      var drawnHeight = Math.max(Math.ceil(bounds[3]) - offsetY, 1);
+      var scaleX = 1,
+          scaleY = 1;
+
+      if (drawnWidth > MAX_GROUP_SIZE) {
+        scaleX = drawnWidth / MAX_GROUP_SIZE;
+        drawnWidth = MAX_GROUP_SIZE;
+      }
+
+      if (drawnHeight > MAX_GROUP_SIZE) {
+        scaleY = drawnHeight / MAX_GROUP_SIZE;
+        drawnHeight = MAX_GROUP_SIZE;
+      }
+
+      var cacheId = 'groupAt' + this.groupLevel;
+
+      if (group.smask) {
+        cacheId += '_smask_' + this.smaskCounter++ % 2;
+      }
+
+      var scratchCanvas = this.cachedCanvases.getCanvas(cacheId, drawnWidth, drawnHeight, true);
+      var groupCtx = scratchCanvas.context;
+      groupCtx.scale(1 / scaleX, 1 / scaleY);
+      groupCtx.translate(-offsetX, -offsetY);
+      groupCtx.transform.apply(groupCtx, currentTransform);
+
+      if (group.smask) {
+        this.smaskStack.push({
+          canvas: scratchCanvas.canvas,
+          context: groupCtx,
+          offsetX: offsetX,
+          offsetY: offsetY,
+          scaleX: scaleX,
+          scaleY: scaleY,
+          subtype: group.smask.subtype,
+          backdrop: group.smask.backdrop,
+          transferMap: group.smask.transferMap || null,
+          startTransformInverse: null
+        });
+      } else {
+        currentCtx.setTransform(1, 0, 0, 1, 0, 0);
+        currentCtx.translate(offsetX, offsetY);
+        currentCtx.scale(scaleX, scaleY);
+      }
+
+      copyCtxState(currentCtx, groupCtx);
+      this.ctx = groupCtx;
+      this.setGState([['BM', 'source-over'], ['ca', 1], ['CA', 1]]);
+      this.groupStack.push(currentCtx);
+      this.groupLevel++;
+      this.current.activeSMask = null;
+    },
+    endGroup: function CanvasGraphics_endGroup(group) {
+      this.groupLevel--;
+      var groupCtx = this.ctx;
+      this.ctx = this.groupStack.pop();
+
+      if (this.ctx.imageSmoothingEnabled !== undefined) {
+        this.ctx.imageSmoothingEnabled = false;
+      } else {
+        this.ctx.mozImageSmoothingEnabled = false;
+      }
+
+      if (group.smask) {
+        this.tempSMask = this.smaskStack.pop();
+      } else {
+        this.ctx.drawImage(groupCtx.canvas, 0, 0);
+      }
+
+      this.restore();
+    },
+    beginAnnotations: function CanvasGraphics_beginAnnotations() {
+      this.save();
+
+      if (this.baseTransform) {
+        this.ctx.setTransform.apply(this.ctx, this.baseTransform);
+      }
+    },
+    endAnnotations: function CanvasGraphics_endAnnotations() {
+      this.restore();
+    },
+    beginAnnotation: function CanvasGraphics_beginAnnotation(rect, transform, matrix) {
+      this.save();
+      resetCtxToDefault(this.ctx);
+      this.current = new CanvasExtraState();
+
+      if (Array.isArray(rect) && rect.length === 4) {
+        var width = rect[2] - rect[0];
+        var height = rect[3] - rect[1];
+        this.ctx.rect(rect[0], rect[1], width, height);
+        this.clip();
+        this.endPath();
+      }
+
+      this.transform.apply(this, transform);
+      this.transform.apply(this, matrix);
+    },
+    endAnnotation: function CanvasGraphics_endAnnotation() {
+      this.restore();
+    },
+    paintJpegXObject: function CanvasGraphics_paintJpegXObject(objId, w, h) {
+      var domImage = this.processingType3 ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+      if (!domImage) {
+        (0, _util.warn)('Dependent image isn\'t ready yet');
+        return;
+      }
+
+      this.save();
+      var ctx = this.ctx;
+      ctx.scale(1 / w, -1 / h);
+      ctx.drawImage(domImage, 0, 0, domImage.width, domImage.height, 0, -h, w, h);
+
+      if (this.imageLayer) {
+        var currentTransform = ctx.mozCurrentTransformInverse;
+        var position = this.getCanvasPosition(0, 0);
+        this.imageLayer.appendImage({
+          objId: objId,
+          left: position[0],
+          top: position[1],
+          width: w / currentTransform[0],
+          height: h / currentTransform[3]
+        });
+      }
+
+      this.restore();
+    },
+    paintImageMaskXObject: function CanvasGraphics_paintImageMaskXObject(img) {
+      var ctx = this.ctx;
+      var width = img.width,
+          height = img.height;
+      var fillColor = this.current.fillColor;
+      var isPatternFill = this.current.patternFill;
+      var glyph = this.processingType3;
+
+      if (COMPILE_TYPE3_GLYPHS && glyph && glyph.compiled === undefined) {
+        if (width <= MAX_SIZE_TO_COMPILE && height <= MAX_SIZE_TO_COMPILE) {
+          glyph.compiled = compileType3Glyph({
+            data: img.data,
+            width: width,
+            height: height
+          });
+        } else {
+          glyph.compiled = null;
+        }
+      }
+
+      if (glyph && glyph.compiled) {
+        glyph.compiled(ctx);
+        return;
+      }
+
+      var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
+      var maskCtx = maskCanvas.context;
+      maskCtx.save();
+      putBinaryImageMask(maskCtx, img);
+      maskCtx.globalCompositeOperation = 'source-in';
+      maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
+      maskCtx.fillRect(0, 0, width, height);
+      maskCtx.restore();
+      this.paintInlineImageXObject(maskCanvas.canvas);
+    },
+    paintImageMaskXObjectRepeat: function CanvasGraphics_paintImageMaskXObjectRepeat(imgData, scaleX, scaleY, positions) {
+      var width = imgData.width;
+      var height = imgData.height;
+      var fillColor = this.current.fillColor;
+      var isPatternFill = this.current.patternFill;
+      var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
+      var maskCtx = maskCanvas.context;
+      maskCtx.save();
+      putBinaryImageMask(maskCtx, imgData);
+      maskCtx.globalCompositeOperation = 'source-in';
+      maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
+      maskCtx.fillRect(0, 0, width, height);
+      maskCtx.restore();
+      var ctx = this.ctx;
+
+      for (var i = 0, ii = positions.length; i < ii; i += 2) {
+        ctx.save();
+        ctx.transform(scaleX, 0, 0, scaleY, positions[i], positions[i + 1]);
+        ctx.scale(1, -1);
+        ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
+        ctx.restore();
+      }
+    },
+    paintImageMaskXObjectGroup: function CanvasGraphics_paintImageMaskXObjectGroup(images) {
+      var ctx = this.ctx;
+      var fillColor = this.current.fillColor;
+      var isPatternFill = this.current.patternFill;
+
+      for (var i = 0, ii = images.length; i < ii; i++) {
+        var image = images[i];
+        var width = image.width,
+            height = image.height;
+        var maskCanvas = this.cachedCanvases.getCanvas('maskCanvas', width, height);
+        var maskCtx = maskCanvas.context;
+        maskCtx.save();
+        putBinaryImageMask(maskCtx, image);
+        maskCtx.globalCompositeOperation = 'source-in';
+        maskCtx.fillStyle = isPatternFill ? fillColor.getPattern(maskCtx, this) : fillColor;
+        maskCtx.fillRect(0, 0, width, height);
+        maskCtx.restore();
+        ctx.save();
+        ctx.transform.apply(ctx, image.transform);
+        ctx.scale(1, -1);
+        ctx.drawImage(maskCanvas.canvas, 0, 0, width, height, 0, -1, 1, 1);
+        ctx.restore();
+      }
+    },
+    paintImageXObject: function CanvasGraphics_paintImageXObject(objId) {
+      var imgData = this.processingType3 ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+      if (!imgData) {
+        (0, _util.warn)('Dependent image isn\'t ready yet');
+        return;
+      }
+
+      this.paintInlineImageXObject(imgData);
+    },
+    paintImageXObjectRepeat: function CanvasGraphics_paintImageXObjectRepeat(objId, scaleX, scaleY, positions) {
+      var imgData = this.processingType3 ? this.commonObjs.get(objId) : this.objs.get(objId);
+
+      if (!imgData) {
+        (0, _util.warn)('Dependent image isn\'t ready yet');
+        return;
+      }
+
+      var width = imgData.width;
+      var height = imgData.height;
+      var map = [];
+
+      for (var i = 0, ii = positions.length; i < ii; i += 2) {
+        map.push({
+          transform: [scaleX, 0, 0, scaleY, positions[i], positions[i + 1]],
+          x: 0,
+          y: 0,
+          w: width,
+          h: height
+        });
+      }
+
+      this.paintInlineImageXObjectGroup(imgData, map);
+    },
+    paintInlineImageXObject: function CanvasGraphics_paintInlineImageXObject(imgData) {
+      var width = imgData.width;
+      var height = imgData.height;
+      var ctx = this.ctx;
+      this.save();
+      ctx.scale(1 / width, -1 / height);
+      var currentTransform = ctx.mozCurrentTransformInverse;
+      var a = currentTransform[0],
+          b = currentTransform[1];
+      var widthScale = Math.max(Math.sqrt(a * a + b * b), 1);
+      var c = currentTransform[2],
+          d = currentTransform[3];
+      var heightScale = Math.max(Math.sqrt(c * c + d * d), 1);
+      var imgToPaint, tmpCanvas;
+
+      if (typeof HTMLElement === 'function' && imgData instanceof HTMLElement || !imgData.data) {
+        imgToPaint = imgData;
+      } else {
+        tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', width, height);
+        var tmpCtx = tmpCanvas.context;
+        putBinaryImageData(tmpCtx, imgData);
+        imgToPaint = tmpCanvas.canvas;
+      }
+
+      var paintWidth = width,
+          paintHeight = height;
+      var tmpCanvasId = 'prescale1';
+
+      while (widthScale > 2 && paintWidth > 1 || heightScale > 2 && paintHeight > 1) {
+        var newWidth = paintWidth,
+            newHeight = paintHeight;
+
+        if (widthScale > 2 && paintWidth > 1) {
+          newWidth = Math.ceil(paintWidth / 2);
+          widthScale /= paintWidth / newWidth;
+        }
+
+        if (heightScale > 2 && paintHeight > 1) {
+          newHeight = Math.ceil(paintHeight / 2);
+          heightScale /= paintHeight / newHeight;
+        }
+
+        tmpCanvas = this.cachedCanvases.getCanvas(tmpCanvasId, newWidth, newHeight);
+        tmpCtx = tmpCanvas.context;
+        tmpCtx.clearRect(0, 0, newWidth, newHeight);
+        tmpCtx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, 0, newWidth, newHeight);
+        imgToPaint = tmpCanvas.canvas;
+        paintWidth = newWidth;
+        paintHeight = newHeight;
+        tmpCanvasId = tmpCanvasId === 'prescale1' ? 'prescale2' : 'prescale1';
+      }
+
+      ctx.drawImage(imgToPaint, 0, 0, paintWidth, paintHeight, 0, -height, width, height);
+
+      if (this.imageLayer) {
+        var position = this.getCanvasPosition(0, -height);
+        this.imageLayer.appendImage({
+          imgData: imgData,
+          left: position[0],
+          top: position[1],
+          width: width / currentTransform[0],
+          height: height / currentTransform[3]
+        });
+      }
+
+      this.restore();
+    },
+    paintInlineImageXObjectGroup: function CanvasGraphics_paintInlineImageXObjectGroup(imgData, map) {
+      var ctx = this.ctx;
+      var w = imgData.width;
+      var h = imgData.height;
+      var tmpCanvas = this.cachedCanvases.getCanvas('inlineImage', w, h);
+      var tmpCtx = tmpCanvas.context;
+      putBinaryImageData(tmpCtx, imgData);
+
+      for (var i = 0, ii = map.length; i < ii; i++) {
+        var entry = map[i];
+        ctx.save();
+        ctx.transform.apply(ctx, entry.transform);
+        ctx.scale(1, -1);
+        ctx.drawImage(tmpCanvas.canvas, entry.x, entry.y, entry.w, entry.h, 0, -1, 1, 1);
+
+        if (this.imageLayer) {
+          var position = this.getCanvasPosition(entry.x, entry.y);
+          this.imageLayer.appendImage({
+            imgData: imgData,
+            left: position[0],
+            top: position[1],
+            width: w,
+            height: h
+          });
+        }
+
+        ctx.restore();
+      }
+    },
+    paintSolidColorImageMask: function CanvasGraphics_paintSolidColorImageMask() {
+      this.ctx.fillRect(0, 0, 1, 1);
+    },
+    paintXObject: function CanvasGraphics_paintXObject() {
+      (0, _util.warn)('Unsupported \'paintXObject\' command.');
+    },
+    markPoint: function CanvasGraphics_markPoint(tag) {},
+    markPointProps: function CanvasGraphics_markPointProps(tag, properties) {},
+    beginMarkedContent: function CanvasGraphics_beginMarkedContent(tag) {},
+    beginMarkedContentProps: function CanvasGraphics_beginMarkedContentProps(tag, properties) {},
+    endMarkedContent: function CanvasGraphics_endMarkedContent() {},
+    beginCompat: function CanvasGraphics_beginCompat() {},
+    endCompat: function CanvasGraphics_endCompat() {},
+    consumePath: function CanvasGraphics_consumePath() {
+      var ctx = this.ctx;
+
+      if (this.pendingClip) {
+        if (this.pendingClip === EO_CLIP) {
+          ctx.clip('evenodd');
+        } else {
+          ctx.clip();
+        }
+
+        this.pendingClip = null;
+      }
+
+      ctx.beginPath();
+    },
+    getSinglePixelWidth: function getSinglePixelWidth(scale) {
+      if (this._cachedGetSinglePixelWidth === null) {
+        var inverse = this.ctx.mozCurrentTransformInverse;
+        this._cachedGetSinglePixelWidth = Math.sqrt(Math.max(inverse[0] * inverse[0] + inverse[1] * inverse[1], inverse[2] * inverse[2] + inverse[3] * inverse[3]));
+      }
+
+      return this._cachedGetSinglePixelWidth;
+    },
+    getCanvasPosition: function CanvasGraphics_getCanvasPosition(x, y) {
+      var transform = this.ctx.mozCurrentTransform;
+      return [transform[0] * x + transform[2] * y + transform[4], transform[1] * x + transform[3] * y + transform[5]];
+    }
+  };
+
+  for (var op in _util.OPS) {
+    CanvasGraphics.prototype[_util.OPS[op]] = CanvasGraphics.prototype[op];
+  }
+
+  return CanvasGraphics;
+}();
+
+exports.CanvasGraphics = CanvasGraphics;
+
+/***/ }),
+/* 155 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getShadingPatternFromIR = getShadingPatternFromIR;
+exports.TilingPattern = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+var ShadingIRs = {};
+ShadingIRs.RadialAxial = {
+  fromIR: function RadialAxial_fromIR(raw) {
+    var type = raw[1];
+    var colorStops = raw[2];
+    var p0 = raw[3];
+    var p1 = raw[4];
+    var r0 = raw[5];
+    var r1 = raw[6];
+    return {
+      type: 'Pattern',
+      getPattern: function RadialAxial_getPattern(ctx) {
+        var grad;
+
+        if (type === 'axial') {
+          grad = ctx.createLinearGradient(p0[0], p0[1], p1[0], p1[1]);
+        } else if (type === 'radial') {
+          grad = ctx.createRadialGradient(p0[0], p0[1], r0, p1[0], p1[1], r1);
+        }
+
+        for (var i = 0, ii = colorStops.length; i < ii; ++i) {
+          var c = colorStops[i];
+          grad.addColorStop(c[0], c[1]);
+        }
+
+        return grad;
+      }
+    };
+  }
+};
+
+var createMeshCanvas = function createMeshCanvasClosure() {
+  function drawTriangle(data, context, p1, p2, p3, c1, c2, c3) {
+    var coords = context.coords,
+        colors = context.colors;
+    var bytes = data.data,
+        rowSize = data.width * 4;
+    var tmp;
+
+    if (coords[p1 + 1] > coords[p2 + 1]) {
+      tmp = p1;
+      p1 = p2;
+      p2 = tmp;
+      tmp = c1;
+      c1 = c2;
+      c2 = tmp;
+    }
+
+    if (coords[p2 + 1] > coords[p3 + 1]) {
+      tmp = p2;
+      p2 = p3;
+      p3 = tmp;
+      tmp = c2;
+      c2 = c3;
+      c3 = tmp;
+    }
+
+    if (coords[p1 + 1] > coords[p2 + 1]) {
+      tmp = p1;
+      p1 = p2;
+      p2 = tmp;
+      tmp = c1;
+      c1 = c2;
+      c2 = tmp;
+    }
+
+    var x1 = (coords[p1] + context.offsetX) * context.scaleX;
+    var y1 = (coords[p1 + 1] + context.offsetY) * context.scaleY;
+    var x2 = (coords[p2] + context.offsetX) * context.scaleX;
+    var y2 = (coords[p2 + 1] + context.offsetY) * context.scaleY;
+    var x3 = (coords[p3] + context.offsetX) * context.scaleX;
+    var y3 = (coords[p3 + 1] + context.offsetY) * context.scaleY;
+
+    if (y1 >= y3) {
+      return;
+    }
+
+    var c1r = colors[c1],
+        c1g = colors[c1 + 1],
+        c1b = colors[c1 + 2];
+    var c2r = colors[c2],
+        c2g = colors[c2 + 1],
+        c2b = colors[c2 + 2];
+    var c3r = colors[c3],
+        c3g = colors[c3 + 1],
+        c3b = colors[c3 + 2];
+    var minY = Math.round(y1),
+        maxY = Math.round(y3);
+    var xa, car, cag, cab;
+    var xb, cbr, cbg, cbb;
+    var k;
+
+    for (var y = minY; y <= maxY; y++) {
+      if (y < y2) {
+        k = y < y1 ? 0 : y1 === y2 ? 1 : (y1 - y) / (y1 - y2);
+        xa = x1 - (x1 - x2) * k;
+        car = c1r - (c1r - c2r) * k;
+        cag = c1g - (c1g - c2g) * k;
+        cab = c1b - (c1b - c2b) * k;
+      } else {
+        k = y > y3 ? 1 : y2 === y3 ? 0 : (y2 - y) / (y2 - y3);
+        xa = x2 - (x2 - x3) * k;
+        car = c2r - (c2r - c3r) * k;
+        cag = c2g - (c2g - c3g) * k;
+        cab = c2b - (c2b - c3b) * k;
+      }
+
+      k = y < y1 ? 0 : y > y3 ? 1 : (y1 - y) / (y1 - y3);
+      xb = x1 - (x1 - x3) * k;
+      cbr = c1r - (c1r - c3r) * k;
+      cbg = c1g - (c1g - c3g) * k;
+      cbb = c1b - (c1b - c3b) * k;
+      var x1_ = Math.round(Math.min(xa, xb));
+      var x2_ = Math.round(Math.max(xa, xb));
+      var j = rowSize * y + x1_ * 4;
+
+      for (var x = x1_; x <= x2_; x++) {
+        k = (xa - x) / (xa - xb);
+        k = k < 0 ? 0 : k > 1 ? 1 : k;
+        bytes[j++] = car - (car - cbr) * k | 0;
+        bytes[j++] = cag - (cag - cbg) * k | 0;
+        bytes[j++] = cab - (cab - cbb) * k | 0;
+        bytes[j++] = 255;
+      }
+    }
+  }
+
+  function drawFigure(data, figure, context) {
+    var ps = figure.coords;
+    var cs = figure.colors;
+    var i, ii;
+
+    switch (figure.type) {
+      case 'lattice':
+        var verticesPerRow = figure.verticesPerRow;
+        var rows = Math.floor(ps.length / verticesPerRow) - 1;
+        var cols = verticesPerRow - 1;
+
+        for (i = 0; i < rows; i++) {
+          var q = i * verticesPerRow;
+
+          for (var j = 0; j < cols; j++, q++) {
+            drawTriangle(data, context, ps[q], ps[q + 1], ps[q + verticesPerRow], cs[q], cs[q + 1], cs[q + verticesPerRow]);
+            drawTriangle(data, context, ps[q + verticesPerRow + 1], ps[q + 1], ps[q + verticesPerRow], cs[q + verticesPerRow + 1], cs[q + 1], cs[q + verticesPerRow]);
+          }
+        }
+
+        break;
+
+      case 'triangles':
+        for (i = 0, ii = ps.length; i < ii; i += 3) {
+          drawTriangle(data, context, ps[i], ps[i + 1], ps[i + 2], cs[i], cs[i + 1], cs[i + 2]);
+        }
+
+        break;
+
+      default:
+        throw new Error('illegal figure');
+    }
+  }
+
+  function createMeshCanvas(bounds, combinesScale, coords, colors, figures, backgroundColor, cachedCanvases, webGLContext) {
+    var EXPECTED_SCALE = 1.1;
+    var MAX_PATTERN_SIZE = 3000;
+    var BORDER_SIZE = 2;
+    var offsetX = Math.floor(bounds[0]);
+    var offsetY = Math.floor(bounds[1]);
+    var boundsWidth = Math.ceil(bounds[2]) - offsetX;
+    var boundsHeight = Math.ceil(bounds[3]) - offsetY;
+    var width = Math.min(Math.ceil(Math.abs(boundsWidth * combinesScale[0] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+    var height = Math.min(Math.ceil(Math.abs(boundsHeight * combinesScale[1] * EXPECTED_SCALE)), MAX_PATTERN_SIZE);
+    var scaleX = boundsWidth / width;
+    var scaleY = boundsHeight / height;
+    var context = {
+      coords: coords,
+      colors: colors,
+      offsetX: -offsetX,
+      offsetY: -offsetY,
+      scaleX: 1 / scaleX,
+      scaleY: 1 / scaleY
+    };
+    var paddedWidth = width + BORDER_SIZE * 2;
+    var paddedHeight = height + BORDER_SIZE * 2;
+    var canvas, tmpCanvas, i, ii;
+
+    if (webGLContext.isEnabled) {
+      canvas = webGLContext.drawFigures({
+        width: width,
+        height: height,
+        backgroundColor: backgroundColor,
+        figures: figures,
+        context: context
+      });
+      tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
+      tmpCanvas.context.drawImage(canvas, BORDER_SIZE, BORDER_SIZE);
+      canvas = tmpCanvas.canvas;
+    } else {
+      tmpCanvas = cachedCanvases.getCanvas('mesh', paddedWidth, paddedHeight, false);
+      var tmpCtx = tmpCanvas.context;
+      var data = tmpCtx.createImageData(width, height);
+
+      if (backgroundColor) {
+        var bytes = data.data;
+
+        for (i = 0, ii = bytes.length; i < ii; i += 4) {
+          bytes[i] = backgroundColor[0];
+          bytes[i + 1] = backgroundColor[1];
+          bytes[i + 2] = backgroundColor[2];
+          bytes[i + 3] = 255;
+        }
+      }
+
+      for (i = 0; i < figures.length; i++) {
+        drawFigure(data, figures[i], context);
+      }
+
+      tmpCtx.putImageData(data, BORDER_SIZE, BORDER_SIZE);
+      canvas = tmpCanvas.canvas;
+    }
+
+    return {
+      canvas: canvas,
+      offsetX: offsetX - BORDER_SIZE * scaleX,
+      offsetY: offsetY - BORDER_SIZE * scaleY,
+      scaleX: scaleX,
+      scaleY: scaleY
+    };
+  }
+
+  return createMeshCanvas;
+}();
+
+ShadingIRs.Mesh = {
+  fromIR: function Mesh_fromIR(raw) {
+    var coords = raw[2];
+    var colors = raw[3];
+    var figures = raw[4];
+    var bounds = raw[5];
+    var matrix = raw[6];
+    var background = raw[8];
+    return {
+      type: 'Pattern',
+      getPattern: function Mesh_getPattern(ctx, owner, shadingFill) {
+        var scale;
+
+        if (shadingFill) {
+          scale = _util.Util.singularValueDecompose2dScale(ctx.mozCurrentTransform);
+        } else {
+          scale = _util.Util.singularValueDecompose2dScale(owner.baseTransform);
+
+          if (matrix) {
+            var matrixScale = _util.Util.singularValueDecompose2dScale(matrix);
+
+            scale = [scale[0] * matrixScale[0], scale[1] * matrixScale[1]];
+          }
+        }
+
+        var temporaryPatternCanvas = createMeshCanvas(bounds, scale, coords, colors, figures, shadingFill ? null : background, owner.cachedCanvases, owner.webGLContext);
+
+        if (!shadingFill) {
+          ctx.setTransform.apply(ctx, owner.baseTransform);
+
+          if (matrix) {
+            ctx.transform.apply(ctx, matrix);
+          }
+        }
+
+        ctx.translate(temporaryPatternCanvas.offsetX, temporaryPatternCanvas.offsetY);
+        ctx.scale(temporaryPatternCanvas.scaleX, temporaryPatternCanvas.scaleY);
+        return ctx.createPattern(temporaryPatternCanvas.canvas, 'no-repeat');
+      }
+    };
+  }
+};
+ShadingIRs.Dummy = {
+  fromIR: function Dummy_fromIR() {
+    return {
+      type: 'Pattern',
+      getPattern: function Dummy_fromIR_getPattern() {
+        return 'hotpink';
+      }
+    };
+  }
+};
+
+function getShadingPatternFromIR(raw) {
+  var shadingIR = ShadingIRs[raw[0]];
+
+  if (!shadingIR) {
+    throw new Error("Unknown IR type: ".concat(raw[0]));
+  }
+
+  return shadingIR.fromIR(raw);
+}
+
+var TilingPattern = function TilingPatternClosure() {
+  var PaintType = {
+    COLORED: 1,
+    UNCOLORED: 2
+  };
+  var MAX_PATTERN_SIZE = 3000;
+
+  function TilingPattern(IR, color, ctx, canvasGraphicsFactory, baseTransform) {
+    this.operatorList = IR[2];
+    this.matrix = IR[3] || [1, 0, 0, 1, 0, 0];
+    this.bbox = IR[4];
+    this.xstep = IR[5];
+    this.ystep = IR[6];
+    this.paintType = IR[7];
+    this.tilingType = IR[8];
+    this.color = color;
+    this.canvasGraphicsFactory = canvasGraphicsFactory;
+    this.baseTransform = baseTransform;
+    this.type = 'Pattern';
+    this.ctx = ctx;
+  }
+
+  TilingPattern.prototype = {
+    createPatternCanvas: function TilinPattern_createPatternCanvas(owner) {
+      var operatorList = this.operatorList;
+      var bbox = this.bbox;
+      var xstep = this.xstep;
+      var ystep = this.ystep;
+      var paintType = this.paintType;
+      var tilingType = this.tilingType;
+      var color = this.color;
+      var canvasGraphicsFactory = this.canvasGraphicsFactory;
+      (0, _util.info)('TilingType: ' + tilingType);
+      var x0 = bbox[0],
+          y0 = bbox[1],
+          x1 = bbox[2],
+          y1 = bbox[3];
+
+      var matrixScale = _util.Util.singularValueDecompose2dScale(this.matrix);
+
+      var curMatrixScale = _util.Util.singularValueDecompose2dScale(this.baseTransform);
+
+      var combinedScale = [matrixScale[0] * curMatrixScale[0], matrixScale[1] * curMatrixScale[1]];
+      var dimx = this.getSizeAndScale(xstep, this.ctx.canvas.width, combinedScale[0]);
+      var dimy = this.getSizeAndScale(ystep, this.ctx.canvas.height, combinedScale[1]);
+      var tmpCanvas = owner.cachedCanvases.getCanvas('pattern', dimx.size, dimy.size, true);
+      var tmpCtx = tmpCanvas.context;
+      var graphics = canvasGraphicsFactory.createCanvasGraphics(tmpCtx);
+      graphics.groupLevel = owner.groupLevel;
+      this.setFillAndStrokeStyleToContext(graphics, paintType, color);
+      graphics.transform(dimx.scale, 0, 0, dimy.scale, 0, 0);
+      graphics.transform(1, 0, 0, 1, -x0, -y0);
+      this.clipBbox(graphics, bbox, x0, y0, x1, y1);
+      graphics.executeOperatorList(operatorList);
+      this.ctx.transform(1, 0, 0, 1, x0, y0);
+      this.ctx.scale(1 / dimx.scale, 1 / dimy.scale);
+      return tmpCanvas.canvas;
+    },
+    getSizeAndScale: function TilingPattern_getSizeAndScale(step, realOutputSize, scale) {
+      step = Math.abs(step);
+      var maxSize = Math.max(MAX_PATTERN_SIZE, realOutputSize);
+      var size = Math.ceil(step * scale);
+
+      if (size >= maxSize) {
+        size = maxSize;
+      } else {
+        scale = size / step;
+      }
+
+      return {
+        scale: scale,
+        size: size
+      };
+    },
+    clipBbox: function clipBbox(graphics, bbox, x0, y0, x1, y1) {
+      if (Array.isArray(bbox) && bbox.length === 4) {
+        var bboxWidth = x1 - x0;
+        var bboxHeight = y1 - y0;
+        graphics.ctx.rect(x0, y0, bboxWidth, bboxHeight);
+        graphics.clip();
+        graphics.endPath();
+      }
+    },
+    setFillAndStrokeStyleToContext: function setFillAndStrokeStyleToContext(graphics, paintType, color) {
+      var context = graphics.ctx,
+          current = graphics.current;
+
+      switch (paintType) {
+        case PaintType.COLORED:
+          var ctx = this.ctx;
+          context.fillStyle = ctx.fillStyle;
+          context.strokeStyle = ctx.strokeStyle;
+          current.fillColor = ctx.fillStyle;
+          current.strokeColor = ctx.strokeStyle;
+          break;
+
+        case PaintType.UNCOLORED:
+          var cssColor = _util.Util.makeCssRgb(color[0], color[1], color[2]);
+
+          context.fillStyle = cssColor;
+          context.strokeStyle = cssColor;
+          current.fillColor = cssColor;
+          current.strokeColor = cssColor;
+          break;
+
+        default:
+          throw new _util.FormatError("Unsupported paint type: ".concat(paintType));
+      }
+    },
+    getPattern: function TilingPattern_getPattern(ctx, owner) {
+      ctx = this.ctx;
+      ctx.setTransform.apply(ctx, this.baseTransform);
+      ctx.transform.apply(ctx, this.matrix);
+      var temporaryPatternCanvas = this.createPatternCanvas(owner);
+      return ctx.createPattern(temporaryPatternCanvas, 'repeat');
+    }
+  };
+  return TilingPattern;
+}();
+
+exports.TilingPattern = TilingPattern;
+
+/***/ }),
+/* 156 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.GlobalWorkerOptions = void 0;
+var GlobalWorkerOptions = Object.create(null);
+exports.GlobalWorkerOptions = GlobalWorkerOptions;
+GlobalWorkerOptions.workerPort = GlobalWorkerOptions.workerPort === undefined ? null : GlobalWorkerOptions.workerPort;
+GlobalWorkerOptions.workerSrc = GlobalWorkerOptions.workerSrc === undefined ? '' : GlobalWorkerOptions.workerSrc;
+
+/***/ }),
+/* 157 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.MessageHandler = MessageHandler;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function resolveCall(_x, _x2) {
+  return _resolveCall.apply(this, arguments);
+}
+
+function _resolveCall() {
+  _resolveCall = _asyncToGenerator(
+  /*#__PURE__*/
+  _regenerator["default"].mark(function _callee(fn, args) {
+    var thisArg,
+        _args = arguments;
+    return _regenerator["default"].wrap(function _callee$(_context) {
+      while (1) {
+        switch (_context.prev = _context.next) {
+          case 0:
+            thisArg = _args.length > 2 && _args[2] !== undefined ? _args[2] : null;
+
+            if (fn) {
+              _context.next = 3;
+              break;
+            }
+
+            return _context.abrupt("return", undefined);
+
+          case 3:
+            return _context.abrupt("return", fn.apply(thisArg, args));
+
+          case 4:
+          case "end":
+            return _context.stop();
+        }
+      }
+    }, _callee);
+  }));
+  return _resolveCall.apply(this, arguments);
+}
+
+function wrapReason(reason) {
+  if (_typeof(reason) !== 'object') {
+    return reason;
+  }
+
+  switch (reason.name) {
+    case 'AbortException':
+      return new _util.AbortException(reason.message);
+
+    case 'MissingPDFException':
+      return new _util.MissingPDFException(reason.message);
+
+    case 'UnexpectedResponseException':
+      return new _util.UnexpectedResponseException(reason.message, reason.status);
+
+    default:
+      return new _util.UnknownErrorException(reason.message, reason.details);
+  }
+}
+
+function makeReasonSerializable(reason) {
+  if (!(reason instanceof Error) || reason instanceof _util.AbortException || reason instanceof _util.MissingPDFException || reason instanceof _util.UnexpectedResponseException || reason instanceof _util.UnknownErrorException) {
+    return reason;
+  }
+
+  return new _util.UnknownErrorException(reason.message, reason.toString());
+}
+
+function resolveOrReject(capability, success, reason) {
+  if (success) {
+    capability.resolve();
+  } else {
+    capability.reject(reason);
+  }
+}
+
+function finalize(promise) {
+  return Promise.resolve(promise)["catch"](function () {});
+}
+
+function MessageHandler(sourceName, targetName, comObj) {
+  var _this = this;
+
+  this.sourceName = sourceName;
+  this.targetName = targetName;
+  this.comObj = comObj;
+  this.callbackId = 1;
+  this.streamId = 1;
+  this.postMessageTransfers = true;
+  this.streamSinks = Object.create(null);
+  this.streamControllers = Object.create(null);
+  var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
+  var ah = this.actionHandler = Object.create(null);
+
+  this._onComObjOnMessage = function (event) {
+    var data = event.data;
+
+    if (data.targetName !== _this.sourceName) {
+      return;
+    }
+
+    if (data.stream) {
+      _this._processStreamMessage(data);
+    } else if (data.isReply) {
+      var callbackId = data.callbackId;
+
+      if (data.callbackId in callbacksCapabilities) {
+        var callback = callbacksCapabilities[callbackId];
+        delete callbacksCapabilities[callbackId];
+
+        if ('error' in data) {
+          callback.reject(wrapReason(data.error));
+        } else {
+          callback.resolve(data.data);
+        }
+      } else {
+        throw new Error("Cannot resolve callback ".concat(callbackId));
+      }
+    } else if (data.action in ah) {
+      var action = ah[data.action];
+
+      if (data.callbackId) {
+        var _sourceName = _this.sourceName;
+        var _targetName = data.sourceName;
+        Promise.resolve().then(function () {
+          return action[0].call(action[1], data.data);
+        }).then(function (result) {
+          comObj.postMessage({
+            sourceName: _sourceName,
+            targetName: _targetName,
+            isReply: true,
+            callbackId: data.callbackId,
+            data: result
+          });
+        }, function (reason) {
+          comObj.postMessage({
+            sourceName: _sourceName,
+            targetName: _targetName,
+            isReply: true,
+            callbackId: data.callbackId,
+            error: makeReasonSerializable(reason)
+          });
+        });
+      } else if (data.streamId) {
+        _this._createStreamSink(data);
+      } else {
+        action[0].call(action[1], data.data);
+      }
+    } else {
+      throw new Error("Unknown action from worker: ".concat(data.action));
+    }
+  };
+
+  comObj.addEventListener('message', this._onComObjOnMessage);
+}
+
+MessageHandler.prototype = {
+  on: function on(actionName, handler, scope) {
+    var ah = this.actionHandler;
+
+    if (ah[actionName]) {
+      throw new Error("There is already an actionName called \"".concat(actionName, "\""));
+    }
+
+    ah[actionName] = [handler, scope];
+  },
+  send: function send(actionName, data, transfers) {
+    var message = {
+      sourceName: this.sourceName,
+      targetName: this.targetName,
+      action: actionName,
+      data: data
+    };
+    this.postMessage(message, transfers);
+  },
+  sendWithPromise: function sendWithPromise(actionName, data, transfers) {
+    var callbackId = this.callbackId++;
+    var message = {
+      sourceName: this.sourceName,
+      targetName: this.targetName,
+      action: actionName,
+      data: data,
+      callbackId: callbackId
+    };
+    var capability = (0, _util.createPromiseCapability)();
+    this.callbacksCapabilities[callbackId] = capability;
+
+    try {
+      this.postMessage(message, transfers);
+    } catch (e) {
+      capability.reject(e);
+    }
+
+    return capability.promise;
+  },
+  sendWithStream: function sendWithStream(actionName, data, queueingStrategy, transfers) {
+    var _this2 = this;
+
+    var streamId = this.streamId++;
+    var sourceName = this.sourceName;
+    var targetName = this.targetName;
+    return new _util.ReadableStream({
+      start: function start(controller) {
+        var startCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId] = {
+          controller: controller,
+          startCall: startCapability,
+          isClosed: false
+        };
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          action: actionName,
+          streamId: streamId,
+          data: data,
+          desiredSize: controller.desiredSize
+        });
+
+        return startCapability.promise;
+      },
+      pull: function pull(controller) {
+        var pullCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId].pullCall = pullCapability;
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          stream: 'pull',
+          streamId: streamId,
+          desiredSize: controller.desiredSize
+        });
+
+        return pullCapability.promise;
+      },
+      cancel: function cancel(reason) {
+        var cancelCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId].cancelCall = cancelCapability;
+        _this2.streamControllers[streamId].isClosed = true;
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          stream: 'cancel',
+          reason: reason,
+          streamId: streamId
+        });
+
+        return cancelCapability.promise;
+      }
+    }, queueingStrategy);
+  },
+  _createStreamSink: function _createStreamSink(data) {
+    var _this3 = this;
+
+    var self = this;
+    var action = this.actionHandler[data.action];
+    var streamId = data.streamId;
+    var desiredSize = data.desiredSize;
+    var sourceName = this.sourceName;
+    var targetName = data.sourceName;
+    var capability = (0, _util.createPromiseCapability)();
+
+    var sendStreamRequest = function sendStreamRequest(_ref) {
+      var stream = _ref.stream,
+          chunk = _ref.chunk,
+          transfers = _ref.transfers,
+          success = _ref.success,
+          reason = _ref.reason;
+
+      _this3.postMessage({
+        sourceName: sourceName,
+        targetName: targetName,
+        stream: stream,
+        streamId: streamId,
+        chunk: chunk,
+        success: success,
+        reason: reason
+      }, transfers);
+    };
+
+    var streamSink = {
+      enqueue: function enqueue(chunk) {
+        var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+        var transfers = arguments.length > 2 ? arguments[2] : undefined;
+
+        if (this.isCancelled) {
+          return;
+        }
+
+        var lastDesiredSize = this.desiredSize;
+        this.desiredSize -= size;
+
+        if (lastDesiredSize > 0 && this.desiredSize <= 0) {
+          this.sinkCapability = (0, _util.createPromiseCapability)();
+          this.ready = this.sinkCapability.promise;
+        }
+
+        sendStreamRequest({
+          stream: 'enqueue',
+          chunk: chunk,
+          transfers: transfers
+        });
+      },
+      close: function close() {
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        sendStreamRequest({
+          stream: 'close'
+        });
+        delete self.streamSinks[streamId];
+      },
+      error: function error(reason) {
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        sendStreamRequest({
+          stream: 'error',
+          reason: reason
+        });
+      },
+      sinkCapability: capability,
+      onPull: null,
+      onCancel: null,
+      isCancelled: false,
+      desiredSize: desiredSize,
+      ready: null
+    };
+    streamSink.sinkCapability.resolve();
+    streamSink.ready = streamSink.sinkCapability.promise;
+    this.streamSinks[streamId] = streamSink;
+    resolveCall(action[0], [data.data, streamSink], action[1]).then(function () {
+      sendStreamRequest({
+        stream: 'start_complete',
+        success: true
+      });
+    }, function (reason) {
+      sendStreamRequest({
+        stream: 'start_complete',
+        success: false,
+        reason: reason
+      });
+    });
+  },
+  _processStreamMessage: function _processStreamMessage(data) {
+    var _this4 = this;
+
+    var sourceName = this.sourceName;
+    var targetName = data.sourceName;
+    var streamId = data.streamId;
+
+    var sendStreamResponse = function sendStreamResponse(_ref2) {
+      var stream = _ref2.stream,
+          success = _ref2.success,
+          reason = _ref2.reason;
+
+      _this4.comObj.postMessage({
+        sourceName: sourceName,
+        targetName: targetName,
+        stream: stream,
+        success: success,
+        streamId: streamId,
+        reason: reason
+      });
+    };
+
+    var deleteStreamController = function deleteStreamController() {
+      Promise.all([_this4.streamControllers[data.streamId].startCall, _this4.streamControllers[data.streamId].pullCall, _this4.streamControllers[data.streamId].cancelCall].map(function (capability) {
+        return capability && finalize(capability.promise);
+      })).then(function () {
+        delete _this4.streamControllers[data.streamId];
+      });
+    };
+
+    switch (data.stream) {
+      case 'start_complete':
+        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
+        break;
+
+      case 'pull_complete':
+        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
+        break;
+
+      case 'pull':
+        if (!this.streamSinks[data.streamId]) {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: true
+          });
+          break;
+        }
+
+        if (this.streamSinks[data.streamId].desiredSize <= 0 && data.desiredSize > 0) {
+          this.streamSinks[data.streamId].sinkCapability.resolve();
+        }
+
+        this.streamSinks[data.streamId].desiredSize = data.desiredSize;
+        resolveCall(this.streamSinks[data.streamId].onPull).then(function () {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: true
+          });
+        }, function (reason) {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: false,
+            reason: reason
+          });
+        });
+        break;
+
+      case 'enqueue':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'enqueue should have stream controller');
+
+        if (!this.streamControllers[data.streamId].isClosed) {
+          this.streamControllers[data.streamId].controller.enqueue(data.chunk);
+        }
+
+        break;
+
+      case 'close':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'close should have stream controller');
+
+        if (this.streamControllers[data.streamId].isClosed) {
+          break;
+        }
+
+        this.streamControllers[data.streamId].isClosed = true;
+        this.streamControllers[data.streamId].controller.close();
+        deleteStreamController();
+        break;
+
+      case 'error':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'error should have stream controller');
+        this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
+        deleteStreamController();
+        break;
+
+      case 'cancel_complete':
+        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
+        deleteStreamController();
+        break;
+
+      case 'cancel':
+        if (!this.streamSinks[data.streamId]) {
+          break;
+        }
+
+        resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(function () {
+          sendStreamResponse({
+            stream: 'cancel_complete',
+            success: true
+          });
+        }, function (reason) {
+          sendStreamResponse({
+            stream: 'cancel_complete',
+            success: false,
+            reason: reason
+          });
+        });
+        this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
+        this.streamSinks[data.streamId].isCancelled = true;
+        delete this.streamSinks[data.streamId];
+        break;
+
+      default:
+        throw new Error('Unexpected stream case');
+    }
+  },
+  postMessage: function postMessage(message, transfers) {
+    if (transfers && this.postMessageTransfers) {
+      this.comObj.postMessage(message, transfers);
+    } else {
+      this.comObj.postMessage(message);
+    }
+  },
+  destroy: function destroy() {
+    this.comObj.removeEventListener('message', this._onComObjOnMessage);
+  }
+};
+
+/***/ }),
+/* 158 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Metadata = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+var _xml_parser = __w_pdfjs_require__(159);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var Metadata =
+/*#__PURE__*/
+function () {
+  function Metadata(data) {
+    _classCallCheck(this, Metadata);
+
+    (0, _util.assert)(typeof data === 'string', 'Metadata: input is not a string');
+    data = this._repair(data);
+    var parser = new _xml_parser.SimpleXMLParser();
+    var xmlDocument = parser.parseFromString(data);
+    this._metadata = Object.create(null);
+
+    if (xmlDocument) {
+      this._parse(xmlDocument);
+    }
+  }
+
+  _createClass(Metadata, [{
+    key: "_repair",
+    value: function _repair(data) {
+      return data.replace(/^([^<]+)/, '').replace(/>\\376\\377([^<]+)/g, function (all, codes) {
+        var bytes = codes.replace(/\\([0-3])([0-7])([0-7])/g, function (code, d1, d2, d3) {
+          return String.fromCharCode(d1 * 64 + d2 * 8 + d3 * 1);
+        }).replace(/&(amp|apos|gt|lt|quot);/g, function (str, name) {
+          switch (name) {
+            case 'amp':
+              return '&';
+
+            case 'apos':
+              return '\'';
+
+            case 'gt':
+              return '>';
+
+            case 'lt':
+              return '<';
+
+            case 'quot':
+              return '\"';
+          }
+
+          throw new Error("_repair: ".concat(name, " isn't defined."));
+        });
+        var chars = '';
+
+        for (var i = 0, ii = bytes.length; i < ii; i += 2) {
+          var code = bytes.charCodeAt(i) * 256 + bytes.charCodeAt(i + 1);
+
+          if (code >= 32 && code < 127 && code !== 60 && code !== 62 && code !== 38) {
+            chars += String.fromCharCode(code);
+          } else {
+            chars += '&#x' + (0x10000 + code).toString(16).substring(1) + ';';
+          }
+        }
+
+        return '>' + chars;
+      });
+    }
+  }, {
+    key: "_parse",
+    value: function _parse(xmlDocument) {
+      var rdf = xmlDocument.documentElement;
+
+      if (rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
+        rdf = rdf.firstChild;
+
+        while (rdf && rdf.nodeName.toLowerCase() !== 'rdf:rdf') {
+          rdf = rdf.nextSibling;
+        }
+      }
+
+      var nodeName = rdf ? rdf.nodeName.toLowerCase() : null;
+
+      if (!rdf || nodeName !== 'rdf:rdf' || !rdf.hasChildNodes()) {
+        return;
+      }
+
+      var children = rdf.childNodes;
+
+      for (var i = 0, ii = children.length; i < ii; i++) {
+        var desc = children[i];
+
+        if (desc.nodeName.toLowerCase() !== 'rdf:description') {
+          continue;
+        }
+
+        for (var j = 0, jj = desc.childNodes.length; j < jj; j++) {
+          if (desc.childNodes[j].nodeName.toLowerCase() !== '#text') {
+            var entry = desc.childNodes[j];
+            var name = entry.nodeName.toLowerCase();
+            this._metadata[name] = entry.textContent.trim();
+          }
+        }
+      }
+    }
+  }, {
+    key: "get",
+    value: function get(name) {
+      var data = this._metadata[name];
+      return typeof data !== 'undefined' ? data : null;
+    }
+  }, {
+    key: "getAll",
+    value: function getAll() {
+      return this._metadata;
+    }
+  }, {
+    key: "has",
+    value: function has(name) {
+      return typeof this._metadata[name] !== 'undefined';
+    }
+  }]);
+
+  return Metadata;
+}();
+
+exports.Metadata = Metadata;
+
+/***/ }),
+/* 159 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.SimpleXMLParser = void 0;
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
+
+function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var XMLParserErrorCode = {
+  NoError: 0,
+  EndOfDocument: -1,
+  UnterminatedCdat: -2,
+  UnterminatedXmlDeclaration: -3,
+  UnterminatedDoctypeDeclaration: -4,
+  UnterminatedComment: -5,
+  MalformedElement: -6,
+  OutOfMemory: -7,
+  UnterminatedAttributeValue: -8,
+  UnterminatedElement: -9,
+  ElementNeverBegun: -10
+};
+
+function isWhitespace(s, index) {
+  var ch = s[index];
+  return ch === ' ' || ch === '\n' || ch === '\r' || ch === '\t';
+}
+
+function isWhitespaceString(s) {
+  for (var i = 0, ii = s.length; i < ii; i++) {
+    if (!isWhitespace(s, i)) {
+      return false;
+    }
+  }
+
+  return true;
+}
+
+var XMLParserBase =
+/*#__PURE__*/
+function () {
+  function XMLParserBase() {
+    _classCallCheck(this, XMLParserBase);
+  }
+
+  _createClass(XMLParserBase, [{
+    key: "_resolveEntities",
+    value: function _resolveEntities(s) {
+      var _this = this;
+
+      return s.replace(/&([^;]+);/g, function (all, entity) {
+        if (entity.substring(0, 2) === '#x') {
+          return String.fromCharCode(parseInt(entity.substring(2), 16));
+        } else if (entity.substring(0, 1) === '#') {
+          return String.fromCharCode(parseInt(entity.substring(1), 10));
+        }
+
+        switch (entity) {
+          case 'lt':
+            return '<';
+
+          case 'gt':
+            return '>';
+
+          case 'amp':
+            return '&';
+
+          case 'quot':
+            return '\"';
+        }
+
+        return _this.onResolveEntity(entity);
+      });
+    }
+  }, {
+    key: "_parseContent",
+    value: function _parseContent(s, start) {
+      var pos = start,
+          name,
+          attributes = [];
+
+      function skipWs() {
+        while (pos < s.length && isWhitespace(s, pos)) {
+          ++pos;
+        }
+      }
+
+      while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
+        ++pos;
+      }
+
+      name = s.substring(start, pos);
+      skipWs();
+
+      while (pos < s.length && s[pos] !== '>' && s[pos] !== '/' && s[pos] !== '?') {
+        skipWs();
+        var attrName = '',
+            attrValue = '';
+
+        while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '=') {
+          attrName += s[pos];
+          ++pos;
+        }
+
+        skipWs();
+
+        if (s[pos] !== '=') {
+          return null;
+        }
+
+        ++pos;
+        skipWs();
+        var attrEndChar = s[pos];
+
+        if (attrEndChar !== '\"' && attrEndChar !== '\'') {
+          return null;
+        }
+
+        var attrEndIndex = s.indexOf(attrEndChar, ++pos);
+
+        if (attrEndIndex < 0) {
+          return null;
+        }
+
+        attrValue = s.substring(pos, attrEndIndex);
+        attributes.push({
+          name: attrName,
+          value: this._resolveEntities(attrValue)
+        });
+        pos = attrEndIndex + 1;
+        skipWs();
+      }
+
+      return {
+        name: name,
+        attributes: attributes,
+        parsed: pos - start
+      };
+    }
+  }, {
+    key: "_parseProcessingInstruction",
+    value: function _parseProcessingInstruction(s, start) {
+      var pos = start,
+          name,
+          value;
+
+      function skipWs() {
+        while (pos < s.length && isWhitespace(s, pos)) {
+          ++pos;
+        }
+      }
+
+      while (pos < s.length && !isWhitespace(s, pos) && s[pos] !== '>' && s[pos] !== '/') {
+        ++pos;
+      }
+
+      name = s.substring(start, pos);
+      skipWs();
+      var attrStart = pos;
+
+      while (pos < s.length && (s[pos] !== '?' || s[pos + 1] !== '>')) {
+        ++pos;
+      }
+
+      value = s.substring(attrStart, pos);
+      return {
+        name: name,
+        value: value,
+        parsed: pos - start
+      };
+    }
+  }, {
+    key: "parseXml",
+    value: function parseXml(s) {
+      var i = 0;
+
+      while (i < s.length) {
+        var ch = s[i];
+        var j = i;
+
+        if (ch === '<') {
+          ++j;
+          var ch2 = s[j];
+          var q = void 0;
+
+          switch (ch2) {
+            case '/':
+              ++j;
+              q = s.indexOf('>', j);
+
+              if (q < 0) {
+                this.onError(XMLParserErrorCode.UnterminatedElement);
+                return;
+              }
+
+              this.onEndElement(s.substring(j, q));
+              j = q + 1;
+              break;
+
+            case '?':
+              ++j;
+
+              var pi = this._parseProcessingInstruction(s, j);
+
+              if (s.substring(j + pi.parsed, j + pi.parsed + 2) !== '?>') {
+                this.onError(XMLParserErrorCode.UnterminatedXmlDeclaration);
+                return;
+              }
+
+              this.onPi(pi.name, pi.value);
+              j += pi.parsed + 2;
+              break;
+
+            case '!':
+              if (s.substring(j + 1, j + 3) === '--') {
+                q = s.indexOf('-->', j + 3);
+
+                if (q < 0) {
+                  this.onError(XMLParserErrorCode.UnterminatedComment);
+                  return;
+                }
+
+                this.onComment(s.substring(j + 3, q));
+                j = q + 3;
+              } else if (s.substring(j + 1, j + 8) === '[CDATA[') {
+                q = s.indexOf(']]>', j + 8);
+
+                if (q < 0) {
+                  this.onError(XMLParserErrorCode.UnterminatedCdat);
+                  return;
+                }
+
+                this.onCdata(s.substring(j + 8, q));
+                j = q + 3;
+              } else if (s.substring(j + 1, j + 8) === 'DOCTYPE') {
+                var q2 = s.indexOf('[', j + 8);
+                var complexDoctype = false;
+                q = s.indexOf('>', j + 8);
+
+                if (q < 0) {
+                  this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
+                  return;
+                }
+
+                if (q2 > 0 && q > q2) {
+                  q = s.indexOf(']>', j + 8);
+
+                  if (q < 0) {
+                    this.onError(XMLParserErrorCode.UnterminatedDoctypeDeclaration);
+                    return;
+                  }
+
+                  complexDoctype = true;
+                }
+
+                var doctypeContent = s.substring(j + 8, q + (complexDoctype ? 1 : 0));
+                this.onDoctype(doctypeContent);
+                j = q + (complexDoctype ? 2 : 1);
+              } else {
+                this.onError(XMLParserErrorCode.MalformedElement);
+                return;
+              }
+
+              break;
+
+            default:
+              var content = this._parseContent(s, j);
+
+              if (content === null) {
+                this.onError(XMLParserErrorCode.MalformedElement);
+                return;
+              }
+
+              var isClosed = false;
+
+              if (s.substring(j + content.parsed, j + content.parsed + 2) === '/>') {
+                isClosed = true;
+              } else if (s.substring(j + content.parsed, j + content.parsed + 1) !== '>') {
+                this.onError(XMLParserErrorCode.UnterminatedElement);
+                return;
+              }
+
+              this.onBeginElement(content.name, content.attributes, isClosed);
+              j += content.parsed + (isClosed ? 2 : 1);
+              break;
+          }
+        } else {
+          while (j < s.length && s[j] !== '<') {
+            j++;
+          }
+
+          var text = s.substring(i, j);
+          this.onText(this._resolveEntities(text));
+        }
+
+        i = j;
+      }
+    }
+  }, {
+    key: "onResolveEntity",
+    value: function onResolveEntity(name) {
+      return "&".concat(name, ";");
+    }
+  }, {
+    key: "onPi",
+    value: function onPi(name, value) {}
+  }, {
+    key: "onComment",
+    value: function onComment(text) {}
+  }, {
+    key: "onCdata",
+    value: function onCdata(text) {}
+  }, {
+    key: "onDoctype",
+    value: function onDoctype(doctypeContent) {}
+  }, {
+    key: "onText",
+    value: function onText(text) {}
+  }, {
+    key: "onBeginElement",
+    value: function onBeginElement(name, attributes, isEmpty) {}
+  }, {
+    key: "onEndElement",
+    value: function onEndElement(name) {}
+  }, {
+    key: "onError",
+    value: function onError(code) {}
+  }]);
+
+  return XMLParserBase;
+}();
+
+var SimpleDOMNode =
+/*#__PURE__*/
+function () {
+  function SimpleDOMNode(nodeName, nodeValue) {
+    _classCallCheck(this, SimpleDOMNode);
+
+    this.nodeName = nodeName;
+    this.nodeValue = nodeValue;
+    Object.defineProperty(this, 'parentNode', {
+      value: null,
+      writable: true
+    });
+  }
+
+  _createClass(SimpleDOMNode, [{
+    key: "hasChildNodes",
+    value: function hasChildNodes() {
+      return this.childNodes && this.childNodes.length > 0;
+    }
+  }, {
+    key: "firstChild",
+    get: function get() {
+      return this.childNodes && this.childNodes[0];
+    }
+  }, {
+    key: "nextSibling",
+    get: function get() {
+      var childNodes = this.parentNode.childNodes;
+
+      if (!childNodes) {
+        return undefined;
+      }
+
+      var index = childNodes.indexOf(this);
+
+      if (index === -1) {
+        return undefined;
+      }
+
+      return childNodes[index + 1];
+    }
+  }, {
+    key: "textContent",
+    get: function get() {
+      if (!this.childNodes) {
+        return this.nodeValue || '';
+      }
+
+      return this.childNodes.map(function (child) {
+        return child.textContent;
+      }).join('');
+    }
+  }]);
+
+  return SimpleDOMNode;
+}();
+
+var SimpleXMLParser =
+/*#__PURE__*/
+function (_XMLParserBase) {
+  _inherits(SimpleXMLParser, _XMLParserBase);
+
+  function SimpleXMLParser() {
+    var _this2;
+
+    _classCallCheck(this, SimpleXMLParser);
+
+    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(SimpleXMLParser).call(this));
+    _this2._currentFragment = null;
+    _this2._stack = null;
+    _this2._errorCode = XMLParserErrorCode.NoError;
+    return _this2;
+  }
+
+  _createClass(SimpleXMLParser, [{
+    key: "parseFromString",
+    value: function parseFromString(data) {
+      this._currentFragment = [];
+      this._stack = [];
+      this._errorCode = XMLParserErrorCode.NoError;
+      this.parseXml(data);
+
+      if (this._errorCode !== XMLParserErrorCode.NoError) {
+        return undefined;
+      }
+
+      var _this$_currentFragmen = _slicedToArray(this._currentFragment, 1),
+          documentElement = _this$_currentFragmen[0];
+
+      if (!documentElement) {
+        return undefined;
+      }
+
+      return {
+        documentElement: documentElement
+      };
+    }
+  }, {
+    key: "onResolveEntity",
+    value: function onResolveEntity(name) {
+      switch (name) {
+        case 'apos':
+          return '\'';
+      }
+
+      return _get(_getPrototypeOf(SimpleXMLParser.prototype), "onResolveEntity", this).call(this, name);
+    }
+  }, {
+    key: "onText",
+    value: function onText(text) {
+      if (isWhitespaceString(text)) {
+        return;
+      }
+
+      var node = new SimpleDOMNode('#text', text);
+
+      this._currentFragment.push(node);
+    }
+  }, {
+    key: "onCdata",
+    value: function onCdata(text) {
+      var node = new SimpleDOMNode('#text', text);
+
+      this._currentFragment.push(node);
+    }
+  }, {
+    key: "onBeginElement",
+    value: function onBeginElement(name, attributes, isEmpty) {
+      var node = new SimpleDOMNode(name);
+      node.childNodes = [];
+
+      this._currentFragment.push(node);
+
+      if (isEmpty) {
+        return;
+      }
+
+      this._stack.push(this._currentFragment);
+
+      this._currentFragment = node.childNodes;
+    }
+  }, {
+    key: "onEndElement",
+    value: function onEndElement(name) {
+      this._currentFragment = this._stack.pop() || [];
+      var lastElement = this._currentFragment[this._currentFragment.length - 1];
+
+      if (!lastElement) {
+        return;
+      }
+
+      for (var i = 0, ii = lastElement.childNodes.length; i < ii; i++) {
+        lastElement.childNodes[i].parentNode = lastElement;
+      }
+    }
+  }, {
+    key: "onError",
+    value: function onError(code) {
+      this._errorCode = code;
+    }
+  }]);
+
+  return SimpleXMLParser;
+}(XMLParserBase);
+
+exports.SimpleXMLParser = SimpleXMLParser;
+
+/***/ }),
+/* 160 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFDataTransportStream = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var PDFDataTransportStream =
+/*#__PURE__*/
+function () {
+  function PDFDataTransportStream(params, pdfDataRangeTransport) {
+    var _this = this;
+
+    _classCallCheck(this, PDFDataTransportStream);
+
+    (0, _util.assert)(pdfDataRangeTransport);
+    this._queuedChunks = [];
+    this._progressiveDone = params.progressiveDone || false;
+    var initialData = params.initialData;
+
+    if (initialData && initialData.length > 0) {
+      var buffer = new Uint8Array(initialData).buffer;
+
+      this._queuedChunks.push(buffer);
+    }
+
+    this._pdfDataRangeTransport = pdfDataRangeTransport;
+    this._isStreamingSupported = !params.disableStream;
+    this._isRangeSupported = !params.disableRange;
+    this._contentLength = params.length;
+    this._fullRequestReader = null;
+    this._rangeReaders = [];
+
+    this._pdfDataRangeTransport.addRangeListener(function (begin, chunk) {
+      _this._onReceiveData({
+        begin: begin,
+        chunk: chunk
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressListener(function (loaded, total) {
+      _this._onProgress({
+        loaded: loaded,
+        total: total
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressiveReadListener(function (chunk) {
+      _this._onReceiveData({
+        chunk: chunk
+      });
+    });
+
+    this._pdfDataRangeTransport.addProgressiveDoneListener(function () {
+      _this._onProgressiveDone();
+    });
+
+    this._pdfDataRangeTransport.transportReady();
+  }
+
+  _createClass(PDFDataTransportStream, [{
+    key: "_onReceiveData",
+    value: function _onReceiveData(args) {
+      var buffer = new Uint8Array(args.chunk).buffer;
+
+      if (args.begin === undefined) {
+        if (this._fullRequestReader) {
+          this._fullRequestReader._enqueue(buffer);
+        } else {
+          this._queuedChunks.push(buffer);
+        }
+      } else {
+        var found = this._rangeReaders.some(function (rangeReader) {
+          if (rangeReader._begin !== args.begin) {
+            return false;
+          }
+
+          rangeReader._enqueue(buffer);
+
+          return true;
+        });
+
+        (0, _util.assert)(found);
+      }
+    }
+  }, {
+    key: "_onProgress",
+    value: function _onProgress(evt) {
+      if (evt.total === undefined) {
+        var firstReader = this._rangeReaders[0];
+
+        if (firstReader && firstReader.onProgress) {
+          firstReader.onProgress({
+            loaded: evt.loaded
+          });
+        }
+      } else {
+        var fullReader = this._fullRequestReader;
+
+        if (fullReader && fullReader.onProgress) {
+          fullReader.onProgress({
+            loaded: evt.loaded,
+            total: evt.total
+          });
+        }
+      }
+    }
+  }, {
+    key: "_onProgressiveDone",
+    value: function _onProgressiveDone() {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.progressiveDone();
+      }
+
+      this._progressiveDone = true;
+    }
+  }, {
+    key: "_removeRangeReader",
+    value: function _removeRangeReader(reader) {
+      var i = this._rangeReaders.indexOf(reader);
+
+      if (i >= 0) {
+        this._rangeReaders.splice(i, 1);
+      }
+    }
+  }, {
+    key: "getFullReader",
+    value: function getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      var queuedChunks = this._queuedChunks;
+      this._queuedChunks = null;
+      return new PDFDataTransportStreamReader(this, queuedChunks, this._progressiveDone);
+    }
+  }, {
+    key: "getRangeReader",
+    value: function getRangeReader(begin, end) {
+      if (end <= this._progressiveDataLength) {
+        return null;
+      }
+
+      var reader = new PDFDataTransportStreamRangeReader(this, begin, end);
+
+      this._pdfDataRangeTransport.requestDataRange(begin, end);
+
+      this._rangeReaders.push(reader);
+
+      return reader;
+    }
+  }, {
+    key: "cancelAllRequests",
+    value: function cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+
+      var readers = this._rangeReaders.slice(0);
+
+      readers.forEach(function (rangeReader) {
+        rangeReader.cancel(reason);
+      });
+
+      this._pdfDataRangeTransport.abort();
+    }
+  }, {
+    key: "_progressiveDataLength",
+    get: function get() {
+      return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
+    }
+  }]);
+
+  return PDFDataTransportStream;
+}();
+
+exports.PDFDataTransportStream = PDFDataTransportStream;
+
+var PDFDataTransportStreamReader =
+/*#__PURE__*/
+function () {
+  function PDFDataTransportStreamReader(stream, queuedChunks) {
+    var progressiveDone = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+    _classCallCheck(this, PDFDataTransportStreamReader);
+
+    this._stream = stream;
+    this._done = progressiveDone || false;
+    this._filename = null;
+    this._queuedChunks = queuedChunks || [];
+    this._loaded = 0;
+    var _iteratorNormalCompletion = true;
+    var _didIteratorError = false;
+    var _iteratorError = undefined;
+
+    try {
+      for (var _iterator = this._queuedChunks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+        var chunk = _step.value;
+        this._loaded += chunk.byteLength;
+      }
+    } catch (err) {
+      _didIteratorError = true;
+      _iteratorError = err;
+    } finally {
+      try {
+        if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+          _iterator["return"]();
+        }
+      } finally {
+        if (_didIteratorError) {
+          throw _iteratorError;
+        }
+      }
+    }
+
+    this._requests = [];
+    this._headersReady = Promise.resolve();
+    stream._fullRequestReader = this;
+    this.onProgress = null;
+  }
+
+  _createClass(PDFDataTransportStreamReader, [{
+    key: "_enqueue",
+    value: function _enqueue(chunk) {
+      if (this._done) {
+        return;
+      }
+
+      if (this._requests.length > 0) {
+        var requestCapability = this._requests.shift();
+
+        requestCapability.resolve({
+          value: chunk,
+          done: false
+        });
+      } else {
+        this._queuedChunks.push(chunk);
+      }
+
+      this._loaded += chunk.byteLength;
+    }
+  }, {
+    key: "read",
+    value: function () {
+      var _read = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee() {
+        var chunk, requestCapability;
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                if (!(this._queuedChunks.length > 0)) {
+                  _context.next = 3;
+                  break;
+                }
+
+                chunk = this._queuedChunks.shift();
+                return _context.abrupt("return", {
+                  value: chunk,
+                  done: false
+                });
+
+              case 3:
+                if (!this._done) {
+                  _context.next = 5;
+                  break;
+                }
+
+                return _context.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 5:
+                requestCapability = (0, _util.createPromiseCapability)();
+
+                this._requests.push(requestCapability);
+
+                return _context.abrupt("return", requestCapability.promise);
+
+              case 8:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function read() {
+        return _read.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._done = true;
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+    }
+  }, {
+    key: "progressiveDone",
+    value: function progressiveDone() {
+      if (this._done) {
+        return;
+      }
+
+      this._done = true;
+    }
+  }, {
+    key: "headersReady",
+    get: function get() {
+      return this._headersReady;
+    }
+  }, {
+    key: "filename",
+    get: function get() {
+      return this._filename;
+    }
+  }, {
+    key: "isRangeSupported",
+    get: function get() {
+      return this._stream._isRangeSupported;
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._stream._isStreamingSupported;
+    }
+  }, {
+    key: "contentLength",
+    get: function get() {
+      return this._stream._contentLength;
+    }
+  }]);
+
+  return PDFDataTransportStreamReader;
+}();
+
+var PDFDataTransportStreamRangeReader =
+/*#__PURE__*/
+function () {
+  function PDFDataTransportStreamRangeReader(stream, begin, end) {
+    _classCallCheck(this, PDFDataTransportStreamRangeReader);
+
+    this._stream = stream;
+    this._begin = begin;
+    this._end = end;
+    this._queuedChunk = null;
+    this._requests = [];
+    this._done = false;
+    this.onProgress = null;
+  }
+
+  _createClass(PDFDataTransportStreamRangeReader, [{
+    key: "_enqueue",
+    value: function _enqueue(chunk) {
+      if (this._done) {
+        return;
+      }
+
+      if (this._requests.length === 0) {
+        this._queuedChunk = chunk;
+      } else {
+        var requestsCapability = this._requests.shift();
+
+        requestsCapability.resolve({
+          value: chunk,
+          done: false
+        });
+
+        this._requests.forEach(function (requestCapability) {
+          requestCapability.resolve({
+            value: undefined,
+            done: true
+          });
+        });
+
+        this._requests = [];
+      }
+
+      this._done = true;
+
+      this._stream._removeRangeReader(this);
+    }
+  }, {
+    key: "read",
+    value: function () {
+      var _read2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2() {
+        var chunk, requestCapability;
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                if (!this._queuedChunk) {
+                  _context2.next = 4;
+                  break;
+                }
+
+                chunk = this._queuedChunk;
+                this._queuedChunk = null;
+                return _context2.abrupt("return", {
+                  value: chunk,
+                  done: false
+                });
+
+              case 4:
+                if (!this._done) {
+                  _context2.next = 6;
+                  break;
+                }
+
+                return _context2.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 6:
+                requestCapability = (0, _util.createPromiseCapability)();
+
+                this._requests.push(requestCapability);
+
+                return _context2.abrupt("return", requestCapability.promise);
+
+              case 9:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function read() {
+        return _read2.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._done = true;
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+
+      this._stream._removeRangeReader(this);
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return false;
+    }
+  }]);
+
+  return PDFDataTransportStreamRangeReader;
+}();
+
+/***/ }),
+/* 161 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.WebGLContext = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var WebGLContext =
+/*#__PURE__*/
+function () {
+  function WebGLContext(_ref) {
+    var _ref$enable = _ref.enable,
+        enable = _ref$enable === void 0 ? false : _ref$enable;
+
+    _classCallCheck(this, WebGLContext);
+
+    this._enabled = enable === true;
+  }
+
+  _createClass(WebGLContext, [{
+    key: "composeSMask",
+    value: function composeSMask(_ref2) {
+      var layer = _ref2.layer,
+          mask = _ref2.mask,
+          properties = _ref2.properties;
+      return WebGLUtils.composeSMask(layer, mask, properties);
+    }
+  }, {
+    key: "drawFigures",
+    value: function drawFigures(_ref3) {
+      var width = _ref3.width,
+          height = _ref3.height,
+          backgroundColor = _ref3.backgroundColor,
+          figures = _ref3.figures,
+          context = _ref3.context;
+      return WebGLUtils.drawFigures(width, height, backgroundColor, figures, context);
+    }
+  }, {
+    key: "clear",
+    value: function clear() {
+      WebGLUtils.cleanup();
+    }
+  }, {
+    key: "isEnabled",
+    get: function get() {
+      var enabled = this._enabled;
+
+      if (enabled) {
+        enabled = WebGLUtils.tryInitGL();
+      }
+
+      return (0, _util.shadow)(this, 'isEnabled', enabled);
+    }
+  }]);
+
+  return WebGLContext;
+}();
+
+exports.WebGLContext = WebGLContext;
+
+var WebGLUtils = function WebGLUtilsClosure() {
+  function loadShader(gl, code, shaderType) {
+    var shader = gl.createShader(shaderType);
+    gl.shaderSource(shader, code);
+    gl.compileShader(shader);
+    var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
+
+    if (!compiled) {
+      var errorMsg = gl.getShaderInfoLog(shader);
+      throw new Error('Error during shader compilation: ' + errorMsg);
+    }
+
+    return shader;
+  }
+
+  function createVertexShader(gl, code) {
+    return loadShader(gl, code, gl.VERTEX_SHADER);
+  }
+
+  function createFragmentShader(gl, code) {
+    return loadShader(gl, code, gl.FRAGMENT_SHADER);
+  }
+
+  function createProgram(gl, shaders) {
+    var program = gl.createProgram();
+
+    for (var i = 0, ii = shaders.length; i < ii; ++i) {
+      gl.attachShader(program, shaders[i]);
+    }
+
+    gl.linkProgram(program);
+    var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
+
+    if (!linked) {
+      var errorMsg = gl.getProgramInfoLog(program);
+      throw new Error('Error during program linking: ' + errorMsg);
+    }
+
+    return program;
+  }
+
+  function createTexture(gl, image, textureId) {
+    gl.activeTexture(textureId);
+    var texture = gl.createTexture();
+    gl.bindTexture(gl.TEXTURE_2D, texture);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
+    gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
+    gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
+    return texture;
+  }
+
+  var currentGL, currentCanvas;
+
+  function generateGL() {
+    if (currentGL) {
+      return;
+    }
+
+    currentCanvas = document.createElement('canvas');
+    currentGL = currentCanvas.getContext('webgl', {
+      premultipliedalpha: false
+    });
+  }
+
+  var smaskVertexShaderCode = '\
+  attribute vec2 a_position;                                    \
+  attribute vec2 a_texCoord;                                    \
+                                                                \
+  uniform vec2 u_resolution;                                    \
+                                                                \
+  varying vec2 v_texCoord;                                      \
+                                                                \
+  void main() {                                                 \
+    vec2 clipSpace = (a_position / u_resolution) * 2.0 - 1.0;   \
+    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);          \
+                                                                \
+    v_texCoord = a_texCoord;                                    \
+  }                                                             ';
+  var smaskFragmentShaderCode = '\
+  precision mediump float;                                      \
+                                                                \
+  uniform vec4 u_backdrop;                                      \
+  uniform int u_subtype;                                        \
+  uniform sampler2D u_image;                                    \
+  uniform sampler2D u_mask;                                     \
+                                                                \
+  varying vec2 v_texCoord;                                      \
+                                                                \
+  void main() {                                                 \
+    vec4 imageColor = texture2D(u_image, v_texCoord);           \
+    vec4 maskColor = texture2D(u_mask, v_texCoord);             \
+    if (u_backdrop.a > 0.0) {                                   \
+      maskColor.rgb = maskColor.rgb * maskColor.a +             \
+                      u_backdrop.rgb * (1.0 - maskColor.a);     \
+    }                                                           \
+    float lum;                                                  \
+    if (u_subtype == 0) {                                       \
+      lum = maskColor.a;                                        \
+    } else {                                                    \
+      lum = maskColor.r * 0.3 + maskColor.g * 0.59 +            \
+            maskColor.b * 0.11;                                 \
+    }                                                           \
+    imageColor.a *= lum;                                        \
+    imageColor.rgb *= imageColor.a;                             \
+    gl_FragColor = imageColor;                                  \
+  }                                                             ';
+  var smaskCache = null;
+
+  function initSmaskGL() {
+    var canvas, gl;
+    generateGL();
+    canvas = currentCanvas;
+    currentCanvas = null;
+    gl = currentGL;
+    currentGL = null;
+    var vertexShader = createVertexShader(gl, smaskVertexShaderCode);
+    var fragmentShader = createFragmentShader(gl, smaskFragmentShaderCode);
+    var program = createProgram(gl, [vertexShader, fragmentShader]);
+    gl.useProgram(program);
+    var cache = {};
+    cache.gl = gl;
+    cache.canvas = canvas;
+    cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
+    cache.positionLocation = gl.getAttribLocation(program, 'a_position');
+    cache.backdropLocation = gl.getUniformLocation(program, 'u_backdrop');
+    cache.subtypeLocation = gl.getUniformLocation(program, 'u_subtype');
+    var texCoordLocation = gl.getAttribLocation(program, 'a_texCoord');
+    var texLayerLocation = gl.getUniformLocation(program, 'u_image');
+    var texMaskLocation = gl.getUniformLocation(program, 'u_mask');
+    var texCoordBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, texCoordBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0]), gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(texCoordLocation);
+    gl.vertexAttribPointer(texCoordLocation, 2, gl.FLOAT, false, 0, 0);
+    gl.uniform1i(texLayerLocation, 0);
+    gl.uniform1i(texMaskLocation, 1);
+    smaskCache = cache;
+  }
+
+  function composeSMask(layer, mask, properties) {
+    var width = layer.width,
+        height = layer.height;
+
+    if (!smaskCache) {
+      initSmaskGL();
+    }
+
+    var cache = smaskCache,
+        canvas = cache.canvas,
+        gl = cache.gl;
+    canvas.width = width;
+    canvas.height = height;
+    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+    gl.uniform2f(cache.resolutionLocation, width, height);
+
+    if (properties.backdrop) {
+      gl.uniform4f(cache.resolutionLocation, properties.backdrop[0], properties.backdrop[1], properties.backdrop[2], 1);
+    } else {
+      gl.uniform4f(cache.resolutionLocation, 0, 0, 0, 0);
+    }
+
+    gl.uniform1i(cache.subtypeLocation, properties.subtype === 'Luminosity' ? 1 : 0);
+    var texture = createTexture(gl, layer, gl.TEXTURE0);
+    var maskTexture = createTexture(gl, mask, gl.TEXTURE1);
+    var buffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
+    gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([0, 0, width, 0, 0, height, 0, height, width, 0, width, height]), gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(cache.positionLocation);
+    gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
+    gl.clearColor(0, 0, 0, 0);
+    gl.enable(gl.BLEND);
+    gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
+    gl.clear(gl.COLOR_BUFFER_BIT);
+    gl.drawArrays(gl.TRIANGLES, 0, 6);
+    gl.flush();
+    gl.deleteTexture(texture);
+    gl.deleteTexture(maskTexture);
+    gl.deleteBuffer(buffer);
+    return canvas;
+  }
+
+  var figuresVertexShaderCode = '\
+  attribute vec2 a_position;                                    \
+  attribute vec3 a_color;                                       \
+                                                                \
+  uniform vec2 u_resolution;                                    \
+  uniform vec2 u_scale;                                         \
+  uniform vec2 u_offset;                                        \
+                                                                \
+  varying vec4 v_color;                                         \
+                                                                \
+  void main() {                                                 \
+    vec2 position = (a_position + u_offset) * u_scale;          \
+    vec2 clipSpace = (position / u_resolution) * 2.0 - 1.0;     \
+    gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);          \
+                                                                \
+    v_color = vec4(a_color / 255.0, 1.0);                       \
+  }                                                             ';
+  var figuresFragmentShaderCode = '\
+  precision mediump float;                                      \
+                                                                \
+  varying vec4 v_color;                                         \
+                                                                \
+  void main() {                                                 \
+    gl_FragColor = v_color;                                     \
+  }                                                             ';
+  var figuresCache = null;
+
+  function initFiguresGL() {
+    var canvas, gl;
+    generateGL();
+    canvas = currentCanvas;
+    currentCanvas = null;
+    gl = currentGL;
+    currentGL = null;
+    var vertexShader = createVertexShader(gl, figuresVertexShaderCode);
+    var fragmentShader = createFragmentShader(gl, figuresFragmentShaderCode);
+    var program = createProgram(gl, [vertexShader, fragmentShader]);
+    gl.useProgram(program);
+    var cache = {};
+    cache.gl = gl;
+    cache.canvas = canvas;
+    cache.resolutionLocation = gl.getUniformLocation(program, 'u_resolution');
+    cache.scaleLocation = gl.getUniformLocation(program, 'u_scale');
+    cache.offsetLocation = gl.getUniformLocation(program, 'u_offset');
+    cache.positionLocation = gl.getAttribLocation(program, 'a_position');
+    cache.colorLocation = gl.getAttribLocation(program, 'a_color');
+    figuresCache = cache;
+  }
+
+  function drawFigures(width, height, backgroundColor, figures, context) {
+    if (!figuresCache) {
+      initFiguresGL();
+    }
+
+    var cache = figuresCache,
+        canvas = cache.canvas,
+        gl = cache.gl;
+    canvas.width = width;
+    canvas.height = height;
+    gl.viewport(0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight);
+    gl.uniform2f(cache.resolutionLocation, width, height);
+    var count = 0;
+    var i, ii, rows;
+
+    for (i = 0, ii = figures.length; i < ii; i++) {
+      switch (figures[i].type) {
+        case 'lattice':
+          rows = figures[i].coords.length / figures[i].verticesPerRow | 0;
+          count += (rows - 1) * (figures[i].verticesPerRow - 1) * 6;
+          break;
+
+        case 'triangles':
+          count += figures[i].coords.length;
+          break;
+      }
+    }
+
+    var coords = new Float32Array(count * 2);
+    var colors = new Uint8Array(count * 3);
+    var coordsMap = context.coords,
+        colorsMap = context.colors;
+    var pIndex = 0,
+        cIndex = 0;
+
+    for (i = 0, ii = figures.length; i < ii; i++) {
+      var figure = figures[i],
+          ps = figure.coords,
+          cs = figure.colors;
+
+      switch (figure.type) {
+        case 'lattice':
+          var cols = figure.verticesPerRow;
+          rows = ps.length / cols | 0;
+
+          for (var row = 1; row < rows; row++) {
+            var offset = row * cols + 1;
+
+            for (var col = 1; col < cols; col++, offset++) {
+              coords[pIndex] = coordsMap[ps[offset - cols - 1]];
+              coords[pIndex + 1] = coordsMap[ps[offset - cols - 1] + 1];
+              coords[pIndex + 2] = coordsMap[ps[offset - cols]];
+              coords[pIndex + 3] = coordsMap[ps[offset - cols] + 1];
+              coords[pIndex + 4] = coordsMap[ps[offset - 1]];
+              coords[pIndex + 5] = coordsMap[ps[offset - 1] + 1];
+              colors[cIndex] = colorsMap[cs[offset - cols - 1]];
+              colors[cIndex + 1] = colorsMap[cs[offset - cols - 1] + 1];
+              colors[cIndex + 2] = colorsMap[cs[offset - cols - 1] + 2];
+              colors[cIndex + 3] = colorsMap[cs[offset - cols]];
+              colors[cIndex + 4] = colorsMap[cs[offset - cols] + 1];
+              colors[cIndex + 5] = colorsMap[cs[offset - cols] + 2];
+              colors[cIndex + 6] = colorsMap[cs[offset - 1]];
+              colors[cIndex + 7] = colorsMap[cs[offset - 1] + 1];
+              colors[cIndex + 8] = colorsMap[cs[offset - 1] + 2];
+              coords[pIndex + 6] = coords[pIndex + 2];
+              coords[pIndex + 7] = coords[pIndex + 3];
+              coords[pIndex + 8] = coords[pIndex + 4];
+              coords[pIndex + 9] = coords[pIndex + 5];
+              coords[pIndex + 10] = coordsMap[ps[offset]];
+              coords[pIndex + 11] = coordsMap[ps[offset] + 1];
+              colors[cIndex + 9] = colors[cIndex + 3];
+              colors[cIndex + 10] = colors[cIndex + 4];
+              colors[cIndex + 11] = colors[cIndex + 5];
+              colors[cIndex + 12] = colors[cIndex + 6];
+              colors[cIndex + 13] = colors[cIndex + 7];
+              colors[cIndex + 14] = colors[cIndex + 8];
+              colors[cIndex + 15] = colorsMap[cs[offset]];
+              colors[cIndex + 16] = colorsMap[cs[offset] + 1];
+              colors[cIndex + 17] = colorsMap[cs[offset] + 2];
+              pIndex += 12;
+              cIndex += 18;
+            }
+          }
+
+          break;
+
+        case 'triangles':
+          for (var j = 0, jj = ps.length; j < jj; j++) {
+            coords[pIndex] = coordsMap[ps[j]];
+            coords[pIndex + 1] = coordsMap[ps[j] + 1];
+            colors[cIndex] = colorsMap[cs[j]];
+            colors[cIndex + 1] = colorsMap[cs[j] + 1];
+            colors[cIndex + 2] = colorsMap[cs[j] + 2];
+            pIndex += 2;
+            cIndex += 3;
+          }
+
+          break;
+      }
+    }
+
+    if (backgroundColor) {
+      gl.clearColor(backgroundColor[0] / 255, backgroundColor[1] / 255, backgroundColor[2] / 255, 1.0);
+    } else {
+      gl.clearColor(0, 0, 0, 0);
+    }
+
+    gl.clear(gl.COLOR_BUFFER_BIT);
+    var coordsBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, coordsBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, coords, gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(cache.positionLocation);
+    gl.vertexAttribPointer(cache.positionLocation, 2, gl.FLOAT, false, 0, 0);
+    var colorsBuffer = gl.createBuffer();
+    gl.bindBuffer(gl.ARRAY_BUFFER, colorsBuffer);
+    gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW);
+    gl.enableVertexAttribArray(cache.colorLocation);
+    gl.vertexAttribPointer(cache.colorLocation, 3, gl.UNSIGNED_BYTE, false, 0, 0);
+    gl.uniform2f(cache.scaleLocation, context.scaleX, context.scaleY);
+    gl.uniform2f(cache.offsetLocation, context.offsetX, context.offsetY);
+    gl.drawArrays(gl.TRIANGLES, 0, count);
+    gl.flush();
+    gl.deleteBuffer(coordsBuffer);
+    gl.deleteBuffer(colorsBuffer);
+    return canvas;
+  }
+
+  return {
+    tryInitGL: function tryInitGL() {
+      try {
+        generateGL();
+        return !!currentGL;
+      } catch (ex) {}
+
+      return false;
+    },
+    composeSMask: composeSMask,
+    drawFigures: drawFigures,
+    cleanup: function cleanup() {
+      if (smaskCache && smaskCache.canvas) {
+        smaskCache.canvas.width = 0;
+        smaskCache.canvas.height = 0;
+      }
+
+      if (figuresCache && figuresCache.canvas) {
+        figuresCache.canvas.width = 0;
+        figuresCache.canvas.height = 0;
+      }
+
+      smaskCache = null;
+      figuresCache = null;
+    }
+  };
+}();
+
+/***/ }),
+/* 162 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.renderTextLayer = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+var _global_scope = _interopRequireDefault(__w_pdfjs_require__(3));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+var renderTextLayer = function renderTextLayerClosure() {
+  var MAX_TEXT_DIVS_TO_RENDER = 100000;
+  var NonWhitespaceRegexp = /\S/;
+
+  function isAllWhitespace(str) {
+    return !NonWhitespaceRegexp.test(str);
+  }
+
+  var styleBuf = ['left: ', 0, 'px; top: ', 0, 'px; font-size: ', 0, 'px; font-family: ', '', ';'];
+
+  function appendText(task, geom, styles) {
+    var textDiv = document.createElement('span');
+    var textDivProperties = {
+      style: null,
+      angle: 0,
+      canvasWidth: 0,
+      isWhitespace: false,
+      originalTransform: null,
+      paddingBottom: 0,
+      paddingLeft: 0,
+      paddingRight: 0,
+      paddingTop: 0,
+      scale: 1
+    };
+
+    task._textDivs.push(textDiv);
+
+    if (isAllWhitespace(geom.str)) {
+      textDivProperties.isWhitespace = true;
+
+      task._textDivProperties.set(textDiv, textDivProperties);
+
+      return;
+    }
+
+    var tx = _util.Util.transform(task._viewport.transform, geom.transform);
+
+    var angle = Math.atan2(tx[1], tx[0]);
+    var style = styles[geom.fontName];
+
+    if (style.vertical) {
+      angle += Math.PI / 2;
+    }
+
+    var fontHeight = Math.sqrt(tx[2] * tx[2] + tx[3] * tx[3]);
+    var fontAscent = fontHeight;
+
+    if (style.ascent) {
+      fontAscent = style.ascent * fontAscent;
+    } else if (style.descent) {
+      fontAscent = (1 + style.descent) * fontAscent;
+    }
+
+    var left;
+    var top;
+
+    if (angle === 0) {
+      left = tx[4];
+      top = tx[5] - fontAscent;
+    } else {
+      left = tx[4] + fontAscent * Math.sin(angle);
+      top = tx[5] - fontAscent * Math.cos(angle);
+    }
+
+    styleBuf[1] = left;
+    styleBuf[3] = top;
+    styleBuf[5] = fontHeight;
+    styleBuf[7] = style.fontFamily;
+    textDivProperties.style = styleBuf.join('');
+    textDiv.setAttribute('style', textDivProperties.style);
+    textDiv.textContent = geom.str;
+
+    if (task._fontInspectorEnabled) {
+      textDiv.dataset.fontName = geom.fontName;
+    }
+
+    if (angle !== 0) {
+      textDivProperties.angle = angle * (180 / Math.PI);
+    }
+
+    if (geom.str.length > 1) {
+      if (style.vertical) {
+        textDivProperties.canvasWidth = geom.height * task._viewport.scale;
+      } else {
+        textDivProperties.canvasWidth = geom.width * task._viewport.scale;
+      }
+    }
+
+    task._textDivProperties.set(textDiv, textDivProperties);
+
+    if (task._textContentStream) {
+      task._layoutText(textDiv);
+    }
+
+    if (task._enhanceTextSelection) {
+      var angleCos = 1,
+          angleSin = 0;
+
+      if (angle !== 0) {
+        angleCos = Math.cos(angle);
+        angleSin = Math.sin(angle);
+      }
+
+      var divWidth = (style.vertical ? geom.height : geom.width) * task._viewport.scale;
+      var divHeight = fontHeight;
+      var m, b;
+
+      if (angle !== 0) {
+        m = [angleCos, angleSin, -angleSin, angleCos, left, top];
+        b = _util.Util.getAxialAlignedBoundingBox([0, 0, divWidth, divHeight], m);
+      } else {
+        b = [left, top, left + divWidth, top + divHeight];
+      }
+
+      task._bounds.push({
+        left: b[0],
+        top: b[1],
+        right: b[2],
+        bottom: b[3],
+        div: textDiv,
+        size: [divWidth, divHeight],
+        m: m
+      });
+    }
+  }
+
+  function render(task) {
+    if (task._canceled) {
+      return;
+    }
+
+    var textDivs = task._textDivs;
+    var capability = task._capability;
+    var textDivsLength = textDivs.length;
+
+    if (textDivsLength > MAX_TEXT_DIVS_TO_RENDER) {
+      task._renderingDone = true;
+      capability.resolve();
+      return;
+    }
+
+    if (!task._textContentStream) {
+      for (var i = 0; i < textDivsLength; i++) {
+        task._layoutText(textDivs[i]);
+      }
+    }
+
+    task._renderingDone = true;
+    capability.resolve();
+  }
+
+  function expand(task) {
+    var bounds = task._bounds;
+    var viewport = task._viewport;
+    var expanded = expandBounds(viewport.width, viewport.height, bounds);
+
+    for (var i = 0; i < expanded.length; i++) {
+      var div = bounds[i].div;
+
+      var divProperties = task._textDivProperties.get(div);
+
+      if (divProperties.angle === 0) {
+        divProperties.paddingLeft = bounds[i].left - expanded[i].left;
+        divProperties.paddingTop = bounds[i].top - expanded[i].top;
+        divProperties.paddingRight = expanded[i].right - bounds[i].right;
+        divProperties.paddingBottom = expanded[i].bottom - bounds[i].bottom;
+
+        task._textDivProperties.set(div, divProperties);
+
+        continue;
+      }
+
+      var e = expanded[i],
+          b = bounds[i];
+      var m = b.m,
+          c = m[0],
+          s = m[1];
+      var points = [[0, 0], [0, b.size[1]], [b.size[0], 0], b.size];
+      var ts = new Float64Array(64);
+      points.forEach(function (p, i) {
+        var t = _util.Util.applyTransform(p, m);
+
+        ts[i + 0] = c && (e.left - t[0]) / c;
+        ts[i + 4] = s && (e.top - t[1]) / s;
+        ts[i + 8] = c && (e.right - t[0]) / c;
+        ts[i + 12] = s && (e.bottom - t[1]) / s;
+        ts[i + 16] = s && (e.left - t[0]) / -s;
+        ts[i + 20] = c && (e.top - t[1]) / c;
+        ts[i + 24] = s && (e.right - t[0]) / -s;
+        ts[i + 28] = c && (e.bottom - t[1]) / c;
+        ts[i + 32] = c && (e.left - t[0]) / -c;
+        ts[i + 36] = s && (e.top - t[1]) / -s;
+        ts[i + 40] = c && (e.right - t[0]) / -c;
+        ts[i + 44] = s && (e.bottom - t[1]) / -s;
+        ts[i + 48] = s && (e.left - t[0]) / s;
+        ts[i + 52] = c && (e.top - t[1]) / -c;
+        ts[i + 56] = s && (e.right - t[0]) / s;
+        ts[i + 60] = c && (e.bottom - t[1]) / -c;
+      });
+
+      var findPositiveMin = function findPositiveMin(ts, offset, count) {
+        var result = 0;
+
+        for (var i = 0; i < count; i++) {
+          var t = ts[offset++];
+
+          if (t > 0) {
+            result = result ? Math.min(t, result) : t;
+          }
+        }
+
+        return result;
+      };
+
+      var boxScale = 1 + Math.min(Math.abs(c), Math.abs(s));
+      divProperties.paddingLeft = findPositiveMin(ts, 32, 16) / boxScale;
+      divProperties.paddingTop = findPositiveMin(ts, 48, 16) / boxScale;
+      divProperties.paddingRight = findPositiveMin(ts, 0, 16) / boxScale;
+      divProperties.paddingBottom = findPositiveMin(ts, 16, 16) / boxScale;
+
+      task._textDivProperties.set(div, divProperties);
+    }
+  }
+
+  function expandBounds(width, height, boxes) {
+    var bounds = boxes.map(function (box, i) {
+      return {
+        x1: box.left,
+        y1: box.top,
+        x2: box.right,
+        y2: box.bottom,
+        index: i,
+        x1New: undefined,
+        x2New: undefined
+      };
+    });
+    expandBoundsLTR(width, bounds);
+    var expanded = new Array(boxes.length);
+    bounds.forEach(function (b) {
+      var i = b.index;
+      expanded[i] = {
+        left: b.x1New,
+        top: 0,
+        right: b.x2New,
+        bottom: 0
+      };
+    });
+    boxes.map(function (box, i) {
+      var e = expanded[i],
+          b = bounds[i];
+      b.x1 = box.top;
+      b.y1 = width - e.right;
+      b.x2 = box.bottom;
+      b.y2 = width - e.left;
+      b.index = i;
+      b.x1New = undefined;
+      b.x2New = undefined;
+    });
+    expandBoundsLTR(height, bounds);
+    bounds.forEach(function (b) {
+      var i = b.index;
+      expanded[i].top = b.x1New;
+      expanded[i].bottom = b.x2New;
+    });
+    return expanded;
+  }
+
+  function expandBoundsLTR(width, bounds) {
+    bounds.sort(function (a, b) {
+      return a.x1 - b.x1 || a.index - b.index;
+    });
+    var fakeBoundary = {
+      x1: -Infinity,
+      y1: -Infinity,
+      x2: 0,
+      y2: Infinity,
+      index: -1,
+      x1New: 0,
+      x2New: 0
+    };
+    var horizon = [{
+      start: -Infinity,
+      end: Infinity,
+      boundary: fakeBoundary
+    }];
+    bounds.forEach(function (boundary) {
+      var i = 0;
+
+      while (i < horizon.length && horizon[i].end <= boundary.y1) {
+        i++;
+      }
+
+      var j = horizon.length - 1;
+
+      while (j >= 0 && horizon[j].start >= boundary.y2) {
+        j--;
+      }
+
+      var horizonPart, affectedBoundary;
+      var q,
+          k,
+          maxXNew = -Infinity;
+
+      for (q = i; q <= j; q++) {
+        horizonPart = horizon[q];
+        affectedBoundary = horizonPart.boundary;
+        var xNew;
+
+        if (affectedBoundary.x2 > boundary.x1) {
+          xNew = affectedBoundary.index > boundary.index ? affectedBoundary.x1New : boundary.x1;
+        } else if (affectedBoundary.x2New === undefined) {
+          xNew = (affectedBoundary.x2 + boundary.x1) / 2;
+        } else {
+          xNew = affectedBoundary.x2New;
+        }
+
+        if (xNew > maxXNew) {
+          maxXNew = xNew;
+        }
+      }
+
+      boundary.x1New = maxXNew;
+
+      for (q = i; q <= j; q++) {
+        horizonPart = horizon[q];
+        affectedBoundary = horizonPart.boundary;
+
+        if (affectedBoundary.x2New === undefined) {
+          if (affectedBoundary.x2 > boundary.x1) {
+            if (affectedBoundary.index > boundary.index) {
+              affectedBoundary.x2New = affectedBoundary.x2;
+            }
+          } else {
+            affectedBoundary.x2New = maxXNew;
+          }
+        } else if (affectedBoundary.x2New > maxXNew) {
+          affectedBoundary.x2New = Math.max(maxXNew, affectedBoundary.x2);
+        }
+      }
+
+      var changedHorizon = [],
+          lastBoundary = null;
+
+      for (q = i; q <= j; q++) {
+        horizonPart = horizon[q];
+        affectedBoundary = horizonPart.boundary;
+        var useBoundary = affectedBoundary.x2 > boundary.x2 ? affectedBoundary : boundary;
+
+        if (lastBoundary === useBoundary) {
+          changedHorizon[changedHorizon.length - 1].end = horizonPart.end;
+        } else {
+          changedHorizon.push({
+            start: horizonPart.start,
+            end: horizonPart.end,
+            boundary: useBoundary
+          });
+          lastBoundary = useBoundary;
+        }
+      }
+
+      if (horizon[i].start < boundary.y1) {
+        changedHorizon[0].start = boundary.y1;
+        changedHorizon.unshift({
+          start: horizon[i].start,
+          end: boundary.y1,
+          boundary: horizon[i].boundary
+        });
+      }
+
+      if (boundary.y2 < horizon[j].end) {
+        changedHorizon[changedHorizon.length - 1].end = boundary.y2;
+        changedHorizon.push({
+          start: boundary.y2,
+          end: horizon[j].end,
+          boundary: horizon[j].boundary
+        });
+      }
+
+      for (q = i; q <= j; q++) {
+        horizonPart = horizon[q];
+        affectedBoundary = horizonPart.boundary;
+
+        if (affectedBoundary.x2New !== undefined) {
+          continue;
+        }
+
+        var used = false;
+
+        for (k = i - 1; !used && k >= 0 && horizon[k].start >= affectedBoundary.y1; k--) {
+          used = horizon[k].boundary === affectedBoundary;
+        }
+
+        for (k = j + 1; !used && k < horizon.length && horizon[k].end <= affectedBoundary.y2; k++) {
+          used = horizon[k].boundary === affectedBoundary;
+        }
+
+        for (k = 0; !used && k < changedHorizon.length; k++) {
+          used = changedHorizon[k].boundary === affectedBoundary;
+        }
+
+        if (!used) {
+          affectedBoundary.x2New = maxXNew;
+        }
+      }
+
+      Array.prototype.splice.apply(horizon, [i, j - i + 1].concat(changedHorizon));
+    });
+    horizon.forEach(function (horizonPart) {
+      var affectedBoundary = horizonPart.boundary;
+
+      if (affectedBoundary.x2New === undefined) {
+        affectedBoundary.x2New = Math.max(width, affectedBoundary.x2);
+      }
+    });
+  }
+
+  function TextLayerRenderTask(_ref) {
+    var _this = this;
+
+    var textContent = _ref.textContent,
+        textContentStream = _ref.textContentStream,
+        container = _ref.container,
+        viewport = _ref.viewport,
+        textDivs = _ref.textDivs,
+        textContentItemsStr = _ref.textContentItemsStr,
+        enhanceTextSelection = _ref.enhanceTextSelection;
+    this._textContent = textContent;
+    this._textContentStream = textContentStream;
+    this._container = container;
+    this._viewport = viewport;
+    this._textDivs = textDivs || [];
+    this._textContentItemsStr = textContentItemsStr || [];
+    this._enhanceTextSelection = !!enhanceTextSelection;
+    this._fontInspectorEnabled = !!(_global_scope["default"].FontInspector && _global_scope["default"].FontInspector.enabled);
+    this._reader = null;
+    this._layoutTextLastFontSize = null;
+    this._layoutTextLastFontFamily = null;
+    this._layoutTextCtx = null;
+    this._textDivProperties = new WeakMap();
+    this._renderingDone = false;
+    this._canceled = false;
+    this._capability = (0, _util.createPromiseCapability)();
+    this._renderTimer = null;
+    this._bounds = [];
+
+    this._capability.promise["finally"](function () {
+      if (_this._layoutTextCtx) {
+        _this._layoutTextCtx.canvas.width = 0;
+        _this._layoutTextCtx.canvas.height = 0;
+        _this._layoutTextCtx = null;
+      }
+    });
+  }
+
+  TextLayerRenderTask.prototype = {
+    get promise() {
+      return this._capability.promise;
+    },
+
+    cancel: function TextLayer_cancel() {
+      this._canceled = true;
+
+      if (this._reader) {
+        this._reader.cancel(new _util.AbortException('TextLayer task cancelled.'));
+
+        this._reader = null;
+      }
+
+      if (this._renderTimer !== null) {
+        clearTimeout(this._renderTimer);
+        this._renderTimer = null;
+      }
+
+      this._capability.reject(new Error('TextLayer task cancelled.'));
+    },
+    _processItems: function _processItems(items, styleCache) {
+      for (var i = 0, len = items.length; i < len; i++) {
+        this._textContentItemsStr.push(items[i].str);
+
+        appendText(this, items[i], styleCache);
+      }
+    },
+    _layoutText: function _layoutText(textDiv) {
+      var textLayerFrag = this._container;
+
+      var textDivProperties = this._textDivProperties.get(textDiv);
+
+      if (textDivProperties.isWhitespace) {
+        return;
+      }
+
+      var fontSize = textDiv.style.fontSize;
+      var fontFamily = textDiv.style.fontFamily;
+
+      if (fontSize !== this._layoutTextLastFontSize || fontFamily !== this._layoutTextLastFontFamily) {
+        this._layoutTextCtx.font = fontSize + ' ' + fontFamily;
+        this._layoutTextLastFontSize = fontSize;
+        this._layoutTextLastFontFamily = fontFamily;
+      }
+
+      var width = this._layoutTextCtx.measureText(textDiv.textContent).width;
+
+      var transform = '';
+
+      if (textDivProperties.canvasWidth !== 0 && width > 0) {
+        textDivProperties.scale = textDivProperties.canvasWidth / width;
+        transform = "scaleX(".concat(textDivProperties.scale, ")");
+      }
+
+      if (textDivProperties.angle !== 0) {
+        transform = "rotate(".concat(textDivProperties.angle, "deg) ").concat(transform);
+      }
+
+      if (transform.length > 0) {
+        textDivProperties.originalTransform = transform;
+        textDiv.style.transform = transform;
+      }
+
+      this._textDivProperties.set(textDiv, textDivProperties);
+
+      textLayerFrag.appendChild(textDiv);
+    },
+    _render: function TextLayer_render(timeout) {
+      var _this2 = this;
+
+      var capability = (0, _util.createPromiseCapability)();
+      var styleCache = Object.create(null);
+      var canvas = document.createElement('canvas');
+      canvas.mozOpaque = true;
+      this._layoutTextCtx = canvas.getContext('2d', {
+        alpha: false
+      });
+
+      if (this._textContent) {
+        var textItems = this._textContent.items;
+        var textStyles = this._textContent.styles;
+
+        this._processItems(textItems, textStyles);
+
+        capability.resolve();
+      } else if (this._textContentStream) {
+        var pump = function pump() {
+          _this2._reader.read().then(function (_ref2) {
+            var value = _ref2.value,
+                done = _ref2.done;
+
+            if (done) {
+              capability.resolve();
+              return;
+            }
+
+            Object.assign(styleCache, value.styles);
+
+            _this2._processItems(value.items, styleCache);
+
+            pump();
+          }, capability.reject);
+        };
+
+        this._reader = this._textContentStream.getReader();
+        pump();
+      } else {
+        throw new Error('Neither "textContent" nor "textContentStream"' + ' parameters specified.');
+      }
+
+      capability.promise.then(function () {
+        styleCache = null;
+
+        if (!timeout) {
+          render(_this2);
+        } else {
+          _this2._renderTimer = setTimeout(function () {
+            render(_this2);
+            _this2._renderTimer = null;
+          }, timeout);
+        }
+      }, this._capability.reject);
+    },
+    expandTextDivs: function TextLayer_expandTextDivs(expandDivs) {
+      if (!this._enhanceTextSelection || !this._renderingDone) {
+        return;
+      }
+
+      if (this._bounds !== null) {
+        expand(this);
+        this._bounds = null;
+      }
+
+      for (var i = 0, ii = this._textDivs.length; i < ii; i++) {
+        var div = this._textDivs[i];
+
+        var divProperties = this._textDivProperties.get(div);
+
+        if (divProperties.isWhitespace) {
+          continue;
+        }
+
+        if (expandDivs) {
+          var transform = '',
+              padding = '';
+
+          if (divProperties.scale !== 1) {
+            transform = 'scaleX(' + divProperties.scale + ')';
+          }
+
+          if (divProperties.angle !== 0) {
+            transform = 'rotate(' + divProperties.angle + 'deg) ' + transform;
+          }
+
+          if (divProperties.paddingLeft !== 0) {
+            padding += ' padding-left: ' + divProperties.paddingLeft / divProperties.scale + 'px;';
+            transform += ' translateX(' + -divProperties.paddingLeft / divProperties.scale + 'px)';
+          }
+
+          if (divProperties.paddingTop !== 0) {
+            padding += ' padding-top: ' + divProperties.paddingTop + 'px;';
+            transform += ' translateY(' + -divProperties.paddingTop + 'px)';
+          }
+
+          if (divProperties.paddingRight !== 0) {
+            padding += ' padding-right: ' + divProperties.paddingRight / divProperties.scale + 'px;';
+          }
+
+          if (divProperties.paddingBottom !== 0) {
+            padding += ' padding-bottom: ' + divProperties.paddingBottom + 'px;';
+          }
+
+          if (padding !== '') {
+            div.setAttribute('style', divProperties.style + padding);
+          }
+
+          if (transform !== '') {
+            div.style.transform = transform;
+          }
+        } else {
+          div.style.padding = 0;
+          div.style.transform = divProperties.originalTransform || '';
+        }
+      }
+    }
+  };
+
+  function renderTextLayer(renderParameters) {
+    var task = new TextLayerRenderTask({
+      textContent: renderParameters.textContent,
+      textContentStream: renderParameters.textContentStream,
+      container: renderParameters.container,
+      viewport: renderParameters.viewport,
+      textDivs: renderParameters.textDivs,
+      textContentItemsStr: renderParameters.textContentItemsStr,
+      enhanceTextSelection: renderParameters.enhanceTextSelection
+    });
+
+    task._render(renderParameters.timeout);
+
+    return task;
+  }
+
+  return renderTextLayer;
+}();
+
+exports.renderTextLayer = renderTextLayer;
+
+/***/ }),
+/* 163 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.AnnotationLayer = void 0;
+
+var _display_utils = __w_pdfjs_require__(151);
+
+var _util = __w_pdfjs_require__(1);
+
+function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
+
+function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var AnnotationElementFactory =
+/*#__PURE__*/
+function () {
+  function AnnotationElementFactory() {
+    _classCallCheck(this, AnnotationElementFactory);
+  }
+
+  _createClass(AnnotationElementFactory, null, [{
+    key: "create",
+    value: function create(parameters) {
+      var subtype = parameters.data.annotationType;
+
+      switch (subtype) {
+        case _util.AnnotationType.LINK:
+          return new LinkAnnotationElement(parameters);
+
+        case _util.AnnotationType.TEXT:
+          return new TextAnnotationElement(parameters);
+
+        case _util.AnnotationType.WIDGET:
+          var fieldType = parameters.data.fieldType;
+
+          switch (fieldType) {
+            case 'Tx':
+              return new TextWidgetAnnotationElement(parameters);
+
+            case 'Btn':
+              if (parameters.data.radioButton) {
+                return new RadioButtonWidgetAnnotationElement(parameters);
+              } else if (parameters.data.checkBox) {
+                return new CheckboxWidgetAnnotationElement(parameters);
+              }
+
+              return new PushButtonWidgetAnnotationElement(parameters);
+
+            case 'Ch':
+              return new ChoiceWidgetAnnotationElement(parameters);
+          }
+
+          return new WidgetAnnotationElement(parameters);
+
+        case _util.AnnotationType.POPUP:
+          return new PopupAnnotationElement(parameters);
+
+        case _util.AnnotationType.FREETEXT:
+          return new FreeTextAnnotationElement(parameters);
+
+        case _util.AnnotationType.LINE:
+          return new LineAnnotationElement(parameters);
+
+        case _util.AnnotationType.SQUARE:
+          return new SquareAnnotationElement(parameters);
+
+        case _util.AnnotationType.CIRCLE:
+          return new CircleAnnotationElement(parameters);
+
+        case _util.AnnotationType.POLYLINE:
+          return new PolylineAnnotationElement(parameters);
+
+        case _util.AnnotationType.CARET:
+          return new CaretAnnotationElement(parameters);
+
+        case _util.AnnotationType.INK:
+          return new InkAnnotationElement(parameters);
+
+        case _util.AnnotationType.POLYGON:
+          return new PolygonAnnotationElement(parameters);
+
+        case _util.AnnotationType.HIGHLIGHT:
+          return new HighlightAnnotationElement(parameters);
+
+        case _util.AnnotationType.UNDERLINE:
+          return new UnderlineAnnotationElement(parameters);
+
+        case _util.AnnotationType.SQUIGGLY:
+          return new SquigglyAnnotationElement(parameters);
+
+        case _util.AnnotationType.STRIKEOUT:
+          return new StrikeOutAnnotationElement(parameters);
+
+        case _util.AnnotationType.STAMP:
+          return new StampAnnotationElement(parameters);
+
+        case _util.AnnotationType.FILEATTACHMENT:
+          return new FileAttachmentAnnotationElement(parameters);
+
+        default:
+          return new AnnotationElement(parameters);
+      }
+    }
+  }]);
+
+  return AnnotationElementFactory;
+}();
+
+var AnnotationElement =
+/*#__PURE__*/
+function () {
+  function AnnotationElement(parameters) {
+    var isRenderable = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+    var ignoreBorder = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+    _classCallCheck(this, AnnotationElement);
+
+    this.isRenderable = isRenderable;
+    this.data = parameters.data;
+    this.layer = parameters.layer;
+    this.page = parameters.page;
+    this.viewport = parameters.viewport;
+    this.linkService = parameters.linkService;
+    this.downloadManager = parameters.downloadManager;
+    this.imageResourcesPath = parameters.imageResourcesPath;
+    this.renderInteractiveForms = parameters.renderInteractiveForms;
+    this.svgFactory = parameters.svgFactory;
+
+    if (isRenderable) {
+      this.container = this._createContainer(ignoreBorder);
+    }
+  }
+
+  _createClass(AnnotationElement, [{
+    key: "_createContainer",
+    value: function _createContainer() {
+      var ignoreBorder = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+      var data = this.data,
+          page = this.page,
+          viewport = this.viewport;
+      var container = document.createElement('section');
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      container.setAttribute('data-annotation-id', data.id);
+
+      var rect = _util.Util.normalizeRect([data.rect[0], page.view[3] - data.rect[1] + page.view[1], data.rect[2], page.view[3] - data.rect[3] + page.view[1]]);
+
+      container.style.transform = 'matrix(' + viewport.transform.join(',') + ')';
+      container.style.transformOrigin = -rect[0] + 'px ' + -rect[1] + 'px';
+
+      if (!ignoreBorder && data.borderStyle.width > 0) {
+        container.style.borderWidth = data.borderStyle.width + 'px';
+
+        if (data.borderStyle.style !== _util.AnnotationBorderStyleType.UNDERLINE) {
+          width = width - 2 * data.borderStyle.width;
+          height = height - 2 * data.borderStyle.width;
+        }
+
+        var horizontalRadius = data.borderStyle.horizontalCornerRadius;
+        var verticalRadius = data.borderStyle.verticalCornerRadius;
+
+        if (horizontalRadius > 0 || verticalRadius > 0) {
+          var radius = horizontalRadius + 'px / ' + verticalRadius + 'px';
+          container.style.borderRadius = radius;
+        }
+
+        switch (data.borderStyle.style) {
+          case _util.AnnotationBorderStyleType.SOLID:
+            container.style.borderStyle = 'solid';
+            break;
+
+          case _util.AnnotationBorderStyleType.DASHED:
+            container.style.borderStyle = 'dashed';
+            break;
+
+          case _util.AnnotationBorderStyleType.BEVELED:
+            (0, _util.warn)('Unimplemented border style: beveled');
+            break;
+
+          case _util.AnnotationBorderStyleType.INSET:
+            (0, _util.warn)('Unimplemented border style: inset');
+            break;
+
+          case _util.AnnotationBorderStyleType.UNDERLINE:
+            container.style.borderBottomStyle = 'solid';
+            break;
+
+          default:
+            break;
+        }
+
+        if (data.color) {
+          container.style.borderColor = _util.Util.makeCssRgb(data.color[0] | 0, data.color[1] | 0, data.color[2] | 0);
+        } else {
+          container.style.borderWidth = 0;
+        }
+      }
+
+      container.style.left = rect[0] + 'px';
+      container.style.top = rect[1] + 'px';
+      container.style.width = width + 'px';
+      container.style.height = height + 'px';
+      return container;
+    }
+  }, {
+    key: "_createPopup",
+    value: function _createPopup(container, trigger, data) {
+      if (!trigger) {
+        trigger = document.createElement('div');
+        trigger.style.height = container.style.height;
+        trigger.style.width = container.style.width;
+        container.appendChild(trigger);
+      }
+
+      var popupElement = new PopupElement({
+        container: container,
+        trigger: trigger,
+        color: data.color,
+        title: data.title,
+        modificationDate: data.modificationDate,
+        contents: data.contents,
+        hideWrapper: true
+      });
+      var popup = popupElement.render();
+      popup.style.left = container.style.width;
+      container.appendChild(popup);
+    }
+  }, {
+    key: "render",
+    value: function render() {
+      (0, _util.unreachable)('Abstract method `AnnotationElement.render` called');
+    }
+  }]);
+
+  return AnnotationElement;
+}();
+
+var LinkAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement) {
+  _inherits(LinkAnnotationElement, _AnnotationElement);
+
+  function LinkAnnotationElement(parameters) {
+    _classCallCheck(this, LinkAnnotationElement);
+
+    var isRenderable = !!(parameters.data.url || parameters.data.dest || parameters.data.action);
+    return _possibleConstructorReturn(this, _getPrototypeOf(LinkAnnotationElement).call(this, parameters, isRenderable));
+  }
+
+  _createClass(LinkAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'linkAnnotation';
+      var data = this.data,
+          linkService = this.linkService;
+      var link = document.createElement('a');
+      (0, _display_utils.addLinkAttributes)(link, {
+        url: data.url,
+        target: data.newWindow ? _display_utils.LinkTarget.BLANK : linkService.externalLinkTarget,
+        rel: linkService.externalLinkRel
+      });
+
+      if (!data.url) {
+        if (data.action) {
+          this._bindNamedAction(link, data.action);
+        } else {
+          this._bindLink(link, data.dest);
+        }
+      }
+
+      this.container.appendChild(link);
+      return this.container;
+    }
+  }, {
+    key: "_bindLink",
+    value: function _bindLink(link, destination) {
+      var _this = this;
+
+      link.href = this.linkService.getDestinationHash(destination);
+
+      link.onclick = function () {
+        if (destination) {
+          _this.linkService.navigateTo(destination);
+        }
+
+        return false;
+      };
+
+      if (destination) {
+        link.className = 'internalLink';
+      }
+    }
+  }, {
+    key: "_bindNamedAction",
+    value: function _bindNamedAction(link, action) {
+      var _this2 = this;
+
+      link.href = this.linkService.getAnchorUrl('');
+
+      link.onclick = function () {
+        _this2.linkService.executeNamedAction(action);
+
+        return false;
+      };
+
+      link.className = 'internalLink';
+    }
+  }]);
+
+  return LinkAnnotationElement;
+}(AnnotationElement);
+
+var TextAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement2) {
+  _inherits(TextAnnotationElement, _AnnotationElement2);
+
+  function TextAnnotationElement(parameters) {
+    _classCallCheck(this, TextAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(TextAnnotationElement).call(this, parameters, isRenderable));
+  }
+
+  _createClass(TextAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'textAnnotation';
+      var image = document.createElement('img');
+      image.style.height = this.container.style.height;
+      image.style.width = this.container.style.width;
+      image.src = this.imageResourcesPath + 'annotation-' + this.data.name.toLowerCase() + '.svg';
+      image.alt = '[{{type}} Annotation]';
+      image.dataset.l10nId = 'text_annotation_type';
+      image.dataset.l10nArgs = JSON.stringify({
+        type: this.data.name
+      });
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, image, this.data);
+      }
+
+      this.container.appendChild(image);
+      return this.container;
+    }
+  }]);
+
+  return TextAnnotationElement;
+}(AnnotationElement);
+
+var WidgetAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement3) {
+  _inherits(WidgetAnnotationElement, _AnnotationElement3);
+
+  function WidgetAnnotationElement() {
+    _classCallCheck(this, WidgetAnnotationElement);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(WidgetAnnotationElement).apply(this, arguments));
+  }
+
+  _createClass(WidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      return this.container;
+    }
+  }]);
+
+  return WidgetAnnotationElement;
+}(AnnotationElement);
+
+var TextWidgetAnnotationElement =
+/*#__PURE__*/
+function (_WidgetAnnotationElem) {
+  _inherits(TextWidgetAnnotationElement, _WidgetAnnotationElem);
+
+  function TextWidgetAnnotationElement(parameters) {
+    _classCallCheck(this, TextWidgetAnnotationElement);
+
+    var isRenderable = parameters.renderInteractiveForms || !parameters.data.hasAppearance && !!parameters.data.fieldValue;
+    return _possibleConstructorReturn(this, _getPrototypeOf(TextWidgetAnnotationElement).call(this, parameters, isRenderable));
+  }
+
+  _createClass(TextWidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      var TEXT_ALIGNMENT = ['left', 'center', 'right'];
+      this.container.className = 'textWidgetAnnotation';
+      var element = null;
+
+      if (this.renderInteractiveForms) {
+        if (this.data.multiLine) {
+          element = document.createElement('textarea');
+          element.textContent = this.data.fieldValue;
+        } else {
+          element = document.createElement('input');
+          element.type = 'text';
+          element.setAttribute('value', this.data.fieldValue);
+        }
+
+        element.disabled = this.data.readOnly;
+
+        if (this.data.maxLen !== null) {
+          element.maxLength = this.data.maxLen;
+        }
+
+        if (this.data.comb) {
+          var fieldWidth = this.data.rect[2] - this.data.rect[0];
+          var combWidth = fieldWidth / this.data.maxLen;
+          element.classList.add('comb');
+          element.style.letterSpacing = 'calc(' + combWidth + 'px - 1ch)';
+        }
+      } else {
+        element = document.createElement('div');
+        element.textContent = this.data.fieldValue;
+        element.style.verticalAlign = 'middle';
+        element.style.display = 'table-cell';
+        var font = null;
+
+        if (this.data.fontRefName && this.page.commonObjs.has(this.data.fontRefName)) {
+          font = this.page.commonObjs.get(this.data.fontRefName);
+        }
+
+        this._setTextStyle(element, font);
+      }
+
+      if (this.data.textAlignment !== null) {
+        element.style.textAlign = TEXT_ALIGNMENT[this.data.textAlignment];
+      }
+
+      this.container.appendChild(element);
+      return this.container;
+    }
+  }, {
+    key: "_setTextStyle",
+    value: function _setTextStyle(element, font) {
+      var style = element.style;
+      style.fontSize = this.data.fontSize + 'px';
+      style.direction = this.data.fontDirection < 0 ? 'rtl' : 'ltr';
+
+      if (!font) {
+        return;
+      }
+
+      style.fontWeight = font.black ? font.bold ? '900' : 'bold' : font.bold ? 'bold' : 'normal';
+      style.fontStyle = font.italic ? 'italic' : 'normal';
+      var fontFamily = font.loadedName ? '"' + font.loadedName + '", ' : '';
+      var fallbackName = font.fallbackName || 'Helvetica, sans-serif';
+      style.fontFamily = fontFamily + fallbackName;
+    }
+  }]);
+
+  return TextWidgetAnnotationElement;
+}(WidgetAnnotationElement);
+
+var CheckboxWidgetAnnotationElement =
+/*#__PURE__*/
+function (_WidgetAnnotationElem2) {
+  _inherits(CheckboxWidgetAnnotationElement, _WidgetAnnotationElem2);
+
+  function CheckboxWidgetAnnotationElement(parameters) {
+    _classCallCheck(this, CheckboxWidgetAnnotationElement);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(CheckboxWidgetAnnotationElement).call(this, parameters, parameters.renderInteractiveForms));
+  }
+
+  _createClass(CheckboxWidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'buttonWidgetAnnotation checkBox';
+      var element = document.createElement('input');
+      element.disabled = this.data.readOnly;
+      element.type = 'checkbox';
+
+      if (this.data.fieldValue && this.data.fieldValue !== 'Off') {
+        element.setAttribute('checked', true);
+      }
+
+      this.container.appendChild(element);
+      return this.container;
+    }
+  }]);
+
+  return CheckboxWidgetAnnotationElement;
+}(WidgetAnnotationElement);
+
+var RadioButtonWidgetAnnotationElement =
+/*#__PURE__*/
+function (_WidgetAnnotationElem3) {
+  _inherits(RadioButtonWidgetAnnotationElement, _WidgetAnnotationElem3);
+
+  function RadioButtonWidgetAnnotationElement(parameters) {
+    _classCallCheck(this, RadioButtonWidgetAnnotationElement);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(RadioButtonWidgetAnnotationElement).call(this, parameters, parameters.renderInteractiveForms));
+  }
+
+  _createClass(RadioButtonWidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'buttonWidgetAnnotation radioButton';
+      var element = document.createElement('input');
+      element.disabled = this.data.readOnly;
+      element.type = 'radio';
+      element.name = this.data.fieldName;
+
+      if (this.data.fieldValue === this.data.buttonValue) {
+        element.setAttribute('checked', true);
+      }
+
+      this.container.appendChild(element);
+      return this.container;
+    }
+  }]);
+
+  return RadioButtonWidgetAnnotationElement;
+}(WidgetAnnotationElement);
+
+var PushButtonWidgetAnnotationElement =
+/*#__PURE__*/
+function (_LinkAnnotationElemen) {
+  _inherits(PushButtonWidgetAnnotationElement, _LinkAnnotationElemen);
+
+  function PushButtonWidgetAnnotationElement() {
+    _classCallCheck(this, PushButtonWidgetAnnotationElement);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(PushButtonWidgetAnnotationElement).apply(this, arguments));
+  }
+
+  _createClass(PushButtonWidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      var container = _get(_getPrototypeOf(PushButtonWidgetAnnotationElement.prototype), "render", this).call(this);
+
+      container.className = 'buttonWidgetAnnotation pushButton';
+      return container;
+    }
+  }]);
+
+  return PushButtonWidgetAnnotationElement;
+}(LinkAnnotationElement);
+
+var ChoiceWidgetAnnotationElement =
+/*#__PURE__*/
+function (_WidgetAnnotationElem4) {
+  _inherits(ChoiceWidgetAnnotationElement, _WidgetAnnotationElem4);
+
+  function ChoiceWidgetAnnotationElement(parameters) {
+    _classCallCheck(this, ChoiceWidgetAnnotationElement);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(ChoiceWidgetAnnotationElement).call(this, parameters, parameters.renderInteractiveForms));
+  }
+
+  _createClass(ChoiceWidgetAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'choiceWidgetAnnotation';
+      var selectElement = document.createElement('select');
+      selectElement.disabled = this.data.readOnly;
+
+      if (!this.data.combo) {
+        selectElement.size = this.data.options.length;
+
+        if (this.data.multiSelect) {
+          selectElement.multiple = true;
+        }
+      }
+
+      for (var i = 0, ii = this.data.options.length; i < ii; i++) {
+        var option = this.data.options[i];
+        var optionElement = document.createElement('option');
+        optionElement.textContent = option.displayValue;
+        optionElement.value = option.exportValue;
+
+        if (this.data.fieldValue.includes(option.displayValue)) {
+          optionElement.setAttribute('selected', true);
+        }
+
+        selectElement.appendChild(optionElement);
+      }
+
+      this.container.appendChild(selectElement);
+      return this.container;
+    }
+  }]);
+
+  return ChoiceWidgetAnnotationElement;
+}(WidgetAnnotationElement);
+
+var PopupAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement4) {
+  _inherits(PopupAnnotationElement, _AnnotationElement4);
+
+  function PopupAnnotationElement(parameters) {
+    _classCallCheck(this, PopupAnnotationElement);
+
+    var isRenderable = !!(parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(PopupAnnotationElement).call(this, parameters, isRenderable));
+  }
+
+  _createClass(PopupAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      var IGNORE_TYPES = ['Line', 'Square', 'Circle', 'PolyLine', 'Polygon', 'Ink'];
+      this.container.className = 'popupAnnotation';
+
+      if (IGNORE_TYPES.includes(this.data.parentType)) {
+        return this.container;
+      }
+
+      var selector = '[data-annotation-id="' + this.data.parentId + '"]';
+      var parentElement = this.layer.querySelector(selector);
+
+      if (!parentElement) {
+        return this.container;
+      }
+
+      var popup = new PopupElement({
+        container: this.container,
+        trigger: parentElement,
+        color: this.data.color,
+        title: this.data.title,
+        modificationDate: this.data.modificationDate,
+        contents: this.data.contents
+      });
+      var parentLeft = parseFloat(parentElement.style.left);
+      var parentWidth = parseFloat(parentElement.style.width);
+      this.container.style.transformOrigin = -(parentLeft + parentWidth) + 'px -' + parentElement.style.top;
+      this.container.style.left = parentLeft + parentWidth + 'px';
+      this.container.appendChild(popup.render());
+      return this.container;
+    }
+  }]);
+
+  return PopupAnnotationElement;
+}(AnnotationElement);
+
+var PopupElement =
+/*#__PURE__*/
+function () {
+  function PopupElement(parameters) {
+    _classCallCheck(this, PopupElement);
+
+    this.container = parameters.container;
+    this.trigger = parameters.trigger;
+    this.color = parameters.color;
+    this.title = parameters.title;
+    this.modificationDate = parameters.modificationDate;
+    this.contents = parameters.contents;
+    this.hideWrapper = parameters.hideWrapper || false;
+    this.pinned = false;
+  }
+
+  _createClass(PopupElement, [{
+    key: "render",
+    value: function render() {
+      var BACKGROUND_ENLIGHT = 0.7;
+      var wrapper = document.createElement('div');
+      wrapper.className = 'popupWrapper';
+      this.hideElement = this.hideWrapper ? wrapper : this.container;
+      this.hideElement.setAttribute('hidden', true);
+      var popup = document.createElement('div');
+      popup.className = 'popup';
+      var color = this.color;
+
+      if (color) {
+        var r = BACKGROUND_ENLIGHT * (255 - color[0]) + color[0];
+        var g = BACKGROUND_ENLIGHT * (255 - color[1]) + color[1];
+        var b = BACKGROUND_ENLIGHT * (255 - color[2]) + color[2];
+        popup.style.backgroundColor = _util.Util.makeCssRgb(r | 0, g | 0, b | 0);
+      }
+
+      var title = document.createElement('h1');
+      title.textContent = this.title;
+      popup.appendChild(title);
+
+      var dateObject = _display_utils.PDFDateString.toDateObject(this.modificationDate);
+
+      if (dateObject) {
+        var modificationDate = document.createElement('span');
+        modificationDate.textContent = '{{date}}, {{time}}';
+        modificationDate.dataset.l10nId = 'annotation_date_string';
+        modificationDate.dataset.l10nArgs = JSON.stringify({
+          date: dateObject.toLocaleDateString(),
+          time: dateObject.toLocaleTimeString()
+        });
+        popup.appendChild(modificationDate);
+      }
+
+      var contents = this._formatContents(this.contents);
+
+      popup.appendChild(contents);
+      this.trigger.addEventListener('click', this._toggle.bind(this));
+      this.trigger.addEventListener('mouseover', this._show.bind(this, false));
+      this.trigger.addEventListener('mouseout', this._hide.bind(this, false));
+      popup.addEventListener('click', this._hide.bind(this, true));
+      wrapper.appendChild(popup);
+      return wrapper;
+    }
+  }, {
+    key: "_formatContents",
+    value: function _formatContents(contents) {
+      var p = document.createElement('p');
+      var lines = contents.split(/(?:\r\n?|\n)/);
+
+      for (var i = 0, ii = lines.length; i < ii; ++i) {
+        var line = lines[i];
+        p.appendChild(document.createTextNode(line));
+
+        if (i < ii - 1) {
+          p.appendChild(document.createElement('br'));
+        }
+      }
+
+      return p;
+    }
+  }, {
+    key: "_toggle",
+    value: function _toggle() {
+      if (this.pinned) {
+        this._hide(true);
+      } else {
+        this._show(true);
+      }
+    }
+  }, {
+    key: "_show",
+    value: function _show() {
+      var pin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+      if (pin) {
+        this.pinned = true;
+      }
+
+      if (this.hideElement.hasAttribute('hidden')) {
+        this.hideElement.removeAttribute('hidden');
+        this.container.style.zIndex += 1;
+      }
+    }
+  }, {
+    key: "_hide",
+    value: function _hide() {
+      var unpin = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
+
+      if (unpin) {
+        this.pinned = false;
+      }
+
+      if (!this.hideElement.hasAttribute('hidden') && !this.pinned) {
+        this.hideElement.setAttribute('hidden', true);
+        this.container.style.zIndex -= 1;
+      }
+    }
+  }]);
+
+  return PopupElement;
+}();
+
+var FreeTextAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement5) {
+  _inherits(FreeTextAnnotationElement, _AnnotationElement5);
+
+  function FreeTextAnnotationElement(parameters) {
+    _classCallCheck(this, FreeTextAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(FreeTextAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(FreeTextAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'freeTextAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return FreeTextAnnotationElement;
+}(AnnotationElement);
+
+var LineAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement6) {
+  _inherits(LineAnnotationElement, _AnnotationElement6);
+
+  function LineAnnotationElement(parameters) {
+    _classCallCheck(this, LineAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(LineAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(LineAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'lineAnnotation';
+      var data = this.data;
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      var svg = this.svgFactory.create(width, height);
+      var line = this.svgFactory.createElement('svg:line');
+      line.setAttribute('x1', data.rect[2] - data.lineCoordinates[0]);
+      line.setAttribute('y1', data.rect[3] - data.lineCoordinates[1]);
+      line.setAttribute('x2', data.rect[2] - data.lineCoordinates[2]);
+      line.setAttribute('y2', data.rect[3] - data.lineCoordinates[3]);
+      line.setAttribute('stroke-width', data.borderStyle.width);
+      line.setAttribute('stroke', 'transparent');
+      svg.appendChild(line);
+      this.container.append(svg);
+
+      this._createPopup(this.container, line, data);
+
+      return this.container;
+    }
+  }]);
+
+  return LineAnnotationElement;
+}(AnnotationElement);
+
+var SquareAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement7) {
+  _inherits(SquareAnnotationElement, _AnnotationElement7);
+
+  function SquareAnnotationElement(parameters) {
+    _classCallCheck(this, SquareAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(SquareAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(SquareAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'squareAnnotation';
+      var data = this.data;
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      var svg = this.svgFactory.create(width, height);
+      var borderWidth = data.borderStyle.width;
+      var square = this.svgFactory.createElement('svg:rect');
+      square.setAttribute('x', borderWidth / 2);
+      square.setAttribute('y', borderWidth / 2);
+      square.setAttribute('width', width - borderWidth);
+      square.setAttribute('height', height - borderWidth);
+      square.setAttribute('stroke-width', borderWidth);
+      square.setAttribute('stroke', 'transparent');
+      square.setAttribute('fill', 'none');
+      svg.appendChild(square);
+      this.container.append(svg);
+
+      this._createPopup(this.container, square, data);
+
+      return this.container;
+    }
+  }]);
+
+  return SquareAnnotationElement;
+}(AnnotationElement);
+
+var CircleAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement8) {
+  _inherits(CircleAnnotationElement, _AnnotationElement8);
+
+  function CircleAnnotationElement(parameters) {
+    _classCallCheck(this, CircleAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(CircleAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(CircleAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'circleAnnotation';
+      var data = this.data;
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      var svg = this.svgFactory.create(width, height);
+      var borderWidth = data.borderStyle.width;
+      var circle = this.svgFactory.createElement('svg:ellipse');
+      circle.setAttribute('cx', width / 2);
+      circle.setAttribute('cy', height / 2);
+      circle.setAttribute('rx', width / 2 - borderWidth / 2);
+      circle.setAttribute('ry', height / 2 - borderWidth / 2);
+      circle.setAttribute('stroke-width', borderWidth);
+      circle.setAttribute('stroke', 'transparent');
+      circle.setAttribute('fill', 'none');
+      svg.appendChild(circle);
+      this.container.append(svg);
+
+      this._createPopup(this.container, circle, data);
+
+      return this.container;
+    }
+  }]);
+
+  return CircleAnnotationElement;
+}(AnnotationElement);
+
+var PolylineAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement9) {
+  _inherits(PolylineAnnotationElement, _AnnotationElement9);
+
+  function PolylineAnnotationElement(parameters) {
+    var _this3;
+
+    _classCallCheck(this, PolylineAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    _this3 = _possibleConstructorReturn(this, _getPrototypeOf(PolylineAnnotationElement).call(this, parameters, isRenderable, true));
+    _this3.containerClassName = 'polylineAnnotation';
+    _this3.svgElementName = 'svg:polyline';
+    return _this3;
+  }
+
+  _createClass(PolylineAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = this.containerClassName;
+      var data = this.data;
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      var svg = this.svgFactory.create(width, height);
+      var vertices = data.vertices;
+      var points = [];
+
+      for (var i = 0, ii = vertices.length; i < ii; i++) {
+        var x = vertices[i].x - data.rect[0];
+        var y = data.rect[3] - vertices[i].y;
+        points.push(x + ',' + y);
+      }
+
+      points = points.join(' ');
+      var borderWidth = data.borderStyle.width;
+      var polyline = this.svgFactory.createElement(this.svgElementName);
+      polyline.setAttribute('points', points);
+      polyline.setAttribute('stroke-width', borderWidth);
+      polyline.setAttribute('stroke', 'transparent');
+      polyline.setAttribute('fill', 'none');
+      svg.appendChild(polyline);
+      this.container.append(svg);
+
+      this._createPopup(this.container, polyline, data);
+
+      return this.container;
+    }
+  }]);
+
+  return PolylineAnnotationElement;
+}(AnnotationElement);
+
+var PolygonAnnotationElement =
+/*#__PURE__*/
+function (_PolylineAnnotationEl) {
+  _inherits(PolygonAnnotationElement, _PolylineAnnotationEl);
+
+  function PolygonAnnotationElement(parameters) {
+    var _this4;
+
+    _classCallCheck(this, PolygonAnnotationElement);
+
+    _this4 = _possibleConstructorReturn(this, _getPrototypeOf(PolygonAnnotationElement).call(this, parameters));
+    _this4.containerClassName = 'polygonAnnotation';
+    _this4.svgElementName = 'svg:polygon';
+    return _this4;
+  }
+
+  return PolygonAnnotationElement;
+}(PolylineAnnotationElement);
+
+var CaretAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement10) {
+  _inherits(CaretAnnotationElement, _AnnotationElement10);
+
+  function CaretAnnotationElement(parameters) {
+    _classCallCheck(this, CaretAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(CaretAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(CaretAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'caretAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return CaretAnnotationElement;
+}(AnnotationElement);
+
+var InkAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement11) {
+  _inherits(InkAnnotationElement, _AnnotationElement11);
+
+  function InkAnnotationElement(parameters) {
+    var _this5;
+
+    _classCallCheck(this, InkAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    _this5 = _possibleConstructorReturn(this, _getPrototypeOf(InkAnnotationElement).call(this, parameters, isRenderable, true));
+    _this5.containerClassName = 'inkAnnotation';
+    _this5.svgElementName = 'svg:polyline';
+    return _this5;
+  }
+
+  _createClass(InkAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = this.containerClassName;
+      var data = this.data;
+      var width = data.rect[2] - data.rect[0];
+      var height = data.rect[3] - data.rect[1];
+      var svg = this.svgFactory.create(width, height);
+      var inkLists = data.inkLists;
+
+      for (var i = 0, ii = inkLists.length; i < ii; i++) {
+        var inkList = inkLists[i];
+        var points = [];
+
+        for (var j = 0, jj = inkList.length; j < jj; j++) {
+          var x = inkList[j].x - data.rect[0];
+          var y = data.rect[3] - inkList[j].y;
+          points.push(x + ',' + y);
+        }
+
+        points = points.join(' ');
+        var borderWidth = data.borderStyle.width;
+        var polyline = this.svgFactory.createElement(this.svgElementName);
+        polyline.setAttribute('points', points);
+        polyline.setAttribute('stroke-width', borderWidth);
+        polyline.setAttribute('stroke', 'transparent');
+        polyline.setAttribute('fill', 'none');
+
+        this._createPopup(this.container, polyline, data);
+
+        svg.appendChild(polyline);
+      }
+
+      this.container.append(svg);
+      return this.container;
+    }
+  }]);
+
+  return InkAnnotationElement;
+}(AnnotationElement);
+
+var HighlightAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement12) {
+  _inherits(HighlightAnnotationElement, _AnnotationElement12);
+
+  function HighlightAnnotationElement(parameters) {
+    _classCallCheck(this, HighlightAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(HighlightAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(HighlightAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'highlightAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return HighlightAnnotationElement;
+}(AnnotationElement);
+
+var UnderlineAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement13) {
+  _inherits(UnderlineAnnotationElement, _AnnotationElement13);
+
+  function UnderlineAnnotationElement(parameters) {
+    _classCallCheck(this, UnderlineAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(UnderlineAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(UnderlineAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'underlineAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return UnderlineAnnotationElement;
+}(AnnotationElement);
+
+var SquigglyAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement14) {
+  _inherits(SquigglyAnnotationElement, _AnnotationElement14);
+
+  function SquigglyAnnotationElement(parameters) {
+    _classCallCheck(this, SquigglyAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(SquigglyAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(SquigglyAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'squigglyAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return SquigglyAnnotationElement;
+}(AnnotationElement);
+
+var StrikeOutAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement15) {
+  _inherits(StrikeOutAnnotationElement, _AnnotationElement15);
+
+  function StrikeOutAnnotationElement(parameters) {
+    _classCallCheck(this, StrikeOutAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(StrikeOutAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(StrikeOutAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'strikeoutAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return StrikeOutAnnotationElement;
+}(AnnotationElement);
+
+var StampAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement16) {
+  _inherits(StampAnnotationElement, _AnnotationElement16);
+
+  function StampAnnotationElement(parameters) {
+    _classCallCheck(this, StampAnnotationElement);
+
+    var isRenderable = !!(parameters.data.hasPopup || parameters.data.title || parameters.data.contents);
+    return _possibleConstructorReturn(this, _getPrototypeOf(StampAnnotationElement).call(this, parameters, isRenderable, true));
+  }
+
+  _createClass(StampAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'stampAnnotation';
+
+      if (!this.data.hasPopup) {
+        this._createPopup(this.container, null, this.data);
+      }
+
+      return this.container;
+    }
+  }]);
+
+  return StampAnnotationElement;
+}(AnnotationElement);
+
+var FileAttachmentAnnotationElement =
+/*#__PURE__*/
+function (_AnnotationElement17) {
+  _inherits(FileAttachmentAnnotationElement, _AnnotationElement17);
+
+  function FileAttachmentAnnotationElement(parameters) {
+    var _this6;
+
+    _classCallCheck(this, FileAttachmentAnnotationElement);
+
+    _this6 = _possibleConstructorReturn(this, _getPrototypeOf(FileAttachmentAnnotationElement).call(this, parameters, true));
+    var _this6$data$file = _this6.data.file,
+        filename = _this6$data$file.filename,
+        content = _this6$data$file.content;
+    _this6.filename = (0, _display_utils.getFilenameFromUrl)(filename);
+    _this6.content = content;
+
+    if (_this6.linkService.eventBus) {
+      _this6.linkService.eventBus.dispatch('fileattachmentannotation', {
+        source: _assertThisInitialized(_this6),
+        id: (0, _util.stringToPDFString)(filename),
+        filename: filename,
+        content: content
+      });
+    }
+
+    return _this6;
+  }
+
+  _createClass(FileAttachmentAnnotationElement, [{
+    key: "render",
+    value: function render() {
+      this.container.className = 'fileAttachmentAnnotation';
+      var trigger = document.createElement('div');
+      trigger.style.height = this.container.style.height;
+      trigger.style.width = this.container.style.width;
+      trigger.addEventListener('dblclick', this._download.bind(this));
+
+      if (!this.data.hasPopup && (this.data.title || this.data.contents)) {
+        this._createPopup(this.container, trigger, this.data);
+      }
+
+      this.container.appendChild(trigger);
+      return this.container;
+    }
+  }, {
+    key: "_download",
+    value: function _download() {
+      if (!this.downloadManager) {
+        (0, _util.warn)('Download cannot be started due to unavailable download manager');
+        return;
+      }
+
+      this.downloadManager.downloadData(this.content, this.filename, '');
+    }
+  }]);
+
+  return FileAttachmentAnnotationElement;
+}(AnnotationElement);
+
+var AnnotationLayer =
+/*#__PURE__*/
+function () {
+  function AnnotationLayer() {
+    _classCallCheck(this, AnnotationLayer);
+  }
+
+  _createClass(AnnotationLayer, null, [{
+    key: "render",
+    value: function render(parameters) {
+      for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
+        var data = parameters.annotations[i];
+
+        if (!data) {
+          continue;
+        }
+
+        var element = AnnotationElementFactory.create({
+          data: data,
+          layer: parameters.div,
+          page: parameters.page,
+          viewport: parameters.viewport,
+          linkService: parameters.linkService,
+          downloadManager: parameters.downloadManager,
+          imageResourcesPath: parameters.imageResourcesPath || '',
+          renderInteractiveForms: parameters.renderInteractiveForms || false,
+          svgFactory: new _display_utils.DOMSVGFactory()
+        });
+
+        if (element.isRenderable) {
+          parameters.div.appendChild(element.render());
+        }
+      }
+    }
+  }, {
+    key: "update",
+    value: function update(parameters) {
+      for (var i = 0, ii = parameters.annotations.length; i < ii; i++) {
+        var data = parameters.annotations[i];
+        var element = parameters.div.querySelector('[data-annotation-id="' + data.id + '"]');
+
+        if (element) {
+          element.style.transform = 'matrix(' + parameters.viewport.transform.join(',') + ')';
+        }
+      }
+
+      parameters.div.removeAttribute('hidden');
+    }
+  }]);
+
+  return AnnotationLayer;
+}();
+
+exports.AnnotationLayer = AnnotationLayer;
+
+/***/ }),
+/* 164 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.SVGGraphics = void 0;
+
+var _util = __w_pdfjs_require__(1);
+
+var _display_utils = __w_pdfjs_require__(151);
+
+var _is_node = _interopRequireDefault(__w_pdfjs_require__(4));
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var SVGGraphics = function SVGGraphics() {
+  throw new Error('Not implemented: SVGGraphics');
+};
+
+exports.SVGGraphics = SVGGraphics;
+{
+  var opListToTree = function opListToTree(opList) {
+    var opTree = [];
+    var tmp = [];
+    var _iteratorNormalCompletion = true;
+    var _didIteratorError = false;
+    var _iteratorError = undefined;
+
+    try {
+      for (var _iterator = opList[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+        var opListElement = _step.value;
+
+        if (opListElement.fn === 'save') {
+          opTree.push({
+            'fnId': 92,
+            'fn': 'group',
+            'items': []
+          });
+          tmp.push(opTree);
+          opTree = opTree[opTree.length - 1].items;
+          continue;
+        }
+
+        if (opListElement.fn === 'restore') {
+          opTree = tmp.pop();
+        } else {
+          opTree.push(opListElement);
+        }
+      }
+    } catch (err) {
+      _didIteratorError = true;
+      _iteratorError = err;
+    } finally {
+      try {
+        if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+          _iterator["return"]();
+        }
+      } finally {
+        if (_didIteratorError) {
+          throw _iteratorError;
+        }
+      }
+    }
+
+    return opTree;
+  };
+
+  var pf = function pf(value) {
+    if (Number.isInteger(value)) {
+      return value.toString();
+    }
+
+    var s = value.toFixed(10);
+    var i = s.length - 1;
+
+    if (s[i] !== '0') {
+      return s;
+    }
+
+    do {
+      i--;
+    } while (s[i] === '0');
+
+    return s.substring(0, s[i] === '.' ? i : i + 1);
+  };
+
+  var pm = function pm(m) {
+    if (m[4] === 0 && m[5] === 0) {
+      if (m[1] === 0 && m[2] === 0) {
+        if (m[0] === 1 && m[3] === 1) {
+          return '';
+        }
+
+        return "scale(".concat(pf(m[0]), " ").concat(pf(m[3]), ")");
+      }
+
+      if (m[0] === m[3] && m[1] === -m[2]) {
+        var a = Math.acos(m[0]) * 180 / Math.PI;
+        return "rotate(".concat(pf(a), ")");
+      }
+    } else {
+      if (m[0] === 1 && m[1] === 0 && m[2] === 0 && m[3] === 1) {
+        return "translate(".concat(pf(m[4]), " ").concat(pf(m[5]), ")");
+      }
+    }
+
+    return "matrix(".concat(pf(m[0]), " ").concat(pf(m[1]), " ").concat(pf(m[2]), " ").concat(pf(m[3]), " ").concat(pf(m[4]), " ") + "".concat(pf(m[5]), ")");
+  };
+
+  var SVG_DEFAULTS = {
+    fontStyle: 'normal',
+    fontWeight: 'normal',
+    fillColor: '#000000'
+  };
+  var XML_NS = 'http://www.w3.org/XML/1998/namespace';
+  var XLINK_NS = 'http://www.w3.org/1999/xlink';
+  var LINE_CAP_STYLES = ['butt', 'round', 'square'];
+  var LINE_JOIN_STYLES = ['miter', 'round', 'bevel'];
+
+  var convertImgDataToPng = function () {
+    var PNG_HEADER = new Uint8Array([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]);
+    var CHUNK_WRAPPER_SIZE = 12;
+    var crcTable = new Int32Array(256);
+
+    for (var i = 0; i < 256; i++) {
+      var c = i;
+
+      for (var h = 0; h < 8; h++) {
+        if (c & 1) {
+          c = 0xedB88320 ^ c >> 1 & 0x7fffffff;
+        } else {
+          c = c >> 1 & 0x7fffffff;
+        }
+      }
+
+      crcTable[i] = c;
+    }
+
+    function crc32(data, start, end) {
+      var crc = -1;
+
+      for (var _i = start; _i < end; _i++) {
+        var a = (crc ^ data[_i]) & 0xff;
+        var b = crcTable[a];
+        crc = crc >>> 8 ^ b;
+      }
+
+      return crc ^ -1;
+    }
+
+    function writePngChunk(type, body, data, offset) {
+      var p = offset;
+      var len = body.length;
+      data[p] = len >> 24 & 0xff;
+      data[p + 1] = len >> 16 & 0xff;
+      data[p + 2] = len >> 8 & 0xff;
+      data[p + 3] = len & 0xff;
+      p += 4;
+      data[p] = type.charCodeAt(0) & 0xff;
+      data[p + 1] = type.charCodeAt(1) & 0xff;
+      data[p + 2] = type.charCodeAt(2) & 0xff;
+      data[p + 3] = type.charCodeAt(3) & 0xff;
+      p += 4;
+      data.set(body, p);
+      p += body.length;
+      var crc = crc32(data, offset + 4, p);
+      data[p] = crc >> 24 & 0xff;
+      data[p + 1] = crc >> 16 & 0xff;
+      data[p + 2] = crc >> 8 & 0xff;
+      data[p + 3] = crc & 0xff;
+    }
+
+    function adler32(data, start, end) {
+      var a = 1;
+      var b = 0;
+
+      for (var _i2 = start; _i2 < end; ++_i2) {
+        a = (a + (data[_i2] & 0xff)) % 65521;
+        b = (b + a) % 65521;
+      }
+
+      return b << 16 | a;
+    }
+
+    function deflateSync(literals) {
+      if (!(0, _is_node["default"])()) {
+        return deflateSyncUncompressed(literals);
+      }
+
+      try {
+        var input;
+
+        if (parseInt(process.versions.node) >= 8) {
+          input = literals;
+        } else {
+          input = new Buffer(literals);
+        }
+
+        var output = require('zlib').deflateSync(input, {
+          level: 9
+        });
+
+        return output instanceof Uint8Array ? output : new Uint8Array(output);
+      } catch (e) {
+        (0, _util.warn)('Not compressing PNG because zlib.deflateSync is unavailable: ' + e);
+      }
+
+      return deflateSyncUncompressed(literals);
+    }
+
+    function deflateSyncUncompressed(literals) {
+      var len = literals.length;
+      var maxBlockLength = 0xFFFF;
+      var deflateBlocks = Math.ceil(len / maxBlockLength);
+      var idat = new Uint8Array(2 + len + deflateBlocks * 5 + 4);
+      var pi = 0;
+      idat[pi++] = 0x78;
+      idat[pi++] = 0x9c;
+      var pos = 0;
+
+      while (len > maxBlockLength) {
+        idat[pi++] = 0x00;
+        idat[pi++] = 0xff;
+        idat[pi++] = 0xff;
+        idat[pi++] = 0x00;
+        idat[pi++] = 0x00;
+        idat.set(literals.subarray(pos, pos + maxBlockLength), pi);
+        pi += maxBlockLength;
+        pos += maxBlockLength;
+        len -= maxBlockLength;
+      }
+
+      idat[pi++] = 0x01;
+      idat[pi++] = len & 0xff;
+      idat[pi++] = len >> 8 & 0xff;
+      idat[pi++] = ~len & 0xffff & 0xff;
+      idat[pi++] = (~len & 0xffff) >> 8 & 0xff;
+      idat.set(literals.subarray(pos), pi);
+      pi += literals.length - pos;
+      var adler = adler32(literals, 0, literals.length);
+      idat[pi++] = adler >> 24 & 0xff;
+      idat[pi++] = adler >> 16 & 0xff;
+      idat[pi++] = adler >> 8 & 0xff;
+      idat[pi++] = adler & 0xff;
+      return idat;
+    }
+
+    function encode(imgData, kind, forceDataSchema, isMask) {
+      var width = imgData.width;
+      var height = imgData.height;
+      var bitDepth, colorType, lineSize;
+      var bytes = imgData.data;
+
+      switch (kind) {
+        case _util.ImageKind.GRAYSCALE_1BPP:
+          colorType = 0;
+          bitDepth = 1;
+          lineSize = width + 7 >> 3;
+          break;
+
+        case _util.ImageKind.RGB_24BPP:
+          colorType = 2;
+          bitDepth = 8;
+          lineSize = width * 3;
+          break;
+
+        case _util.ImageKind.RGBA_32BPP:
+          colorType = 6;
+          bitDepth = 8;
+          lineSize = width * 4;
+          break;
+
+        default:
+          throw new Error('invalid format');
+      }
+
+      var literals = new Uint8Array((1 + lineSize) * height);
+      var offsetLiterals = 0,
+          offsetBytes = 0;
+
+      for (var y = 0; y < height; ++y) {
+        literals[offsetLiterals++] = 0;
+        literals.set(bytes.subarray(offsetBytes, offsetBytes + lineSize), offsetLiterals);
+        offsetBytes += lineSize;
+        offsetLiterals += lineSize;
+      }
+
+      if (kind === _util.ImageKind.GRAYSCALE_1BPP && isMask) {
+        offsetLiterals = 0;
+
+        for (var _y = 0; _y < height; _y++) {
+          offsetLiterals++;
+
+          for (var _i3 = 0; _i3 < lineSize; _i3++) {
+            literals[offsetLiterals++] ^= 0xFF;
+          }
+        }
+      }
+
+      var ihdr = new Uint8Array([width >> 24 & 0xff, width >> 16 & 0xff, width >> 8 & 0xff, width & 0xff, height >> 24 & 0xff, height >> 16 & 0xff, height >> 8 & 0xff, height & 0xff, bitDepth, colorType, 0x00, 0x00, 0x00]);
+      var idat = deflateSync(literals);
+      var pngLength = PNG_HEADER.length + CHUNK_WRAPPER_SIZE * 3 + ihdr.length + idat.length;
+      var data = new Uint8Array(pngLength);
+      var offset = 0;
+      data.set(PNG_HEADER, offset);
+      offset += PNG_HEADER.length;
+      writePngChunk('IHDR', ihdr, data, offset);
+      offset += CHUNK_WRAPPER_SIZE + ihdr.length;
+      writePngChunk('IDATA', idat, data, offset);
+      offset += CHUNK_WRAPPER_SIZE + idat.length;
+      writePngChunk('IEND', new Uint8Array(0), data, offset);
+      return (0, _util.createObjectURL)(data, 'image/png', forceDataSchema);
+    }
+
+    return function convertImgDataToPng(imgData, forceDataSchema, isMask) {
+      var kind = imgData.kind === undefined ? _util.ImageKind.GRAYSCALE_1BPP : imgData.kind;
+      return encode(imgData, kind, forceDataSchema, isMask);
+    };
+  }();
+
+  var SVGExtraState =
+  /*#__PURE__*/
+  function () {
+    function SVGExtraState() {
+      _classCallCheck(this, SVGExtraState);
+
+      this.fontSizeScale = 1;
+      this.fontWeight = SVG_DEFAULTS.fontWeight;
+      this.fontSize = 0;
+      this.textMatrix = _util.IDENTITY_MATRIX;
+      this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
+      this.leading = 0;
+      this.textRenderingMode = _util.TextRenderingMode.FILL;
+      this.textMatrixScale = 1;
+      this.x = 0;
+      this.y = 0;
+      this.lineX = 0;
+      this.lineY = 0;
+      this.charSpacing = 0;
+      this.wordSpacing = 0;
+      this.textHScale = 1;
+      this.textRise = 0;
+      this.fillColor = SVG_DEFAULTS.fillColor;
+      this.strokeColor = '#000000';
+      this.fillAlpha = 1;
+      this.strokeAlpha = 1;
+      this.lineWidth = 1;
+      this.lineJoin = '';
+      this.lineCap = '';
+      this.miterLimit = 0;
+      this.dashArray = [];
+      this.dashPhase = 0;
+      this.dependencies = [];
+      this.activeClipUrl = null;
+      this.clipGroup = null;
+      this.maskId = '';
+    }
+
+    _createClass(SVGExtraState, [{
+      key: "clone",
+      value: function clone() {
+        return Object.create(this);
+      }
+    }, {
+      key: "setCurrentPoint",
+      value: function setCurrentPoint(x, y) {
+        this.x = x;
+        this.y = y;
+      }
+    }]);
+
+    return SVGExtraState;
+  }();
+
+  var clipCount = 0;
+  var maskCount = 0;
+  var shadingCount = 0;
+
+  exports.SVGGraphics = SVGGraphics =
+  /*#__PURE__*/
+  function () {
+    function SVGGraphics(commonObjs, objs, forceDataSchema) {
+      _classCallCheck(this, SVGGraphics);
+
+      this.svgFactory = new _display_utils.DOMSVGFactory();
+      this.current = new SVGExtraState();
+      this.transformMatrix = _util.IDENTITY_MATRIX;
+      this.transformStack = [];
+      this.extraStack = [];
+      this.commonObjs = commonObjs;
+      this.objs = objs;
+      this.pendingClip = null;
+      this.pendingEOFill = false;
+      this.embedFonts = false;
+      this.embeddedFonts = Object.create(null);
+      this.cssStyle = null;
+      this.forceDataSchema = !!forceDataSchema;
+      this._operatorIdMapping = [];
+
+      for (var op in _util.OPS) {
+        this._operatorIdMapping[_util.OPS[op]] = op;
+      }
+    }
+
+    _createClass(SVGGraphics, [{
+      key: "save",
+      value: function save() {
+        this.transformStack.push(this.transformMatrix);
+        var old = this.current;
+        this.extraStack.push(old);
+        this.current = old.clone();
+      }
+    }, {
+      key: "restore",
+      value: function restore() {
+        this.transformMatrix = this.transformStack.pop();
+        this.current = this.extraStack.pop();
+        this.pendingClip = null;
+        this.tgrp = null;
+      }
+    }, {
+      key: "group",
+      value: function group(items) {
+        this.save();
+        this.executeOpTree(items);
+        this.restore();
+      }
+    }, {
+      key: "loadDependencies",
+      value: function loadDependencies(operatorList) {
+        var _this = this;
+
+        var fnArray = operatorList.fnArray;
+        var argsArray = operatorList.argsArray;
+
+        for (var i = 0, ii = fnArray.length; i < ii; i++) {
+          if (fnArray[i] !== _util.OPS.dependency) {
+            continue;
+          }
+
+          var _iteratorNormalCompletion2 = true;
+          var _didIteratorError2 = false;
+          var _iteratorError2 = undefined;
+
+          try {
+            var _loop = function _loop() {
+              var obj = _step2.value;
+              var objsPool = obj.startsWith('g_') ? _this.commonObjs : _this.objs;
+              var promise = new Promise(function (resolve) {
+                objsPool.get(obj, resolve);
+              });
+
+              _this.current.dependencies.push(promise);
+            };
+
+            for (var _iterator2 = argsArray[i][Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+              _loop();
+            }
+          } catch (err) {
+            _didIteratorError2 = true;
+            _iteratorError2 = err;
+          } finally {
+            try {
+              if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
+                _iterator2["return"]();
+              }
+            } finally {
+              if (_didIteratorError2) {
+                throw _iteratorError2;
+              }
+            }
+          }
+        }
+
+        return Promise.all(this.current.dependencies);
+      }
+    }, {
+      key: "transform",
+      value: function transform(a, b, c, d, e, f) {
+        var transformMatrix = [a, b, c, d, e, f];
+        this.transformMatrix = _util.Util.transform(this.transformMatrix, transformMatrix);
+        this.tgrp = null;
+      }
+    }, {
+      key: "getSVG",
+      value: function getSVG(operatorList, viewport) {
+        var _this2 = this;
+
+        this.viewport = viewport;
+
+        var svgElement = this._initialize(viewport);
+
+        return this.loadDependencies(operatorList).then(function () {
+          _this2.transformMatrix = _util.IDENTITY_MATRIX;
+
+          _this2.executeOpTree(_this2.convertOpList(operatorList));
+
+          return svgElement;
+        });
+      }
+    }, {
+      key: "convertOpList",
+      value: function convertOpList(operatorList) {
+        var operatorIdMapping = this._operatorIdMapping;
+        var argsArray = operatorList.argsArray;
+        var fnArray = operatorList.fnArray;
+        var opList = [];
+
+        for (var i = 0, ii = fnArray.length; i < ii; i++) {
+          var fnId = fnArray[i];
+          opList.push({
+            'fnId': fnId,
+            'fn': operatorIdMapping[fnId],
+            'args': argsArray[i]
+          });
+        }
+
+        return opListToTree(opList);
+      }
+    }, {
+      key: "executeOpTree",
+      value: function executeOpTree(opTree) {
+        var _iteratorNormalCompletion3 = true;
+        var _didIteratorError3 = false;
+        var _iteratorError3 = undefined;
+
+        try {
+          for (var _iterator3 = opTree[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+            var opTreeElement = _step3.value;
+            var fn = opTreeElement.fn;
+            var fnId = opTreeElement.fnId;
+            var args = opTreeElement.args;
+
+            switch (fnId | 0) {
+              case _util.OPS.beginText:
+                this.beginText();
+                break;
+
+              case _util.OPS.dependency:
+                break;
+
+              case _util.OPS.setLeading:
+                this.setLeading(args);
+                break;
+
+              case _util.OPS.setLeadingMoveText:
+                this.setLeadingMoveText(args[0], args[1]);
+                break;
+
+              case _util.OPS.setFont:
+                this.setFont(args);
+                break;
+
+              case _util.OPS.showText:
+                this.showText(args[0]);
+                break;
+
+              case _util.OPS.showSpacedText:
+                this.showText(args[0]);
+                break;
+
+              case _util.OPS.endText:
+                this.endText();
+                break;
+
+              case _util.OPS.moveText:
+                this.moveText(args[0], args[1]);
+                break;
+
+              case _util.OPS.setCharSpacing:
+                this.setCharSpacing(args[0]);
+                break;
+
+              case _util.OPS.setWordSpacing:
+                this.setWordSpacing(args[0]);
+                break;
+
+              case _util.OPS.setHScale:
+                this.setHScale(args[0]);
+                break;
+
+              case _util.OPS.setTextMatrix:
+                this.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+                break;
+
+              case _util.OPS.setTextRise:
+                this.setTextRise(args[0]);
+                break;
+
+              case _util.OPS.setTextRenderingMode:
+                this.setTextRenderingMode(args[0]);
+                break;
+
+              case _util.OPS.setLineWidth:
+                this.setLineWidth(args[0]);
+                break;
+
+              case _util.OPS.setLineJoin:
+                this.setLineJoin(args[0]);
+                break;
+
+              case _util.OPS.setLineCap:
+                this.setLineCap(args[0]);
+                break;
+
+              case _util.OPS.setMiterLimit:
+                this.setMiterLimit(args[0]);
+                break;
+
+              case _util.OPS.setFillRGBColor:
+                this.setFillRGBColor(args[0], args[1], args[2]);
+                break;
+
+              case _util.OPS.setStrokeRGBColor:
+                this.setStrokeRGBColor(args[0], args[1], args[2]);
+                break;
+
+              case _util.OPS.setStrokeColorN:
+                this.setStrokeColorN(args);
+                break;
+
+              case _util.OPS.setFillColorN:
+                this.setFillColorN(args);
+                break;
+
+              case _util.OPS.shadingFill:
+                this.shadingFill(args[0]);
+                break;
+
+              case _util.OPS.setDash:
+                this.setDash(args[0], args[1]);
+                break;
+
+              case _util.OPS.setRenderingIntent:
+                this.setRenderingIntent(args[0]);
+                break;
+
+              case _util.OPS.setFlatness:
+                this.setFlatness(args[0]);
+                break;
+
+              case _util.OPS.setGState:
+                this.setGState(args[0]);
+                break;
+
+              case _util.OPS.fill:
+                this.fill();
+                break;
+
+              case _util.OPS.eoFill:
+                this.eoFill();
+                break;
+
+              case _util.OPS.stroke:
+                this.stroke();
+                break;
+
+              case _util.OPS.fillStroke:
+                this.fillStroke();
+                break;
+
+              case _util.OPS.eoFillStroke:
+                this.eoFillStroke();
+                break;
+
+              case _util.OPS.clip:
+                this.clip('nonzero');
+                break;
+
+              case _util.OPS.eoClip:
+                this.clip('evenodd');
+                break;
+
+              case _util.OPS.paintSolidColorImageMask:
+                this.paintSolidColorImageMask();
+                break;
+
+              case _util.OPS.paintJpegXObject:
+                this.paintJpegXObject(args[0], args[1], args[2]);
+                break;
+
+              case _util.OPS.paintImageXObject:
+                this.paintImageXObject(args[0]);
+                break;
+
+              case _util.OPS.paintInlineImageXObject:
+                this.paintInlineImageXObject(args[0]);
+                break;
+
+              case _util.OPS.paintImageMaskXObject:
+                this.paintImageMaskXObject(args[0]);
+                break;
+
+              case _util.OPS.paintFormXObjectBegin:
+                this.paintFormXObjectBegin(args[0], args[1]);
+                break;
+
+              case _util.OPS.paintFormXObjectEnd:
+                this.paintFormXObjectEnd();
+                break;
+
+              case _util.OPS.closePath:
+                this.closePath();
+                break;
+
+              case _util.OPS.closeStroke:
+                this.closeStroke();
+                break;
+
+              case _util.OPS.closeFillStroke:
+                this.closeFillStroke();
+                break;
+
+              case _util.OPS.closeEOFillStroke:
+                this.closeEOFillStroke();
+                break;
+
+              case _util.OPS.nextLine:
+                this.nextLine();
+                break;
+
+              case _util.OPS.transform:
+                this.transform(args[0], args[1], args[2], args[3], args[4], args[5]);
+                break;
+
+              case _util.OPS.constructPath:
+                this.constructPath(args[0], args[1]);
+                break;
+
+              case _util.OPS.endPath:
+                this.endPath();
+                break;
+
+              case 92:
+                this.group(opTreeElement.items);
+                break;
+
+              default:
+                (0, _util.warn)("Unimplemented operator ".concat(fn));
+                break;
+            }
+          }
+        } catch (err) {
+          _didIteratorError3 = true;
+          _iteratorError3 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
+              _iterator3["return"]();
+            }
+          } finally {
+            if (_didIteratorError3) {
+              throw _iteratorError3;
+            }
+          }
+        }
+      }
+    }, {
+      key: "setWordSpacing",
+      value: function setWordSpacing(wordSpacing) {
+        this.current.wordSpacing = wordSpacing;
+      }
+    }, {
+      key: "setCharSpacing",
+      value: function setCharSpacing(charSpacing) {
+        this.current.charSpacing = charSpacing;
+      }
+    }, {
+      key: "nextLine",
+      value: function nextLine() {
+        this.moveText(0, this.current.leading);
+      }
+    }, {
+      key: "setTextMatrix",
+      value: function setTextMatrix(a, b, c, d, e, f) {
+        var current = this.current;
+        current.textMatrix = current.lineMatrix = [a, b, c, d, e, f];
+        current.textMatrixScale = Math.sqrt(a * a + b * b);
+        current.x = current.lineX = 0;
+        current.y = current.lineY = 0;
+        current.xcoords = [];
+        current.tspan = this.svgFactory.createElement('svg:tspan');
+        current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+        current.tspan.setAttributeNS(null, 'font-size', "".concat(pf(current.fontSize), "px"));
+        current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+        current.txtElement = this.svgFactory.createElement('svg:text');
+        current.txtElement.appendChild(current.tspan);
+      }
+    }, {
+      key: "beginText",
+      value: function beginText() {
+        var current = this.current;
+        current.x = current.lineX = 0;
+        current.y = current.lineY = 0;
+        current.textMatrix = _util.IDENTITY_MATRIX;
+        current.lineMatrix = _util.IDENTITY_MATRIX;
+        current.textMatrixScale = 1;
+        current.tspan = this.svgFactory.createElement('svg:tspan');
+        current.txtElement = this.svgFactory.createElement('svg:text');
+        current.txtgrp = this.svgFactory.createElement('svg:g');
+        current.xcoords = [];
+      }
+    }, {
+      key: "moveText",
+      value: function moveText(x, y) {
+        var current = this.current;
+        current.x = current.lineX += x;
+        current.y = current.lineY += y;
+        current.xcoords = [];
+        current.tspan = this.svgFactory.createElement('svg:tspan');
+        current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+        current.tspan.setAttributeNS(null, 'font-size', "".concat(pf(current.fontSize), "px"));
+        current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+      }
+    }, {
+      key: "showText",
+      value: function showText(glyphs) {
+        var current = this.current;
+        var font = current.font;
+        var fontSize = current.fontSize;
+
+        if (fontSize === 0) {
+          return;
+        }
+
+        var charSpacing = current.charSpacing;
+        var wordSpacing = current.wordSpacing;
+        var fontDirection = current.fontDirection;
+        var textHScale = current.textHScale * fontDirection;
+        var vertical = font.vertical;
+        var widthAdvanceScale = fontSize * current.fontMatrix[0];
+        var x = 0;
+        var _iteratorNormalCompletion4 = true;
+        var _didIteratorError4 = false;
+        var _iteratorError4 = undefined;
+
+        try {
+          for (var _iterator4 = glyphs[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+            var glyph = _step4.value;
+
+            if (glyph === null) {
+              x += fontDirection * wordSpacing;
+              continue;
+            } else if ((0, _util.isNum)(glyph)) {
+              x += -glyph * fontSize * 0.001;
+              continue;
+            }
+
+            var width = glyph.width;
+            var character = glyph.fontChar;
+            var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing;
+            var charWidth = width * widthAdvanceScale + spacing * fontDirection;
+
+            if (!glyph.isInFont && !font.missingFile) {
+              x += charWidth;
+              continue;
+            }
+
+            current.xcoords.push(current.x + x * textHScale);
+            current.tspan.textContent += character;
+            x += charWidth;
+          }
+        } catch (err) {
+          _didIteratorError4 = true;
+          _iteratorError4 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
+              _iterator4["return"]();
+            }
+          } finally {
+            if (_didIteratorError4) {
+              throw _iteratorError4;
+            }
+          }
+        }
+
+        if (vertical) {
+          current.y -= x * textHScale;
+        } else {
+          current.x += x * textHScale;
+        }
+
+        current.tspan.setAttributeNS(null, 'x', current.xcoords.map(pf).join(' '));
+        current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+        current.tspan.setAttributeNS(null, 'font-family', current.fontFamily);
+        current.tspan.setAttributeNS(null, 'font-size', "".concat(pf(current.fontSize), "px"));
+
+        if (current.fontStyle !== SVG_DEFAULTS.fontStyle) {
+          current.tspan.setAttributeNS(null, 'font-style', current.fontStyle);
+        }
+
+        if (current.fontWeight !== SVG_DEFAULTS.fontWeight) {
+          current.tspan.setAttributeNS(null, 'font-weight', current.fontWeight);
+        }
+
+        var fillStrokeMode = current.textRenderingMode & _util.TextRenderingMode.FILL_STROKE_MASK;
+
+        if (fillStrokeMode === _util.TextRenderingMode.FILL || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          if (current.fillColor !== SVG_DEFAULTS.fillColor) {
+            current.tspan.setAttributeNS(null, 'fill', current.fillColor);
+          }
+
+          if (current.fillAlpha < 1) {
+            current.tspan.setAttributeNS(null, 'fill-opacity', current.fillAlpha);
+          }
+        } else if (current.textRenderingMode === _util.TextRenderingMode.ADD_TO_PATH) {
+          current.tspan.setAttributeNS(null, 'fill', 'transparent');
+        } else {
+          current.tspan.setAttributeNS(null, 'fill', 'none');
+        }
+
+        if (fillStrokeMode === _util.TextRenderingMode.STROKE || fillStrokeMode === _util.TextRenderingMode.FILL_STROKE) {
+          var lineWidthScale = 1 / (current.textMatrixScale || 1);
+
+          this._setStrokeAttributes(current.tspan, lineWidthScale);
+        }
+
+        var textMatrix = current.textMatrix;
+
+        if (current.textRise !== 0) {
+          textMatrix = textMatrix.slice();
+          textMatrix[5] += current.textRise;
+        }
+
+        current.txtElement.setAttributeNS(null, 'transform', "".concat(pm(textMatrix), " scale(1, -1)"));
+        current.txtElement.setAttributeNS(XML_NS, 'xml:space', 'preserve');
+        current.txtElement.appendChild(current.tspan);
+        current.txtgrp.appendChild(current.txtElement);
+
+        this._ensureTransformGroup().appendChild(current.txtElement);
+      }
+    }, {
+      key: "setLeadingMoveText",
+      value: function setLeadingMoveText(x, y) {
+        this.setLeading(-y);
+        this.moveText(x, y);
+      }
+    }, {
+      key: "addFontStyle",
+      value: function addFontStyle(fontObj) {
+        if (!this.cssStyle) {
+          this.cssStyle = this.svgFactory.createElement('svg:style');
+          this.cssStyle.setAttributeNS(null, 'type', 'text/css');
+          this.defs.appendChild(this.cssStyle);
+        }
+
+        var url = (0, _util.createObjectURL)(fontObj.data, fontObj.mimetype, this.forceDataSchema);
+        this.cssStyle.textContent += "@font-face { font-family: \"".concat(fontObj.loadedName, "\";") + " src: url(".concat(url, "); }\n");
+      }
+    }, {
+      key: "setFont",
+      value: function setFont(details) {
+        var current = this.current;
+        var fontObj = this.commonObjs.get(details[0]);
+        var size = details[1];
+        current.font = fontObj;
+
+        if (this.embedFonts && fontObj.data && !this.embeddedFonts[fontObj.loadedName]) {
+          this.addFontStyle(fontObj);
+          this.embeddedFonts[fontObj.loadedName] = fontObj;
+        }
+
+        current.fontMatrix = fontObj.fontMatrix ? fontObj.fontMatrix : _util.FONT_IDENTITY_MATRIX;
+        var bold = fontObj.black ? fontObj.bold ? 'bolder' : 'bold' : fontObj.bold ? 'bold' : 'normal';
+        var italic = fontObj.italic ? 'italic' : 'normal';
+
+        if (size < 0) {
+          size = -size;
+          current.fontDirection = -1;
+        } else {
+          current.fontDirection = 1;
+        }
+
+        current.fontSize = size;
+        current.fontFamily = fontObj.loadedName;
+        current.fontWeight = bold;
+        current.fontStyle = italic;
+        current.tspan = this.svgFactory.createElement('svg:tspan');
+        current.tspan.setAttributeNS(null, 'y', pf(-current.y));
+        current.xcoords = [];
+      }
+    }, {
+      key: "endText",
+      value: function endText() {
+        var current = this.current;
+
+        if (current.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG && current.txtElement && current.txtElement.hasChildNodes()) {
+          current.element = current.txtElement;
+          this.clip('nonzero');
+          this.endPath();
+        }
+      }
+    }, {
+      key: "setLineWidth",
+      value: function setLineWidth(width) {
+        if (width > 0) {
+          this.current.lineWidth = width;
+        }
+      }
+    }, {
+      key: "setLineCap",
+      value: function setLineCap(style) {
+        this.current.lineCap = LINE_CAP_STYLES[style];
+      }
+    }, {
+      key: "setLineJoin",
+      value: function setLineJoin(style) {
+        this.current.lineJoin = LINE_JOIN_STYLES[style];
+      }
+    }, {
+      key: "setMiterLimit",
+      value: function setMiterLimit(limit) {
+        this.current.miterLimit = limit;
+      }
+    }, {
+      key: "setStrokeAlpha",
+      value: function setStrokeAlpha(strokeAlpha) {
+        this.current.strokeAlpha = strokeAlpha;
+      }
+    }, {
+      key: "setStrokeRGBColor",
+      value: function setStrokeRGBColor(r, g, b) {
+        this.current.strokeColor = _util.Util.makeCssRgb(r, g, b);
+      }
+    }, {
+      key: "setFillAlpha",
+      value: function setFillAlpha(fillAlpha) {
+        this.current.fillAlpha = fillAlpha;
+      }
+    }, {
+      key: "setFillRGBColor",
+      value: function setFillRGBColor(r, g, b) {
+        this.current.fillColor = _util.Util.makeCssRgb(r, g, b);
+        this.current.tspan = this.svgFactory.createElement('svg:tspan');
+        this.current.xcoords = [];
+      }
+    }, {
+      key: "setStrokeColorN",
+      value: function setStrokeColorN(args) {
+        this.current.strokeColor = this._makeColorN_Pattern(args);
+      }
+    }, {
+      key: "setFillColorN",
+      value: function setFillColorN(args) {
+        this.current.fillColor = this._makeColorN_Pattern(args);
+      }
+    }, {
+      key: "shadingFill",
+      value: function shadingFill(args) {
+        var width = this.viewport.width;
+        var height = this.viewport.height;
+
+        var inv = _util.Util.inverseTransform(this.transformMatrix);
+
+        var bl = _util.Util.applyTransform([0, 0], inv);
+
+        var br = _util.Util.applyTransform([0, height], inv);
+
+        var ul = _util.Util.applyTransform([width, 0], inv);
+
+        var ur = _util.Util.applyTransform([width, height], inv);
+
+        var x0 = Math.min(bl[0], br[0], ul[0], ur[0]);
+        var y0 = Math.min(bl[1], br[1], ul[1], ur[1]);
+        var x1 = Math.max(bl[0], br[0], ul[0], ur[0]);
+        var y1 = Math.max(bl[1], br[1], ul[1], ur[1]);
+        var rect = this.svgFactory.createElement('svg:rect');
+        rect.setAttributeNS(null, 'x', x0);
+        rect.setAttributeNS(null, 'y', y0);
+        rect.setAttributeNS(null, 'width', x1 - x0);
+        rect.setAttributeNS(null, 'height', y1 - y0);
+        rect.setAttributeNS(null, 'fill', this._makeShadingPattern(args));
+
+        this._ensureTransformGroup().appendChild(rect);
+      }
+    }, {
+      key: "_makeColorN_Pattern",
+      value: function _makeColorN_Pattern(args) {
+        if (args[0] === 'TilingPattern') {
+          return this._makeTilingPattern(args);
+        }
+
+        return this._makeShadingPattern(args);
+      }
+    }, {
+      key: "_makeTilingPattern",
+      value: function _makeTilingPattern(args) {
+        var color = args[1];
+        var operatorList = args[2];
+        var matrix = args[3] || _util.IDENTITY_MATRIX;
+
+        var _args$ = _slicedToArray(args[4], 4),
+            x0 = _args$[0],
+            y0 = _args$[1],
+            x1 = _args$[2],
+            y1 = _args$[3];
+
+        var xstep = args[5];
+        var ystep = args[6];
+        var paintType = args[7];
+        var tilingId = "shading".concat(shadingCount++);
+
+        var _Util$applyTransform = _util.Util.applyTransform([x0, y0], matrix),
+            _Util$applyTransform2 = _slicedToArray(_Util$applyTransform, 2),
+            tx0 = _Util$applyTransform2[0],
+            ty0 = _Util$applyTransform2[1];
+
+        var _Util$applyTransform3 = _util.Util.applyTransform([x1, y1], matrix),
+            _Util$applyTransform4 = _slicedToArray(_Util$applyTransform3, 2),
+            tx1 = _Util$applyTransform4[0],
+            ty1 = _Util$applyTransform4[1];
+
+        var _Util$singularValueDe = _util.Util.singularValueDecompose2dScale(matrix),
+            _Util$singularValueDe2 = _slicedToArray(_Util$singularValueDe, 2),
+            xscale = _Util$singularValueDe2[0],
+            yscale = _Util$singularValueDe2[1];
+
+        var txstep = xstep * xscale;
+        var tystep = ystep * yscale;
+        var tiling = this.svgFactory.createElement('svg:pattern');
+        tiling.setAttributeNS(null, 'id', tilingId);
+        tiling.setAttributeNS(null, 'patternUnits', 'userSpaceOnUse');
+        tiling.setAttributeNS(null, 'width', txstep);
+        tiling.setAttributeNS(null, 'height', tystep);
+        tiling.setAttributeNS(null, 'x', "".concat(tx0));
+        tiling.setAttributeNS(null, 'y', "".concat(ty0));
+        var svg = this.svg;
+        var transformMatrix = this.transformMatrix;
+        var fillColor = this.current.fillColor;
+        var strokeColor = this.current.strokeColor;
+        var bbox = this.svgFactory.create(tx1 - tx0, ty1 - ty0);
+        this.svg = bbox;
+        this.transformMatrix = matrix;
+
+        if (paintType === 2) {
+          var cssColor = _util.Util.makeCssRgb.apply(_util.Util, _toConsumableArray(color));
+
+          this.current.fillColor = cssColor;
+          this.current.strokeColor = cssColor;
+        }
+
+        this.executeOpTree(this.convertOpList(operatorList));
+        this.svg = svg;
+        this.transformMatrix = transformMatrix;
+        this.current.fillColor = fillColor;
+        this.current.strokeColor = strokeColor;
+        tiling.appendChild(bbox.childNodes[0]);
+        this.defs.appendChild(tiling);
+        return "url(#".concat(tilingId, ")");
+      }
+    }, {
+      key: "_makeShadingPattern",
+      value: function _makeShadingPattern(args) {
+        switch (args[0]) {
+          case 'RadialAxial':
+            var shadingId = "shading".concat(shadingCount++);
+            var colorStops = args[2];
+            var gradient;
+
+            switch (args[1]) {
+              case 'axial':
+                var point0 = args[3];
+                var point1 = args[4];
+                gradient = this.svgFactory.createElement('svg:linearGradient');
+                gradient.setAttributeNS(null, 'id', shadingId);
+                gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');
+                gradient.setAttributeNS(null, 'x1', point0[0]);
+                gradient.setAttributeNS(null, 'y1', point0[1]);
+                gradient.setAttributeNS(null, 'x2', point1[0]);
+                gradient.setAttributeNS(null, 'y2', point1[1]);
+                break;
+
+              case 'radial':
+                var focalPoint = args[3];
+                var circlePoint = args[4];
+                var focalRadius = args[5];
+                var circleRadius = args[6];
+                gradient = this.svgFactory.createElement('svg:radialGradient');
+                gradient.setAttributeNS(null, 'id', shadingId);
+                gradient.setAttributeNS(null, 'gradientUnits', 'userSpaceOnUse');
+                gradient.setAttributeNS(null, 'cx', circlePoint[0]);
+                gradient.setAttributeNS(null, 'cy', circlePoint[1]);
+                gradient.setAttributeNS(null, 'r', circleRadius);
+                gradient.setAttributeNS(null, 'fx', focalPoint[0]);
+                gradient.setAttributeNS(null, 'fy', focalPoint[1]);
+                gradient.setAttributeNS(null, 'fr', focalRadius);
+                break;
+
+              default:
+                throw new Error("Unknown RadialAxial type: ".concat(args[1]));
+            }
+
+            var _iteratorNormalCompletion5 = true;
+            var _didIteratorError5 = false;
+            var _iteratorError5 = undefined;
+
+            try {
+              for (var _iterator5 = colorStops[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {
+                var colorStop = _step5.value;
+                var stop = this.svgFactory.createElement('svg:stop');
+                stop.setAttributeNS(null, 'offset', colorStop[0]);
+                stop.setAttributeNS(null, 'stop-color', colorStop[1]);
+                gradient.appendChild(stop);
+              }
+            } catch (err) {
+              _didIteratorError5 = true;
+              _iteratorError5 = err;
+            } finally {
+              try {
+                if (!_iteratorNormalCompletion5 && _iterator5["return"] != null) {
+                  _iterator5["return"]();
+                }
+              } finally {
+                if (_didIteratorError5) {
+                  throw _iteratorError5;
+                }
+              }
+            }
+
+            this.defs.appendChild(gradient);
+            return "url(#".concat(shadingId, ")");
+
+          case 'Mesh':
+            (0, _util.warn)('Unimplemented pattern Mesh');
+            return null;
+
+          case 'Dummy':
+            return 'hotpink';
+
+          default:
+            throw new Error("Unknown IR type: ".concat(args[0]));
+        }
+      }
+    }, {
+      key: "setDash",
+      value: function setDash(dashArray, dashPhase) {
+        this.current.dashArray = dashArray;
+        this.current.dashPhase = dashPhase;
+      }
+    }, {
+      key: "constructPath",
+      value: function constructPath(ops, args) {
+        var current = this.current;
+        var x = current.x,
+            y = current.y;
+        var d = [];
+        var j = 0;
+        var _iteratorNormalCompletion6 = true;
+        var _didIteratorError6 = false;
+        var _iteratorError6 = undefined;
+
+        try {
+          for (var _iterator6 = ops[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {
+            var op = _step6.value;
+
+            switch (op | 0) {
+              case _util.OPS.rectangle:
+                x = args[j++];
+                y = args[j++];
+                var width = args[j++];
+                var height = args[j++];
+                var xw = x + width;
+                var yh = y + height;
+                d.push('M', pf(x), pf(y), 'L', pf(xw), pf(y), 'L', pf(xw), pf(yh), 'L', pf(x), pf(yh), 'Z');
+                break;
+
+              case _util.OPS.moveTo:
+                x = args[j++];
+                y = args[j++];
+                d.push('M', pf(x), pf(y));
+                break;
+
+              case _util.OPS.lineTo:
+                x = args[j++];
+                y = args[j++];
+                d.push('L', pf(x), pf(y));
+                break;
+
+              case _util.OPS.curveTo:
+                x = args[j + 4];
+                y = args[j + 5];
+                d.push('C', pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]), pf(x), pf(y));
+                j += 6;
+                break;
+
+              case _util.OPS.curveTo2:
+                x = args[j + 2];
+                y = args[j + 3];
+                d.push('C', pf(x), pf(y), pf(args[j]), pf(args[j + 1]), pf(args[j + 2]), pf(args[j + 3]));
+                j += 4;
+                break;
+
+              case _util.OPS.curveTo3:
+                x = args[j + 2];
+                y = args[j + 3];
+                d.push('C', pf(args[j]), pf(args[j + 1]), pf(x), pf(y), pf(x), pf(y));
+                j += 4;
+                break;
+
+              case _util.OPS.closePath:
+                d.push('Z');
+                break;
+            }
+          }
+        } catch (err) {
+          _didIteratorError6 = true;
+          _iteratorError6 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion6 && _iterator6["return"] != null) {
+              _iterator6["return"]();
+            }
+          } finally {
+            if (_didIteratorError6) {
+              throw _iteratorError6;
+            }
+          }
+        }
+
+        d = d.join(' ');
+
+        if (current.path && ops.length > 0 && ops[0] !== _util.OPS.rectangle && ops[0] !== _util.OPS.moveTo) {
+          d = current.path.getAttributeNS(null, 'd') + d;
+        } else {
+          current.path = this.svgFactory.createElement('svg:path');
+
+          this._ensureTransformGroup().appendChild(current.path);
+        }
+
+        current.path.setAttributeNS(null, 'd', d);
+        current.path.setAttributeNS(null, 'fill', 'none');
+        current.element = current.path;
+        current.setCurrentPoint(x, y);
+      }
+    }, {
+      key: "endPath",
+      value: function endPath() {
+        var current = this.current;
+        current.path = null;
+
+        if (!this.pendingClip) {
+          return;
+        }
+
+        if (!current.element) {
+          this.pendingClip = null;
+          return;
+        }
+
+        var clipId = "clippath".concat(clipCount++);
+        var clipPath = this.svgFactory.createElement('svg:clipPath');
+        clipPath.setAttributeNS(null, 'id', clipId);
+        clipPath.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+        var clipElement = current.element.cloneNode(true);
+
+        if (this.pendingClip === 'evenodd') {
+          clipElement.setAttributeNS(null, 'clip-rule', 'evenodd');
+        } else {
+          clipElement.setAttributeNS(null, 'clip-rule', 'nonzero');
+        }
+
+        this.pendingClip = null;
+        clipPath.appendChild(clipElement);
+        this.defs.appendChild(clipPath);
+
+        if (current.activeClipUrl) {
+          current.clipGroup = null;
+          this.extraStack.forEach(function (prev) {
+            prev.clipGroup = null;
+          });
+          clipPath.setAttributeNS(null, 'clip-path', current.activeClipUrl);
+        }
+
+        current.activeClipUrl = "url(#".concat(clipId, ")");
+        this.tgrp = null;
+      }
+    }, {
+      key: "clip",
+      value: function clip(type) {
+        this.pendingClip = type;
+      }
+    }, {
+      key: "closePath",
+      value: function closePath() {
+        var current = this.current;
+
+        if (current.path) {
+          var d = "".concat(current.path.getAttributeNS(null, 'd'), "Z");
+          current.path.setAttributeNS(null, 'd', d);
+        }
+      }
+    }, {
+      key: "setLeading",
+      value: function setLeading(leading) {
+        this.current.leading = -leading;
+      }
+    }, {
+      key: "setTextRise",
+      value: function setTextRise(textRise) {
+        this.current.textRise = textRise;
+      }
+    }, {
+      key: "setTextRenderingMode",
+      value: function setTextRenderingMode(textRenderingMode) {
+        this.current.textRenderingMode = textRenderingMode;
+      }
+    }, {
+      key: "setHScale",
+      value: function setHScale(scale) {
+        this.current.textHScale = scale / 100;
+      }
+    }, {
+      key: "setRenderingIntent",
+      value: function setRenderingIntent(intent) {}
+    }, {
+      key: "setFlatness",
+      value: function setFlatness(flatness) {}
+    }, {
+      key: "setGState",
+      value: function setGState(states) {
+        var _iteratorNormalCompletion7 = true;
+        var _didIteratorError7 = false;
+        var _iteratorError7 = undefined;
+
+        try {
+          for (var _iterator7 = states[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {
+            var _step7$value = _slicedToArray(_step7.value, 2),
+                key = _step7$value[0],
+                value = _step7$value[1];
+
+            switch (key) {
+              case 'LW':
+                this.setLineWidth(value);
+                break;
+
+              case 'LC':
+                this.setLineCap(value);
+                break;
+
+              case 'LJ':
+                this.setLineJoin(value);
+                break;
+
+              case 'ML':
+                this.setMiterLimit(value);
+                break;
+
+              case 'D':
+                this.setDash(value[0], value[1]);
+                break;
+
+              case 'RI':
+                this.setRenderingIntent(value);
+                break;
+
+              case 'FL':
+                this.setFlatness(value);
+                break;
+
+              case 'Font':
+                this.setFont(value);
+                break;
+
+              case 'CA':
+                this.setStrokeAlpha(value);
+                break;
+
+              case 'ca':
+                this.setFillAlpha(value);
+                break;
+
+              default:
+                (0, _util.warn)("Unimplemented graphic state operator ".concat(key));
+                break;
+            }
+          }
+        } catch (err) {
+          _didIteratorError7 = true;
+          _iteratorError7 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion7 && _iterator7["return"] != null) {
+              _iterator7["return"]();
+            }
+          } finally {
+            if (_didIteratorError7) {
+              throw _iteratorError7;
+            }
+          }
+        }
+      }
+    }, {
+      key: "fill",
+      value: function fill() {
+        var current = this.current;
+
+        if (current.element) {
+          current.element.setAttributeNS(null, 'fill', current.fillColor);
+          current.element.setAttributeNS(null, 'fill-opacity', current.fillAlpha);
+          this.endPath();
+        }
+      }
+    }, {
+      key: "stroke",
+      value: function stroke() {
+        var current = this.current;
+
+        if (current.element) {
+          this._setStrokeAttributes(current.element);
+
+          current.element.setAttributeNS(null, 'fill', 'none');
+          this.endPath();
+        }
+      }
+    }, {
+      key: "_setStrokeAttributes",
+      value: function _setStrokeAttributes(element) {
+        var lineWidthScale = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+        var current = this.current;
+        var dashArray = current.dashArray;
+
+        if (lineWidthScale !== 1 && dashArray.length > 0) {
+          dashArray = dashArray.map(function (value) {
+            return lineWidthScale * value;
+          });
+        }
+
+        element.setAttributeNS(null, 'stroke', current.strokeColor);
+        element.setAttributeNS(null, 'stroke-opacity', current.strokeAlpha);
+        element.setAttributeNS(null, 'stroke-miterlimit', pf(current.miterLimit));
+        element.setAttributeNS(null, 'stroke-linecap', current.lineCap);
+        element.setAttributeNS(null, 'stroke-linejoin', current.lineJoin);
+        element.setAttributeNS(null, 'stroke-width', pf(lineWidthScale * current.lineWidth) + 'px');
+        element.setAttributeNS(null, 'stroke-dasharray', dashArray.map(pf).join(' '));
+        element.setAttributeNS(null, 'stroke-dashoffset', pf(lineWidthScale * current.dashPhase) + 'px');
+      }
+    }, {
+      key: "eoFill",
+      value: function eoFill() {
+        if (this.current.element) {
+          this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
+        }
+
+        this.fill();
+      }
+    }, {
+      key: "fillStroke",
+      value: function fillStroke() {
+        this.stroke();
+        this.fill();
+      }
+    }, {
+      key: "eoFillStroke",
+      value: function eoFillStroke() {
+        if (this.current.element) {
+          this.current.element.setAttributeNS(null, 'fill-rule', 'evenodd');
+        }
+
+        this.fillStroke();
+      }
+    }, {
+      key: "closeStroke",
+      value: function closeStroke() {
+        this.closePath();
+        this.stroke();
+      }
+    }, {
+      key: "closeFillStroke",
+      value: function closeFillStroke() {
+        this.closePath();
+        this.fillStroke();
+      }
+    }, {
+      key: "closeEOFillStroke",
+      value: function closeEOFillStroke() {
+        this.closePath();
+        this.eoFillStroke();
+      }
+    }, {
+      key: "paintSolidColorImageMask",
+      value: function paintSolidColorImageMask() {
+        var rect = this.svgFactory.createElement('svg:rect');
+        rect.setAttributeNS(null, 'x', '0');
+        rect.setAttributeNS(null, 'y', '0');
+        rect.setAttributeNS(null, 'width', '1px');
+        rect.setAttributeNS(null, 'height', '1px');
+        rect.setAttributeNS(null, 'fill', this.current.fillColor);
+
+        this._ensureTransformGroup().appendChild(rect);
+      }
+    }, {
+      key: "paintJpegXObject",
+      value: function paintJpegXObject(objId, w, h) {
+        var imgObj = this.objs.get(objId);
+        var imgEl = this.svgFactory.createElement('svg:image');
+        imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgObj.src);
+        imgEl.setAttributeNS(null, 'width', pf(w));
+        imgEl.setAttributeNS(null, 'height', pf(h));
+        imgEl.setAttributeNS(null, 'x', '0');
+        imgEl.setAttributeNS(null, 'y', pf(-h));
+        imgEl.setAttributeNS(null, 'transform', "scale(".concat(pf(1 / w), " ").concat(pf(-1 / h), ")"));
+
+        this._ensureTransformGroup().appendChild(imgEl);
+      }
+    }, {
+      key: "paintImageXObject",
+      value: function paintImageXObject(objId) {
+        var imgData = this.objs.get(objId);
+
+        if (!imgData) {
+          (0, _util.warn)("Dependent image with object ID ".concat(objId, " is not ready yet"));
+          return;
+        }
+
+        this.paintInlineImageXObject(imgData);
+      }
+    }, {
+      key: "paintInlineImageXObject",
+      value: function paintInlineImageXObject(imgData, mask) {
+        var width = imgData.width;
+        var height = imgData.height;
+        var imgSrc = convertImgDataToPng(imgData, this.forceDataSchema, !!mask);
+        var cliprect = this.svgFactory.createElement('svg:rect');
+        cliprect.setAttributeNS(null, 'x', '0');
+        cliprect.setAttributeNS(null, 'y', '0');
+        cliprect.setAttributeNS(null, 'width', pf(width));
+        cliprect.setAttributeNS(null, 'height', pf(height));
+        this.current.element = cliprect;
+        this.clip('nonzero');
+        var imgEl = this.svgFactory.createElement('svg:image');
+        imgEl.setAttributeNS(XLINK_NS, 'xlink:href', imgSrc);
+        imgEl.setAttributeNS(null, 'x', '0');
+        imgEl.setAttributeNS(null, 'y', pf(-height));
+        imgEl.setAttributeNS(null, 'width', pf(width) + 'px');
+        imgEl.setAttributeNS(null, 'height', pf(height) + 'px');
+        imgEl.setAttributeNS(null, 'transform', "scale(".concat(pf(1 / width), " ").concat(pf(-1 / height), ")"));
+
+        if (mask) {
+          mask.appendChild(imgEl);
+        } else {
+          this._ensureTransformGroup().appendChild(imgEl);
+        }
+      }
+    }, {
+      key: "paintImageMaskXObject",
+      value: function paintImageMaskXObject(imgData) {
+        var current = this.current;
+        var width = imgData.width;
+        var height = imgData.height;
+        var fillColor = current.fillColor;
+        current.maskId = "mask".concat(maskCount++);
+        var mask = this.svgFactory.createElement('svg:mask');
+        mask.setAttributeNS(null, 'id', current.maskId);
+        var rect = this.svgFactory.createElement('svg:rect');
+        rect.setAttributeNS(null, 'x', '0');
+        rect.setAttributeNS(null, 'y', '0');
+        rect.setAttributeNS(null, 'width', pf(width));
+        rect.setAttributeNS(null, 'height', pf(height));
+        rect.setAttributeNS(null, 'fill', fillColor);
+        rect.setAttributeNS(null, 'mask', "url(#".concat(current.maskId, ")"));
+        this.defs.appendChild(mask);
+
+        this._ensureTransformGroup().appendChild(rect);
+
+        this.paintInlineImageXObject(imgData, mask);
+      }
+    }, {
+      key: "paintFormXObjectBegin",
+      value: function paintFormXObjectBegin(matrix, bbox) {
+        if (Array.isArray(matrix) && matrix.length === 6) {
+          this.transform(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]);
+        }
+
+        if (bbox) {
+          var width = bbox[2] - bbox[0];
+          var height = bbox[3] - bbox[1];
+          var cliprect = this.svgFactory.createElement('svg:rect');
+          cliprect.setAttributeNS(null, 'x', bbox[0]);
+          cliprect.setAttributeNS(null, 'y', bbox[1]);
+          cliprect.setAttributeNS(null, 'width', pf(width));
+          cliprect.setAttributeNS(null, 'height', pf(height));
+          this.current.element = cliprect;
+          this.clip('nonzero');
+          this.endPath();
+        }
+      }
+    }, {
+      key: "paintFormXObjectEnd",
+      value: function paintFormXObjectEnd() {}
+    }, {
+      key: "_initialize",
+      value: function _initialize(viewport) {
+        var svg = this.svgFactory.create(viewport.width, viewport.height);
+        var definitions = this.svgFactory.createElement('svg:defs');
+        svg.appendChild(definitions);
+        this.defs = definitions;
+        var rootGroup = this.svgFactory.createElement('svg:g');
+        rootGroup.setAttributeNS(null, 'transform', pm(viewport.transform));
+        svg.appendChild(rootGroup);
+        this.svg = rootGroup;
+        return svg;
+      }
+    }, {
+      key: "_ensureClipGroup",
+      value: function _ensureClipGroup() {
+        if (!this.current.clipGroup) {
+          var clipGroup = this.svgFactory.createElement('svg:g');
+          clipGroup.setAttributeNS(null, 'clip-path', this.current.activeClipUrl);
+          this.svg.appendChild(clipGroup);
+          this.current.clipGroup = clipGroup;
+        }
+
+        return this.current.clipGroup;
+      }
+    }, {
+      key: "_ensureTransformGroup",
+      value: function _ensureTransformGroup() {
+        if (!this.tgrp) {
+          this.tgrp = this.svgFactory.createElement('svg:g');
+          this.tgrp.setAttributeNS(null, 'transform', pm(this.transformMatrix));
+
+          if (this.current.activeClipUrl) {
+            this._ensureClipGroup().appendChild(this.tgrp);
+          } else {
+            this.svg.appendChild(this.tgrp);
+          }
+        }
+
+        return this.tgrp;
+      }
+    }]);
+
+    return SVGGraphics;
+  }();
+}
+
+/***/ }),
+/* 165 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFNodeStream = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+var _network_utils = __w_pdfjs_require__(166);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var fs = require('fs');
+
+var http = require('http');
+
+var https = require('https');
+
+var url = require('url');
+
+var fileUriRegex = /^file:\/\/\/[a-zA-Z]:\//;
+
+function parseUrl(sourceUrl) {
+  var parsedUrl = url.parse(sourceUrl);
+
+  if (parsedUrl.protocol === 'file:' || parsedUrl.host) {
+    return parsedUrl;
+  }
+
+  if (/^[a-z]:[/\\]/i.test(sourceUrl)) {
+    return url.parse("file:///".concat(sourceUrl));
+  }
+
+  if (!parsedUrl.host) {
+    parsedUrl.protocol = 'file:';
+  }
+
+  return parsedUrl;
+}
+
+var PDFNodeStream =
+/*#__PURE__*/
+function () {
+  function PDFNodeStream(source) {
+    _classCallCheck(this, PDFNodeStream);
+
+    this.source = source;
+    this.url = parseUrl(source.url);
+    this.isHttp = this.url.protocol === 'http:' || this.url.protocol === 'https:';
+    this.isFsUrl = this.url.protocol === 'file:';
+    this.httpHeaders = this.isHttp && source.httpHeaders || {};
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  _createClass(PDFNodeStream, [{
+    key: "getFullReader",
+    value: function getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      this._fullRequestReader = this.isFsUrl ? new PDFNodeStreamFsFullReader(this) : new PDFNodeStreamFullReader(this);
+      return this._fullRequestReader;
+    }
+  }, {
+    key: "getRangeReader",
+    value: function getRangeReader(start, end) {
+      if (end <= this._progressiveDataLength) {
+        return null;
+      }
+
+      var rangeReader = this.isFsUrl ? new PDFNodeStreamFsRangeReader(this, start, end) : new PDFNodeStreamRangeReader(this, start, end);
+
+      this._rangeRequestReaders.push(rangeReader);
+
+      return rangeReader;
+    }
+  }, {
+    key: "cancelAllRequests",
+    value: function cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+
+      var readers = this._rangeRequestReaders.slice(0);
+
+      readers.forEach(function (reader) {
+        reader.cancel(reason);
+      });
+    }
+  }, {
+    key: "_progressiveDataLength",
+    get: function get() {
+      return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
+    }
+  }]);
+
+  return PDFNodeStream;
+}();
+
+exports.PDFNodeStream = PDFNodeStream;
+
+var BaseFullReader =
+/*#__PURE__*/
+function () {
+  function BaseFullReader(stream) {
+    _classCallCheck(this, BaseFullReader);
+
+    this._url = stream.url;
+    this._done = false;
+    this._storedError = null;
+    this.onProgress = null;
+    var source = stream.source;
+    this._contentLength = source.length;
+    this._loaded = 0;
+    this._filename = null;
+    this._disableRange = source.disableRange || false;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    this._isStreamingSupported = !source.disableStream;
+    this._isRangeSupported = !source.disableRange;
+    this._readableStream = null;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    this._headersCapability = (0, _util.createPromiseCapability)();
+  }
+
+  _createClass(BaseFullReader, [{
+    key: "read",
+    value: function () {
+      var _read = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee() {
+        var chunk, buffer;
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                _context.next = 2;
+                return this._readCapability.promise;
+
+              case 2:
+                if (!this._done) {
+                  _context.next = 4;
+                  break;
+                }
+
+                return _context.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 4:
+                if (!this._storedError) {
+                  _context.next = 6;
+                  break;
+                }
+
+                throw this._storedError;
+
+              case 6:
+                chunk = this._readableStream.read();
+
+                if (!(chunk === null)) {
+                  _context.next = 10;
+                  break;
+                }
+
+                this._readCapability = (0, _util.createPromiseCapability)();
+                return _context.abrupt("return", this.read());
+
+              case 10:
+                this._loaded += chunk.length;
+
+                if (this.onProgress) {
+                  this.onProgress({
+                    loaded: this._loaded,
+                    total: this._contentLength
+                  });
+                }
+
+                buffer = new Uint8Array(chunk).buffer;
+                return _context.abrupt("return", {
+                  value: buffer,
+                  done: false
+                });
+
+              case 14:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function read() {
+        return _read.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      if (!this._readableStream) {
+        this._error(reason);
+
+        return;
+      }
+
+      this._readableStream.destroy(reason);
+    }
+  }, {
+    key: "_error",
+    value: function _error(reason) {
+      this._storedError = reason;
+
+      this._readCapability.resolve();
+    }
+  }, {
+    key: "_setReadableStream",
+    value: function _setReadableStream(readableStream) {
+      var _this = this;
+
+      this._readableStream = readableStream;
+      readableStream.on('readable', function () {
+        _this._readCapability.resolve();
+      });
+      readableStream.on('end', function () {
+        readableStream.destroy();
+        _this._done = true;
+
+        _this._readCapability.resolve();
+      });
+      readableStream.on('error', function (reason) {
+        _this._error(reason);
+      });
+
+      if (!this._isStreamingSupported && this._isRangeSupported) {
+        this._error(new _util.AbortException('streaming is disabled'));
+      }
+
+      if (this._storedError) {
+        this._readableStream.destroy(this._storedError);
+      }
+    }
+  }, {
+    key: "headersReady",
+    get: function get() {
+      return this._headersCapability.promise;
+    }
+  }, {
+    key: "filename",
+    get: function get() {
+      return this._filename;
+    }
+  }, {
+    key: "contentLength",
+    get: function get() {
+      return this._contentLength;
+    }
+  }, {
+    key: "isRangeSupported",
+    get: function get() {
+      return this._isRangeSupported;
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }]);
+
+  return BaseFullReader;
+}();
+
+var BaseRangeReader =
+/*#__PURE__*/
+function () {
+  function BaseRangeReader(stream) {
+    _classCallCheck(this, BaseRangeReader);
+
+    this._url = stream.url;
+    this._done = false;
+    this._storedError = null;
+    this.onProgress = null;
+    this._loaded = 0;
+    this._readableStream = null;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    var source = stream.source;
+    this._isStreamingSupported = !source.disableStream;
+  }
+
+  _createClass(BaseRangeReader, [{
+    key: "read",
+    value: function () {
+      var _read2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2() {
+        var chunk, buffer;
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                _context2.next = 2;
+                return this._readCapability.promise;
+
+              case 2:
+                if (!this._done) {
+                  _context2.next = 4;
+                  break;
+                }
+
+                return _context2.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 4:
+                if (!this._storedError) {
+                  _context2.next = 6;
+                  break;
+                }
+
+                throw this._storedError;
+
+              case 6:
+                chunk = this._readableStream.read();
+
+                if (!(chunk === null)) {
+                  _context2.next = 10;
+                  break;
+                }
+
+                this._readCapability = (0, _util.createPromiseCapability)();
+                return _context2.abrupt("return", this.read());
+
+              case 10:
+                this._loaded += chunk.length;
+
+                if (this.onProgress) {
+                  this.onProgress({
+                    loaded: this._loaded
+                  });
+                }
+
+                buffer = new Uint8Array(chunk).buffer;
+                return _context2.abrupt("return", {
+                  value: buffer,
+                  done: false
+                });
+
+              case 14:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function read() {
+        return _read2.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      if (!this._readableStream) {
+        this._error(reason);
+
+        return;
+      }
+
+      this._readableStream.destroy(reason);
+    }
+  }, {
+    key: "_error",
+    value: function _error(reason) {
+      this._storedError = reason;
+
+      this._readCapability.resolve();
+    }
+  }, {
+    key: "_setReadableStream",
+    value: function _setReadableStream(readableStream) {
+      var _this2 = this;
+
+      this._readableStream = readableStream;
+      readableStream.on('readable', function () {
+        _this2._readCapability.resolve();
+      });
+      readableStream.on('end', function () {
+        readableStream.destroy();
+        _this2._done = true;
+
+        _this2._readCapability.resolve();
+      });
+      readableStream.on('error', function (reason) {
+        _this2._error(reason);
+      });
+
+      if (this._storedError) {
+        this._readableStream.destroy(this._storedError);
+      }
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }]);
+
+  return BaseRangeReader;
+}();
+
+function createRequestOptions(url, headers) {
+  return {
+    protocol: url.protocol,
+    auth: url.auth,
+    host: url.hostname,
+    port: url.port,
+    path: url.path,
+    method: 'GET',
+    headers: headers
+  };
+}
+
+var PDFNodeStreamFullReader =
+/*#__PURE__*/
+function (_BaseFullReader) {
+  _inherits(PDFNodeStreamFullReader, _BaseFullReader);
+
+  function PDFNodeStreamFullReader(stream) {
+    var _this3;
+
+    _classCallCheck(this, PDFNodeStreamFullReader);
+
+    _this3 = _possibleConstructorReturn(this, _getPrototypeOf(PDFNodeStreamFullReader).call(this, stream));
+
+    var handleResponse = function handleResponse(response) {
+      if (response.statusCode === 404) {
+        var error = new _util.MissingPDFException("Missing PDF \"".concat(_this3._url, "\"."));
+        _this3._storedError = error;
+
+        _this3._headersCapability.reject(error);
+
+        return;
+      }
+
+      _this3._headersCapability.resolve();
+
+      _this3._setReadableStream(response);
+
+      var getResponseHeader = function getResponseHeader(name) {
+        return _this3._readableStream.headers[name.toLowerCase()];
+      };
+
+      var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
+        getResponseHeader: getResponseHeader,
+        isHttp: stream.isHttp,
+        rangeChunkSize: _this3._rangeChunkSize,
+        disableRange: _this3._disableRange
+      }),
+          allowRangeRequests = _validateRangeRequest.allowRangeRequests,
+          suggestedLength = _validateRangeRequest.suggestedLength;
+
+      _this3._isRangeSupported = allowRangeRequests;
+      _this3._contentLength = suggestedLength || _this3._contentLength;
+      _this3._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+    };
+
+    _this3._request = null;
+
+    if (_this3._url.protocol === 'http:') {
+      _this3._request = http.request(createRequestOptions(_this3._url, stream.httpHeaders), handleResponse);
+    } else {
+      _this3._request = https.request(createRequestOptions(_this3._url, stream.httpHeaders), handleResponse);
+    }
+
+    _this3._request.on('error', function (reason) {
+      _this3._storedError = reason;
+
+      _this3._headersCapability.reject(reason);
+    });
+
+    _this3._request.end();
+
+    return _this3;
+  }
+
+  return PDFNodeStreamFullReader;
+}(BaseFullReader);
+
+var PDFNodeStreamRangeReader =
+/*#__PURE__*/
+function (_BaseRangeReader) {
+  _inherits(PDFNodeStreamRangeReader, _BaseRangeReader);
+
+  function PDFNodeStreamRangeReader(stream, start, end) {
+    var _this4;
+
+    _classCallCheck(this, PDFNodeStreamRangeReader);
+
+    _this4 = _possibleConstructorReturn(this, _getPrototypeOf(PDFNodeStreamRangeReader).call(this, stream));
+    _this4._httpHeaders = {};
+
+    for (var property in stream.httpHeaders) {
+      var value = stream.httpHeaders[property];
+
+      if (typeof value === 'undefined') {
+        continue;
+      }
+
+      _this4._httpHeaders[property] = value;
+    }
+
+    _this4._httpHeaders['Range'] = "bytes=".concat(start, "-").concat(end - 1);
+
+    var handleResponse = function handleResponse(response) {
+      if (response.statusCode === 404) {
+        var error = new _util.MissingPDFException("Missing PDF \"".concat(_this4._url, "\"."));
+        _this4._storedError = error;
+        return;
+      }
+
+      _this4._setReadableStream(response);
+    };
+
+    _this4._request = null;
+
+    if (_this4._url.protocol === 'http:') {
+      _this4._request = http.request(createRequestOptions(_this4._url, _this4._httpHeaders), handleResponse);
+    } else {
+      _this4._request = https.request(createRequestOptions(_this4._url, _this4._httpHeaders), handleResponse);
+    }
+
+    _this4._request.on('error', function (reason) {
+      _this4._storedError = reason;
+    });
+
+    _this4._request.end();
+
+    return _this4;
+  }
+
+  return PDFNodeStreamRangeReader;
+}(BaseRangeReader);
+
+var PDFNodeStreamFsFullReader =
+/*#__PURE__*/
+function (_BaseFullReader2) {
+  _inherits(PDFNodeStreamFsFullReader, _BaseFullReader2);
+
+  function PDFNodeStreamFsFullReader(stream) {
+    var _this5;
+
+    _classCallCheck(this, PDFNodeStreamFsFullReader);
+
+    _this5 = _possibleConstructorReturn(this, _getPrototypeOf(PDFNodeStreamFsFullReader).call(this, stream));
+    var path = decodeURIComponent(_this5._url.path);
+
+    if (fileUriRegex.test(_this5._url.href)) {
+      path = path.replace(/^\//, '');
+    }
+
+    fs.lstat(path, function (error, stat) {
+      if (error) {
+        if (error.code === 'ENOENT') {
+          error = new _util.MissingPDFException("Missing PDF \"".concat(path, "\"."));
+        }
+
+        _this5._storedError = error;
+
+        _this5._headersCapability.reject(error);
+
+        return;
+      }
+
+      _this5._contentLength = stat.size;
+
+      _this5._setReadableStream(fs.createReadStream(path));
+
+      _this5._headersCapability.resolve();
+    });
+    return _this5;
+  }
+
+  return PDFNodeStreamFsFullReader;
+}(BaseFullReader);
+
+var PDFNodeStreamFsRangeReader =
+/*#__PURE__*/
+function (_BaseRangeReader2) {
+  _inherits(PDFNodeStreamFsRangeReader, _BaseRangeReader2);
+
+  function PDFNodeStreamFsRangeReader(stream, start, end) {
+    var _this6;
+
+    _classCallCheck(this, PDFNodeStreamFsRangeReader);
+
+    _this6 = _possibleConstructorReturn(this, _getPrototypeOf(PDFNodeStreamFsRangeReader).call(this, stream));
+    var path = decodeURIComponent(_this6._url.path);
+
+    if (fileUriRegex.test(_this6._url.href)) {
+      path = path.replace(/^\//, '');
+    }
+
+    _this6._setReadableStream(fs.createReadStream(path, {
+      start: start,
+      end: end - 1
+    }));
+
+    return _this6;
+  }
+
+  return PDFNodeStreamFsRangeReader;
+}(BaseRangeReader);
+
+/***/ }),
+/* 166 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.createResponseStatusError = createResponseStatusError;
+exports.extractFilenameFromHeader = extractFilenameFromHeader;
+exports.validateRangeRequestCapabilities = validateRangeRequestCapabilities;
+exports.validateResponseStatus = validateResponseStatus;
+
+var _util = __w_pdfjs_require__(1);
+
+var _content_disposition = __w_pdfjs_require__(167);
+
+function validateRangeRequestCapabilities(_ref) {
+  var getResponseHeader = _ref.getResponseHeader,
+      isHttp = _ref.isHttp,
+      rangeChunkSize = _ref.rangeChunkSize,
+      disableRange = _ref.disableRange;
+  (0, _util.assert)(rangeChunkSize > 0, 'Range chunk size must be larger than zero');
+  var returnValues = {
+    allowRangeRequests: false,
+    suggestedLength: undefined
+  };
+  var length = parseInt(getResponseHeader('Content-Length'), 10);
+
+  if (!Number.isInteger(length)) {
+    return returnValues;
+  }
+
+  returnValues.suggestedLength = length;
+
+  if (length <= 2 * rangeChunkSize) {
+    return returnValues;
+  }
+
+  if (disableRange || !isHttp) {
+    return returnValues;
+  }
+
+  if (getResponseHeader('Accept-Ranges') !== 'bytes') {
+    return returnValues;
+  }
+
+  var contentEncoding = getResponseHeader('Content-Encoding') || 'identity';
+
+  if (contentEncoding !== 'identity') {
+    return returnValues;
+  }
+
+  returnValues.allowRangeRequests = true;
+  return returnValues;
+}
+
+function extractFilenameFromHeader(getResponseHeader) {
+  var contentDisposition = getResponseHeader('Content-Disposition');
+
+  if (contentDisposition) {
+    var filename = (0, _content_disposition.getFilenameFromContentDispositionHeader)(contentDisposition);
+
+    if (/\.pdf$/i.test(filename)) {
+      return filename;
+    }
+  }
+
+  return null;
+}
+
+function createResponseStatusError(status, url) {
+  if (status === 404 || status === 0 && /^file:/.test(url)) {
+    return new _util.MissingPDFException('Missing PDF "' + url + '".');
+  }
+
+  return new _util.UnexpectedResponseException('Unexpected server response (' + status + ') while retrieving PDF "' + url + '".', status);
+}
+
+function validateResponseStatus(status) {
+  return status === 200 || status === 206;
+}
+
+/***/ }),
+/* 167 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getFilenameFromContentDispositionHeader = getFilenameFromContentDispositionHeader;
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function getFilenameFromContentDispositionHeader(contentDisposition) {
+  var needsEncodingFixup = true;
+  var tmp = toParamRegExp('filename\\*', 'i').exec(contentDisposition);
+
+  if (tmp) {
+    tmp = tmp[1];
+    var filename = rfc2616unquote(tmp);
+    filename = unescape(filename);
+    filename = rfc5987decode(filename);
+    filename = rfc2047decode(filename);
+    return fixupEncoding(filename);
+  }
+
+  tmp = rfc2231getparam(contentDisposition);
+
+  if (tmp) {
+    var _filename = rfc2047decode(tmp);
+
+    return fixupEncoding(_filename);
+  }
+
+  tmp = toParamRegExp('filename', 'i').exec(contentDisposition);
+
+  if (tmp) {
+    tmp = tmp[1];
+
+    var _filename2 = rfc2616unquote(tmp);
+
+    _filename2 = rfc2047decode(_filename2);
+    return fixupEncoding(_filename2);
+  }
+
+  function toParamRegExp(attributePattern, flags) {
+    return new RegExp('(?:^|;)\\s*' + attributePattern + '\\s*=\\s*' + '(' + '[^";\\s][^;\\s]*' + '|' + '"(?:[^"\\\\]|\\\\"?)+"?' + ')', flags);
+  }
+
+  function textdecode(encoding, value) {
+    if (encoding) {
+      if (!/^[\x00-\xFF]+$/.test(value)) {
+        return value;
+      }
+
+      try {
+        var decoder = new TextDecoder(encoding, {
+          fatal: true
+        });
+        var bytes = Array.from(value, function (ch) {
+          return ch.charCodeAt(0) & 0xFF;
+        });
+        value = decoder.decode(new Uint8Array(bytes));
+        needsEncodingFixup = false;
+      } catch (e) {
+        if (/^utf-?8$/i.test(encoding)) {
+          try {
+            value = decodeURIComponent(escape(value));
+            needsEncodingFixup = false;
+          } catch (err) {}
+        }
+      }
+    }
+
+    return value;
+  }
+
+  function fixupEncoding(value) {
+    if (needsEncodingFixup && /[\x80-\xff]/.test(value)) {
+      value = textdecode('utf-8', value);
+
+      if (needsEncodingFixup) {
+        value = textdecode('iso-8859-1', value);
+      }
+    }
+
+    return value;
+  }
+
+  function rfc2231getparam(contentDisposition) {
+    var matches = [],
+        match;
+    var iter = toParamRegExp('filename\\*((?!0\\d)\\d+)(\\*?)', 'ig');
+
+    while ((match = iter.exec(contentDisposition)) !== null) {
+      var _match = match,
+          _match2 = _slicedToArray(_match, 4),
+          n = _match2[1],
+          quot = _match2[2],
+          part = _match2[3];
+
+      n = parseInt(n, 10);
+
+      if (n in matches) {
+        if (n === 0) {
+          break;
+        }
+
+        continue;
+      }
+
+      matches[n] = [quot, part];
+    }
+
+    var parts = [];
+
+    for (var n = 0; n < matches.length; ++n) {
+      if (!(n in matches)) {
+        break;
+      }
+
+      var _matches$n = _slicedToArray(matches[n], 2),
+          quot = _matches$n[0],
+          part = _matches$n[1];
+
+      part = rfc2616unquote(part);
+
+      if (quot) {
+        part = unescape(part);
+
+        if (n === 0) {
+          part = rfc5987decode(part);
+        }
+      }
+
+      parts.push(part);
+    }
+
+    return parts.join('');
+  }
+
+  function rfc2616unquote(value) {
+    if (value.startsWith('"')) {
+      var parts = value.slice(1).split('\\"');
+
+      for (var i = 0; i < parts.length; ++i) {
+        var quotindex = parts[i].indexOf('"');
+
+        if (quotindex !== -1) {
+          parts[i] = parts[i].slice(0, quotindex);
+          parts.length = i + 1;
+        }
+
+        parts[i] = parts[i].replace(/\\(.)/g, '$1');
+      }
+
+      value = parts.join('"');
+    }
+
+    return value;
+  }
+
+  function rfc5987decode(extvalue) {
+    var encodingend = extvalue.indexOf('\'');
+
+    if (encodingend === -1) {
+      return extvalue;
+    }
+
+    var encoding = extvalue.slice(0, encodingend);
+    var langvalue = extvalue.slice(encodingend + 1);
+    var value = langvalue.replace(/^[^']*'/, '');
+    return textdecode(encoding, value);
+  }
+
+  function rfc2047decode(value) {
+    if (!value.startsWith('=?') || /[\x00-\x19\x80-\xff]/.test(value)) {
+      return value;
+    }
+
+    return value.replace(/=\?([\w-]*)\?([QqBb])\?((?:[^?]|\?(?!=))*)\?=/g, function (_, charset, encoding, text) {
+      if (encoding === 'q' || encoding === 'Q') {
+        text = text.replace(/_/g, ' ');
+        text = text.replace(/=([0-9a-fA-F]{2})/g, function (_, hex) {
+          return String.fromCharCode(parseInt(hex, 16));
+        });
+        return textdecode(charset, text);
+      }
+
+      try {
+        text = atob(text);
+      } catch (e) {}
+
+      return textdecode(charset, text);
+    });
+  }
+
+  return '';
+}
+
+/***/ }),
+/* 168 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFNetworkStream = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+var _network_utils = __w_pdfjs_require__(166);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+;
+var OK_RESPONSE = 200;
+var PARTIAL_CONTENT_RESPONSE = 206;
+
+function getArrayBuffer(xhr) {
+  var data = xhr.response;
+
+  if (typeof data !== 'string') {
+    return data;
+  }
+
+  var array = (0, _util.stringToBytes)(data);
+  return array.buffer;
+}
+
+var NetworkManager =
+/*#__PURE__*/
+function () {
+  function NetworkManager(url, args) {
+    _classCallCheck(this, NetworkManager);
+
+    this.url = url;
+    args = args || {};
+    this.isHttp = /^https?:/i.test(url);
+    this.httpHeaders = this.isHttp && args.httpHeaders || {};
+    this.withCredentials = args.withCredentials || false;
+
+    this.getXhr = args.getXhr || function NetworkManager_getXhr() {
+      return new XMLHttpRequest();
+    };
+
+    this.currXhrId = 0;
+    this.pendingRequests = Object.create(null);
+  }
+
+  _createClass(NetworkManager, [{
+    key: "requestRange",
+    value: function requestRange(begin, end, listeners) {
+      var args = {
+        begin: begin,
+        end: end
+      };
+
+      for (var prop in listeners) {
+        args[prop] = listeners[prop];
+      }
+
+      return this.request(args);
+    }
+  }, {
+    key: "requestFull",
+    value: function requestFull(listeners) {
+      return this.request(listeners);
+    }
+  }, {
+    key: "request",
+    value: function request(args) {
+      var xhr = this.getXhr();
+      var xhrId = this.currXhrId++;
+      var pendingRequest = this.pendingRequests[xhrId] = {
+        xhr: xhr
+      };
+      xhr.open('GET', this.url);
+      xhr.withCredentials = this.withCredentials;
+
+      for (var property in this.httpHeaders) {
+        var value = this.httpHeaders[property];
+
+        if (typeof value === 'undefined') {
+          continue;
+        }
+
+        xhr.setRequestHeader(property, value);
+      }
+
+      if (this.isHttp && 'begin' in args && 'end' in args) {
+        xhr.setRequestHeader('Range', "bytes=".concat(args.begin, "-").concat(args.end - 1));
+        pendingRequest.expectedStatus = PARTIAL_CONTENT_RESPONSE;
+      } else {
+        pendingRequest.expectedStatus = OK_RESPONSE;
+      }
+
+      xhr.responseType = 'arraybuffer';
+
+      if (args.onError) {
+        xhr.onerror = function (evt) {
+          args.onError(xhr.status);
+        };
+      }
+
+      xhr.onreadystatechange = this.onStateChange.bind(this, xhrId);
+      xhr.onprogress = this.onProgress.bind(this, xhrId);
+      pendingRequest.onHeadersReceived = args.onHeadersReceived;
+      pendingRequest.onDone = args.onDone;
+      pendingRequest.onError = args.onError;
+      pendingRequest.onProgress = args.onProgress;
+      xhr.send(null);
+      return xhrId;
+    }
+  }, {
+    key: "onProgress",
+    value: function onProgress(xhrId, evt) {
+      var pendingRequest = this.pendingRequests[xhrId];
+
+      if (!pendingRequest) {
+        return;
+      }
+
+      if (pendingRequest.onProgress) {
+        pendingRequest.onProgress(evt);
+      }
+    }
+  }, {
+    key: "onStateChange",
+    value: function onStateChange(xhrId, evt) {
+      var pendingRequest = this.pendingRequests[xhrId];
+
+      if (!pendingRequest) {
+        return;
+      }
+
+      var xhr = pendingRequest.xhr;
+
+      if (xhr.readyState >= 2 && pendingRequest.onHeadersReceived) {
+        pendingRequest.onHeadersReceived();
+        delete pendingRequest.onHeadersReceived;
+      }
+
+      if (xhr.readyState !== 4) {
+        return;
+      }
+
+      if (!(xhrId in this.pendingRequests)) {
+        return;
+      }
+
+      delete this.pendingRequests[xhrId];
+
+      if (xhr.status === 0 && this.isHttp) {
+        if (pendingRequest.onError) {
+          pendingRequest.onError(xhr.status);
+        }
+
+        return;
+      }
+
+      var xhrStatus = xhr.status || OK_RESPONSE;
+      var ok_response_on_range_request = xhrStatus === OK_RESPONSE && pendingRequest.expectedStatus === PARTIAL_CONTENT_RESPONSE;
+
+      if (!ok_response_on_range_request && xhrStatus !== pendingRequest.expectedStatus) {
+        if (pendingRequest.onError) {
+          pendingRequest.onError(xhr.status);
+        }
+
+        return;
+      }
+
+      var chunk = getArrayBuffer(xhr);
+
+      if (xhrStatus === PARTIAL_CONTENT_RESPONSE) {
+        var rangeHeader = xhr.getResponseHeader('Content-Range');
+        var matches = /bytes (\d+)-(\d+)\/(\d+)/.exec(rangeHeader);
+        pendingRequest.onDone({
+          begin: parseInt(matches[1], 10),
+          chunk: chunk
+        });
+      } else if (chunk) {
+        pendingRequest.onDone({
+          begin: 0,
+          chunk: chunk
+        });
+      } else if (pendingRequest.onError) {
+        pendingRequest.onError(xhr.status);
+      }
+    }
+  }, {
+    key: "hasPendingRequests",
+    value: function hasPendingRequests() {
+      for (var xhrId in this.pendingRequests) {
+        return true;
+      }
+
+      return false;
+    }
+  }, {
+    key: "getRequestXhr",
+    value: function getRequestXhr(xhrId) {
+      return this.pendingRequests[xhrId].xhr;
+    }
+  }, {
+    key: "isPendingRequest",
+    value: function isPendingRequest(xhrId) {
+      return xhrId in this.pendingRequests;
+    }
+  }, {
+    key: "abortAllRequests",
+    value: function abortAllRequests() {
+      for (var xhrId in this.pendingRequests) {
+        this.abortRequest(xhrId | 0);
+      }
+    }
+  }, {
+    key: "abortRequest",
+    value: function abortRequest(xhrId) {
+      var xhr = this.pendingRequests[xhrId].xhr;
+      delete this.pendingRequests[xhrId];
+      xhr.abort();
+    }
+  }]);
+
+  return NetworkManager;
+}();
+
+var PDFNetworkStream =
+/*#__PURE__*/
+function () {
+  function PDFNetworkStream(source) {
+    _classCallCheck(this, PDFNetworkStream);
+
+    this._source = source;
+    this._manager = new NetworkManager(source.url, {
+      httpHeaders: source.httpHeaders,
+      withCredentials: source.withCredentials
+    });
+    this._rangeChunkSize = source.rangeChunkSize;
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  _createClass(PDFNetworkStream, [{
+    key: "_onRangeRequestReaderClosed",
+    value: function _onRangeRequestReaderClosed(reader) {
+      var i = this._rangeRequestReaders.indexOf(reader);
+
+      if (i >= 0) {
+        this._rangeRequestReaders.splice(i, 1);
+      }
+    }
+  }, {
+    key: "getFullReader",
+    value: function getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      this._fullRequestReader = new PDFNetworkStreamFullRequestReader(this._manager, this._source);
+      return this._fullRequestReader;
+    }
+  }, {
+    key: "getRangeReader",
+    value: function getRangeReader(begin, end) {
+      var reader = new PDFNetworkStreamRangeRequestReader(this._manager, begin, end);
+      reader.onClosed = this._onRangeRequestReaderClosed.bind(this);
+
+      this._rangeRequestReaders.push(reader);
+
+      return reader;
+    }
+  }, {
+    key: "cancelAllRequests",
+    value: function cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+
+      var readers = this._rangeRequestReaders.slice(0);
+
+      readers.forEach(function (reader) {
+        reader.cancel(reason);
+      });
+    }
+  }]);
+
+  return PDFNetworkStream;
+}();
+
+exports.PDFNetworkStream = PDFNetworkStream;
+
+var PDFNetworkStreamFullRequestReader =
+/*#__PURE__*/
+function () {
+  function PDFNetworkStreamFullRequestReader(manager, source) {
+    _classCallCheck(this, PDFNetworkStreamFullRequestReader);
+
+    this._manager = manager;
+    var args = {
+      onHeadersReceived: this._onHeadersReceived.bind(this),
+      onDone: this._onDone.bind(this),
+      onError: this._onError.bind(this),
+      onProgress: this._onProgress.bind(this)
+    };
+    this._url = source.url;
+    this._fullRequestId = manager.requestFull(args);
+    this._headersReceivedCapability = (0, _util.createPromiseCapability)();
+    this._disableRange = source.disableRange || false;
+    this._contentLength = source.length;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    this._isStreamingSupported = false;
+    this._isRangeSupported = false;
+    this._cachedChunks = [];
+    this._requests = [];
+    this._done = false;
+    this._storedError = undefined;
+    this._filename = null;
+    this.onProgress = null;
+  }
+
+  _createClass(PDFNetworkStreamFullRequestReader, [{
+    key: "_onHeadersReceived",
+    value: function _onHeadersReceived() {
+      var fullRequestXhrId = this._fullRequestId;
+
+      var fullRequestXhr = this._manager.getRequestXhr(fullRequestXhrId);
+
+      var getResponseHeader = function getResponseHeader(name) {
+        return fullRequestXhr.getResponseHeader(name);
+      };
+
+      var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
+        getResponseHeader: getResponseHeader,
+        isHttp: this._manager.isHttp,
+        rangeChunkSize: this._rangeChunkSize,
+        disableRange: this._disableRange
+      }),
+          allowRangeRequests = _validateRangeRequest.allowRangeRequests,
+          suggestedLength = _validateRangeRequest.suggestedLength;
+
+      if (allowRangeRequests) {
+        this._isRangeSupported = true;
+      }
+
+      this._contentLength = suggestedLength || this._contentLength;
+      this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+
+      if (this._isRangeSupported) {
+        this._manager.abortRequest(fullRequestXhrId);
+      }
+
+      this._headersReceivedCapability.resolve();
+    }
+  }, {
+    key: "_onDone",
+    value: function _onDone(args) {
+      if (args) {
+        if (this._requests.length > 0) {
+          var requestCapability = this._requests.shift();
+
+          requestCapability.resolve({
+            value: args.chunk,
+            done: false
+          });
+        } else {
+          this._cachedChunks.push(args.chunk);
+        }
+      }
+
+      this._done = true;
+
+      if (this._cachedChunks.length > 0) {
+        return;
+      }
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+    }
+  }, {
+    key: "_onError",
+    value: function _onError(status) {
+      var url = this._url;
+      var exception = (0, _network_utils.createResponseStatusError)(status, url);
+      this._storedError = exception;
+
+      this._headersReceivedCapability.reject(exception);
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.reject(exception);
+      });
+
+      this._requests = [];
+      this._cachedChunks = [];
+    }
+  }, {
+    key: "_onProgress",
+    value: function _onProgress(data) {
+      if (this.onProgress) {
+        this.onProgress({
+          loaded: data.loaded,
+          total: data.lengthComputable ? data.total : this._contentLength
+        });
+      }
+    }
+  }, {
+    key: "read",
+    value: function () {
+      var _read = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee() {
+        var chunk, requestCapability;
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                if (!this._storedError) {
+                  _context.next = 2;
+                  break;
+                }
+
+                throw this._storedError;
+
+              case 2:
+                if (!(this._cachedChunks.length > 0)) {
+                  _context.next = 5;
+                  break;
+                }
+
+                chunk = this._cachedChunks.shift();
+                return _context.abrupt("return", {
+                  value: chunk,
+                  done: false
+                });
+
+              case 5:
+                if (!this._done) {
+                  _context.next = 7;
+                  break;
+                }
+
+                return _context.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 7:
+                requestCapability = (0, _util.createPromiseCapability)();
+
+                this._requests.push(requestCapability);
+
+                return _context.abrupt("return", requestCapability.promise);
+
+              case 10:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function read() {
+        return _read.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._done = true;
+
+      this._headersReceivedCapability.reject(reason);
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+
+      if (this._manager.isPendingRequest(this._fullRequestId)) {
+        this._manager.abortRequest(this._fullRequestId);
+      }
+
+      this._fullRequestReader = null;
+    }
+  }, {
+    key: "filename",
+    get: function get() {
+      return this._filename;
+    }
+  }, {
+    key: "isRangeSupported",
+    get: function get() {
+      return this._isRangeSupported;
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }, {
+    key: "contentLength",
+    get: function get() {
+      return this._contentLength;
+    }
+  }, {
+    key: "headersReady",
+    get: function get() {
+      return this._headersReceivedCapability.promise;
+    }
+  }]);
+
+  return PDFNetworkStreamFullRequestReader;
+}();
+
+var PDFNetworkStreamRangeRequestReader =
+/*#__PURE__*/
+function () {
+  function PDFNetworkStreamRangeRequestReader(manager, begin, end) {
+    _classCallCheck(this, PDFNetworkStreamRangeRequestReader);
+
+    this._manager = manager;
+    var args = {
+      onDone: this._onDone.bind(this),
+      onProgress: this._onProgress.bind(this)
+    };
+    this._requestId = manager.requestRange(begin, end, args);
+    this._requests = [];
+    this._queuedChunk = null;
+    this._done = false;
+    this.onProgress = null;
+    this.onClosed = null;
+  }
+
+  _createClass(PDFNetworkStreamRangeRequestReader, [{
+    key: "_close",
+    value: function _close() {
+      if (this.onClosed) {
+        this.onClosed(this);
+      }
+    }
+  }, {
+    key: "_onDone",
+    value: function _onDone(data) {
+      var chunk = data.chunk;
+
+      if (this._requests.length > 0) {
+        var requestCapability = this._requests.shift();
+
+        requestCapability.resolve({
+          value: chunk,
+          done: false
+        });
+      } else {
+        this._queuedChunk = chunk;
+      }
+
+      this._done = true;
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+
+      this._close();
+    }
+  }, {
+    key: "_onProgress",
+    value: function _onProgress(evt) {
+      if (!this.isStreamingSupported && this.onProgress) {
+        this.onProgress({
+          loaded: evt.loaded
+        });
+      }
+    }
+  }, {
+    key: "read",
+    value: function () {
+      var _read2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2() {
+        var chunk, requestCapability;
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                if (!(this._queuedChunk !== null)) {
+                  _context2.next = 4;
+                  break;
+                }
+
+                chunk = this._queuedChunk;
+                this._queuedChunk = null;
+                return _context2.abrupt("return", {
+                  value: chunk,
+                  done: false
+                });
+
+              case 4:
+                if (!this._done) {
+                  _context2.next = 6;
+                  break;
+                }
+
+                return _context2.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 6:
+                requestCapability = (0, _util.createPromiseCapability)();
+
+                this._requests.push(requestCapability);
+
+                return _context2.abrupt("return", requestCapability.promise);
+
+              case 9:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function read() {
+        return _read2.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._done = true;
+
+      this._requests.forEach(function (requestCapability) {
+        requestCapability.resolve({
+          value: undefined,
+          done: true
+        });
+      });
+
+      this._requests = [];
+
+      if (this._manager.isPendingRequest(this._requestId)) {
+        this._manager.abortRequest(this._requestId);
+      }
+
+      this._close();
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return false;
+    }
+  }]);
+
+  return PDFNetworkStreamRangeRequestReader;
+}();
+
+/***/ }),
+/* 169 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFFetchStream = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(148));
+
+var _util = __w_pdfjs_require__(1);
+
+var _network_utils = __w_pdfjs_require__(166);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function createFetchOptions(headers, withCredentials, abortController) {
+  return {
+    method: 'GET',
+    headers: headers,
+    signal: abortController && abortController.signal,
+    mode: 'cors',
+    credentials: withCredentials ? 'include' : 'same-origin',
+    redirect: 'follow'
+  };
+}
+
+var PDFFetchStream =
+/*#__PURE__*/
+function () {
+  function PDFFetchStream(source) {
+    _classCallCheck(this, PDFFetchStream);
+
+    this.source = source;
+    this.isHttp = /^https?:/i.test(source.url);
+    this.httpHeaders = this.isHttp && source.httpHeaders || {};
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  _createClass(PDFFetchStream, [{
+    key: "getFullReader",
+    value: function getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      this._fullRequestReader = new PDFFetchStreamReader(this);
+      return this._fullRequestReader;
+    }
+  }, {
+    key: "getRangeReader",
+    value: function getRangeReader(begin, end) {
+      if (end <= this._progressiveDataLength) {
+        return null;
+      }
+
+      var reader = new PDFFetchStreamRangeReader(this, begin, end);
+
+      this._rangeRequestReaders.push(reader);
+
+      return reader;
+    }
+  }, {
+    key: "cancelAllRequests",
+    value: function cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+
+      var readers = this._rangeRequestReaders.slice(0);
+
+      readers.forEach(function (reader) {
+        reader.cancel(reason);
+      });
+    }
+  }, {
+    key: "_progressiveDataLength",
+    get: function get() {
+      return this._fullRequestReader ? this._fullRequestReader._loaded : 0;
+    }
+  }]);
+
+  return PDFFetchStream;
+}();
+
+exports.PDFFetchStream = PDFFetchStream;
+
+var PDFFetchStreamReader =
+/*#__PURE__*/
+function () {
+  function PDFFetchStreamReader(stream) {
+    var _this = this;
+
+    _classCallCheck(this, PDFFetchStreamReader);
+
+    this._stream = stream;
+    this._reader = null;
+    this._loaded = 0;
+    this._filename = null;
+    var source = stream.source;
+    this._withCredentials = source.withCredentials || false;
+    this._contentLength = source.length;
+    this._headersCapability = (0, _util.createPromiseCapability)();
+    this._disableRange = source.disableRange || false;
+    this._rangeChunkSize = source.rangeChunkSize;
+
+    if (!this._rangeChunkSize && !this._disableRange) {
+      this._disableRange = true;
+    }
+
+    if (typeof AbortController !== 'undefined') {
+      this._abortController = new AbortController();
+    }
+
+    this._isStreamingSupported = !source.disableStream;
+    this._isRangeSupported = !source.disableRange;
+    this._headers = new Headers();
+
+    for (var property in this._stream.httpHeaders) {
+      var value = this._stream.httpHeaders[property];
+
+      if (typeof value === 'undefined') {
+        continue;
+      }
+
+      this._headers.append(property, value);
+    }
+
+    var url = source.url;
+    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
+      if (!(0, _network_utils.validateResponseStatus)(response.status)) {
+        throw (0, _network_utils.createResponseStatusError)(response.status, url);
+      }
+
+      _this._reader = response.body.getReader();
+
+      _this._headersCapability.resolve();
+
+      var getResponseHeader = function getResponseHeader(name) {
+        return response.headers.get(name);
+      };
+
+      var _validateRangeRequest = (0, _network_utils.validateRangeRequestCapabilities)({
+        getResponseHeader: getResponseHeader,
+        isHttp: _this._stream.isHttp,
+        rangeChunkSize: _this._rangeChunkSize,
+        disableRange: _this._disableRange
+      }),
+          allowRangeRequests = _validateRangeRequest.allowRangeRequests,
+          suggestedLength = _validateRangeRequest.suggestedLength;
+
+      _this._isRangeSupported = allowRangeRequests;
+      _this._contentLength = suggestedLength || _this._contentLength;
+      _this._filename = (0, _network_utils.extractFilenameFromHeader)(getResponseHeader);
+
+      if (!_this._isStreamingSupported && _this._isRangeSupported) {
+        _this.cancel(new _util.AbortException('Streaming is disabled.'));
+      }
+    })["catch"](this._headersCapability.reject);
+    this.onProgress = null;
+  }
+
+  _createClass(PDFFetchStreamReader, [{
+    key: "read",
+    value: function () {
+      var _read = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee() {
+        var _ref, value, done, buffer;
+
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                _context.next = 2;
+                return this._headersCapability.promise;
+
+              case 2:
+                _context.next = 4;
+                return this._reader.read();
+
+              case 4:
+                _ref = _context.sent;
+                value = _ref.value;
+                done = _ref.done;
+
+                if (!done) {
+                  _context.next = 9;
+                  break;
+                }
+
+                return _context.abrupt("return", {
+                  value: value,
+                  done: done
+                });
+
+              case 9:
+                this._loaded += value.byteLength;
+
+                if (this.onProgress) {
+                  this.onProgress({
+                    loaded: this._loaded,
+                    total: this._contentLength
+                  });
+                }
+
+                buffer = new Uint8Array(value).buffer;
+                return _context.abrupt("return", {
+                  value: buffer,
+                  done: false
+                });
+
+              case 13:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function read() {
+        return _read.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      if (this._reader) {
+        this._reader.cancel(reason);
+      }
+
+      if (this._abortController) {
+        this._abortController.abort();
+      }
+    }
+  }, {
+    key: "headersReady",
+    get: function get() {
+      return this._headersCapability.promise;
+    }
+  }, {
+    key: "filename",
+    get: function get() {
+      return this._filename;
+    }
+  }, {
+    key: "contentLength",
+    get: function get() {
+      return this._contentLength;
+    }
+  }, {
+    key: "isRangeSupported",
+    get: function get() {
+      return this._isRangeSupported;
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }]);
+
+  return PDFFetchStreamReader;
+}();
+
+var PDFFetchStreamRangeReader =
+/*#__PURE__*/
+function () {
+  function PDFFetchStreamRangeReader(stream, begin, end) {
+    var _this2 = this;
+
+    _classCallCheck(this, PDFFetchStreamRangeReader);
+
+    this._stream = stream;
+    this._reader = null;
+    this._loaded = 0;
+    var source = stream.source;
+    this._withCredentials = source.withCredentials || false;
+    this._readCapability = (0, _util.createPromiseCapability)();
+    this._isStreamingSupported = !source.disableStream;
+
+    if (typeof AbortController !== 'undefined') {
+      this._abortController = new AbortController();
+    }
+
+    this._headers = new Headers();
+
+    for (var property in this._stream.httpHeaders) {
+      var value = this._stream.httpHeaders[property];
+
+      if (typeof value === 'undefined') {
+        continue;
+      }
+
+      this._headers.append(property, value);
+    }
+
+    this._headers.append('Range', "bytes=".concat(begin, "-").concat(end - 1));
+
+    var url = source.url;
+    fetch(url, createFetchOptions(this._headers, this._withCredentials, this._abortController)).then(function (response) {
+      if (!(0, _network_utils.validateResponseStatus)(response.status)) {
+        throw (0, _network_utils.createResponseStatusError)(response.status, url);
+      }
+
+      _this2._readCapability.resolve();
+
+      _this2._reader = response.body.getReader();
+    });
+    this.onProgress = null;
+  }
+
+  _createClass(PDFFetchStreamRangeReader, [{
+    key: "read",
+    value: function () {
+      var _read2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2() {
+        var _ref2, value, done, buffer;
+
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                _context2.next = 2;
+                return this._readCapability.promise;
+
+              case 2:
+                _context2.next = 4;
+                return this._reader.read();
+
+              case 4:
+                _ref2 = _context2.sent;
+                value = _ref2.value;
+                done = _ref2.done;
+
+                if (!done) {
+                  _context2.next = 9;
+                  break;
+                }
+
+                return _context2.abrupt("return", {
+                  value: value,
+                  done: done
+                });
+
+              case 9:
+                this._loaded += value.byteLength;
+
+                if (this.onProgress) {
+                  this.onProgress({
+                    loaded: this._loaded
+                  });
+                }
+
+                buffer = new Uint8Array(value).buffer;
+                return _context2.abrupt("return", {
+                  value: buffer,
+                  done: false
+                });
+
+              case 13:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function read() {
+        return _read2.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      if (this._reader) {
+        this._reader.cancel(reason);
+      }
+
+      if (this._abortController) {
+        this._abortController.abort();
+      }
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }]);
+
+  return PDFFetchStreamRangeReader;
+}();
+
+/***/ })
+/******/ ]);
+});
+//# sourceMappingURL=pdf.js.map
\ No newline at end of file
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.worker.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.worker.js
new file mode 100644
index 0000000..211fbbd
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pdf_js/pdf.worker.js
@@ -0,0 +1,56199 @@
+/**
+ * @licstart The following is the entire license notice for the
+ * Javascript code in this page
+ *
+ * Copyright 2019 Mozilla Foundation
+ *
+ * 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.
+ *
+ * @licend The above is the entire license notice for the
+ * Javascript code in this page
+ */
+
+(function webpackUniversalModuleDefinition(root, factory) {
+	if(typeof exports === 'object' && typeof module === 'object')
+		module.exports = factory();
+	else if(typeof define === 'function' && define.amd)
+		define("pdfjs-dist/build/pdf.worker", [], factory);
+	else if(typeof exports === 'object')
+		exports["pdfjs-dist/build/pdf.worker"] = factory();
+	else
+		root["pdfjs-dist/build/pdf.worker"] = root.pdfjsWorker = factory();
+})(this, function() {
+return /******/ (function(modules) { // webpackBootstrap
+/******/ 	// The module cache
+/******/ 	var installedModules = {};
+/******/
+/******/ 	// The require function
+/******/ 	function __w_pdfjs_require__(moduleId) {
+/******/
+/******/ 		// Check if module is in cache
+/******/ 		if(installedModules[moduleId]) {
+/******/ 			return installedModules[moduleId].exports;
+/******/ 		}
+/******/ 		// Create a new module (and put it into the cache)
+/******/ 		var module = installedModules[moduleId] = {
+/******/ 			i: moduleId,
+/******/ 			l: false,
+/******/ 			exports: {}
+/******/ 		};
+/******/
+/******/ 		// Execute the module function
+/******/ 		modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
+/******/
+/******/ 		// Flag the module as loaded
+/******/ 		module.l = true;
+/******/
+/******/ 		// Return the exports of the module
+/******/ 		return module.exports;
+/******/ 	}
+/******/
+/******/
+/******/ 	// expose the modules object (__webpack_modules__)
+/******/ 	__w_pdfjs_require__.m = modules;
+/******/
+/******/ 	// expose the module cache
+/******/ 	__w_pdfjs_require__.c = installedModules;
+/******/
+/******/ 	// define getter function for harmony exports
+/******/ 	__w_pdfjs_require__.d = function(exports, name, getter) {
+/******/ 		if(!__w_pdfjs_require__.o(exports, name)) {
+/******/ 			Object.defineProperty(exports, name, { enumerable: true, get: getter });
+/******/ 		}
+/******/ 	};
+/******/
+/******/ 	// define __esModule on exports
+/******/ 	__w_pdfjs_require__.r = function(exports) {
+/******/ 		if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
+/******/ 			Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
+/******/ 		}
+/******/ 		Object.defineProperty(exports, '__esModule', { value: true });
+/******/ 	};
+/******/
+/******/ 	// create a fake namespace object
+/******/ 	// mode & 1: value is a module id, require it
+/******/ 	// mode & 2: merge all properties of value into the ns
+/******/ 	// mode & 4: return value when already ns object
+/******/ 	// mode & 8|1: behave like require
+/******/ 	__w_pdfjs_require__.t = function(value, mode) {
+/******/ 		if(mode & 1) value = __w_pdfjs_require__(value);
+/******/ 		if(mode & 8) return value;
+/******/ 		if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
+/******/ 		var ns = Object.create(null);
+/******/ 		__w_pdfjs_require__.r(ns);
+/******/ 		Object.defineProperty(ns, 'default', { enumerable: true, value: value });
+/******/ 		if(mode & 2 && typeof value != 'string') for(var key in value) __w_pdfjs_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
+/******/ 		return ns;
+/******/ 	};
+/******/
+/******/ 	// getDefaultExport function for compatibility with non-harmony modules
+/******/ 	__w_pdfjs_require__.n = function(module) {
+/******/ 		var getter = module && module.__esModule ?
+/******/ 			function getDefault() { return module['default']; } :
+/******/ 			function getModuleExports() { return module; };
+/******/ 		__w_pdfjs_require__.d(getter, 'a', getter);
+/******/ 		return getter;
+/******/ 	};
+/******/
+/******/ 	// Object.prototype.hasOwnProperty.call
+/******/ 	__w_pdfjs_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
+/******/
+/******/ 	// __webpack_public_path__
+/******/ 	__w_pdfjs_require__.p = "";
+/******/
+/******/
+/******/ 	// Load entry module and return exports
+/******/ 	return __w_pdfjs_require__(__w_pdfjs_require__.s = 0);
+/******/ })
+/************************************************************************/
+/******/ ([
+/* 0 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var pdfjsVersion = '2.2.228';
+var pdfjsBuild = 'd7afb74a';
+
+var pdfjsCoreWorker = __w_pdfjs_require__(1);
+
+exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler;
+
+/***/ }),
+/* 1 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.WorkerMessageHandler = exports.WorkerTask = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _pdf_manager = __w_pdfjs_require__(152);
+
+var _is_node = _interopRequireDefault(__w_pdfjs_require__(8));
+
+var _message_handler = __w_pdfjs_require__(191);
+
+var _worker_stream = __w_pdfjs_require__(192);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+var WorkerTask = function WorkerTaskClosure() {
+  function WorkerTask(name) {
+    this.name = name;
+    this.terminated = false;
+    this._capability = (0, _util.createPromiseCapability)();
+  }
+
+  WorkerTask.prototype = {
+    get finished() {
+      return this._capability.promise;
+    },
+
+    finish: function finish() {
+      this._capability.resolve();
+    },
+    terminate: function terminate() {
+      this.terminated = true;
+    },
+    ensureNotTerminated: function ensureNotTerminated() {
+      if (this.terminated) {
+        throw new Error('Worker task was terminated');
+      }
+    }
+  };
+  return WorkerTask;
+}();
+
+exports.WorkerTask = WorkerTask;
+var WorkerMessageHandler = {
+  setup: function setup(handler, port) {
+    var testMessageProcessed = false;
+    handler.on('test', function wphSetupTest(data) {
+      if (testMessageProcessed) {
+        return;
+      }
+
+      testMessageProcessed = true;
+
+      if (!(data instanceof Uint8Array)) {
+        handler.send('test', false);
+        return;
+      }
+
+      var supportTransfers = data[0] === 255;
+      handler.postMessageTransfers = supportTransfers;
+      var xhr = new XMLHttpRequest();
+      var responseExists = 'response' in xhr;
+
+      try {
+        xhr.responseType;
+      } catch (e) {
+        responseExists = false;
+      }
+
+      if (!responseExists) {
+        handler.send('test', false);
+        return;
+      }
+
+      handler.send('test', {
+        supportTypedArray: true,
+        supportTransfers: supportTransfers
+      });
+    });
+    handler.on('configure', function wphConfigure(data) {
+      (0, _util.setVerbosityLevel)(data.verbosity);
+    });
+    handler.on('GetDocRequest', function wphSetupDoc(data) {
+      return WorkerMessageHandler.createDocumentHandler(data, port);
+    });
+  },
+  createDocumentHandler: function createDocumentHandler(docParams, port) {
+    var pdfManager;
+    var terminated = false;
+    var cancelXHRs = null;
+    var WorkerTasks = [];
+    var verbosity = (0, _util.getVerbosityLevel)();
+    var apiVersion = docParams.apiVersion;
+    var workerVersion = '2.2.228';
+
+    if (apiVersion !== workerVersion) {
+      throw new Error("The API version \"".concat(apiVersion, "\" does not match ") + "the Worker version \"".concat(workerVersion, "\"."));
+    }
+
+    var docId = docParams.docId;
+    var docBaseUrl = docParams.docBaseUrl;
+    var workerHandlerName = docParams.docId + '_worker';
+    var handler = new _message_handler.MessageHandler(workerHandlerName, docId, port);
+    handler.postMessageTransfers = docParams.postMessageTransfers;
+
+    function ensureNotTerminated() {
+      if (terminated) {
+        throw new Error('Worker was terminated');
+      }
+    }
+
+    function startWorkerTask(task) {
+      WorkerTasks.push(task);
+    }
+
+    function finishWorkerTask(task) {
+      task.finish();
+      var i = WorkerTasks.indexOf(task);
+      WorkerTasks.splice(i, 1);
+    }
+
+    function loadDocument(_x) {
+      return _loadDocument.apply(this, arguments);
+    }
+
+    function _loadDocument() {
+      _loadDocument = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee(recoveryMode) {
+        var _ref4, _ref5, numPages, fingerprint;
+
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                _context.next = 2;
+                return pdfManager.ensureDoc('checkHeader');
+
+              case 2:
+                _context.next = 4;
+                return pdfManager.ensureDoc('parseStartXRef');
+
+              case 4:
+                _context.next = 6;
+                return pdfManager.ensureDoc('parse', [recoveryMode]);
+
+              case 6:
+                if (recoveryMode) {
+                  _context.next = 9;
+                  break;
+                }
+
+                _context.next = 9;
+                return pdfManager.ensureDoc('checkFirstPage');
+
+              case 9:
+                _context.next = 11;
+                return Promise.all([pdfManager.ensureDoc('numPages'), pdfManager.ensureDoc('fingerprint')]);
+
+              case 11:
+                _ref4 = _context.sent;
+                _ref5 = _slicedToArray(_ref4, 2);
+                numPages = _ref5[0];
+                fingerprint = _ref5[1];
+                return _context.abrupt("return", {
+                  numPages: numPages,
+                  fingerprint: fingerprint
+                });
+
+              case 16:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee);
+      }));
+      return _loadDocument.apply(this, arguments);
+    }
+
+    function getPdfManager(data, evaluatorOptions) {
+      var pdfManagerCapability = (0, _util.createPromiseCapability)();
+      var pdfManager;
+      var source = data.source;
+
+      if (source.data) {
+        try {
+          pdfManager = new _pdf_manager.LocalPdfManager(docId, source.data, source.password, evaluatorOptions, docBaseUrl);
+          pdfManagerCapability.resolve(pdfManager);
+        } catch (ex) {
+          pdfManagerCapability.reject(ex);
+        }
+
+        return pdfManagerCapability.promise;
+      }
+
+      var pdfStream,
+          cachedChunks = [];
+
+      try {
+        pdfStream = new _worker_stream.PDFWorkerStream(handler);
+      } catch (ex) {
+        pdfManagerCapability.reject(ex);
+        return pdfManagerCapability.promise;
+      }
+
+      var fullRequest = pdfStream.getFullReader();
+      fullRequest.headersReady.then(function () {
+        if (!fullRequest.isRangeSupported) {
+          return;
+        }
+
+        var disableAutoFetch = source.disableAutoFetch || fullRequest.isStreamingSupported;
+        pdfManager = new _pdf_manager.NetworkPdfManager(docId, pdfStream, {
+          msgHandler: handler,
+          password: source.password,
+          length: fullRequest.contentLength,
+          disableAutoFetch: disableAutoFetch,
+          rangeChunkSize: source.rangeChunkSize
+        }, evaluatorOptions, docBaseUrl);
+
+        for (var i = 0; i < cachedChunks.length; i++) {
+          pdfManager.sendProgressiveData(cachedChunks[i]);
+        }
+
+        cachedChunks = [];
+        pdfManagerCapability.resolve(pdfManager);
+        cancelXHRs = null;
+      })["catch"](function (reason) {
+        pdfManagerCapability.reject(reason);
+        cancelXHRs = null;
+      });
+      var loaded = 0;
+
+      var flushChunks = function flushChunks() {
+        var pdfFile = (0, _util.arraysToBytes)(cachedChunks);
+
+        if (source.length && pdfFile.length !== source.length) {
+          (0, _util.warn)('reported HTTP length is different from actual');
+        }
+
+        try {
+          pdfManager = new _pdf_manager.LocalPdfManager(docId, pdfFile, source.password, evaluatorOptions, docBaseUrl);
+          pdfManagerCapability.resolve(pdfManager);
+        } catch (ex) {
+          pdfManagerCapability.reject(ex);
+        }
+
+        cachedChunks = [];
+      };
+
+      var readPromise = new Promise(function (resolve, reject) {
+        var readChunk = function readChunk(chunk) {
+          try {
+            ensureNotTerminated();
+
+            if (chunk.done) {
+              if (!pdfManager) {
+                flushChunks();
+              }
+
+              cancelXHRs = null;
+              return;
+            }
+
+            var data = chunk.value;
+            loaded += (0, _util.arrayByteLength)(data);
+
+            if (!fullRequest.isStreamingSupported) {
+              handler.send('DocProgress', {
+                loaded: loaded,
+                total: Math.max(loaded, fullRequest.contentLength || 0)
+              });
+            }
+
+            if (pdfManager) {
+              pdfManager.sendProgressiveData(data);
+            } else {
+              cachedChunks.push(data);
+            }
+
+            fullRequest.read().then(readChunk, reject);
+          } catch (e) {
+            reject(e);
+          }
+        };
+
+        fullRequest.read().then(readChunk, reject);
+      });
+      readPromise["catch"](function (e) {
+        pdfManagerCapability.reject(e);
+        cancelXHRs = null;
+      });
+
+      cancelXHRs = function cancelXHRs() {
+        pdfStream.cancelAllRequests('abort');
+      };
+
+      return pdfManagerCapability.promise;
+    }
+
+    function setupDoc(data) {
+      function onSuccess(doc) {
+        ensureNotTerminated();
+        handler.send('GetDoc', {
+          pdfInfo: doc
+        });
+      }
+
+      function onFailure(e) {
+        ensureNotTerminated();
+
+        if (e instanceof _util.PasswordException) {
+          var task = new WorkerTask('PasswordException: response ' + e.code);
+          startWorkerTask(task);
+          handler.sendWithPromise('PasswordRequest', e).then(function (data) {
+            finishWorkerTask(task);
+            pdfManager.updatePassword(data.password);
+            pdfManagerReady();
+          })["catch"](function (boundException) {
+            finishWorkerTask(task);
+            handler.send('PasswordException', boundException);
+          }.bind(null, e));
+        } else if (e instanceof _util.InvalidPDFException) {
+          handler.send('InvalidPDF', e);
+        } else if (e instanceof _util.MissingPDFException) {
+          handler.send('MissingPDF', e);
+        } else if (e instanceof _util.UnexpectedResponseException) {
+          handler.send('UnexpectedResponse', e);
+        } else {
+          handler.send('UnknownError', new _util.UnknownErrorException(e.message, e.toString()));
+        }
+      }
+
+      function pdfManagerReady() {
+        ensureNotTerminated();
+        loadDocument(false).then(onSuccess, function loadFailure(ex) {
+          ensureNotTerminated();
+
+          if (!(ex instanceof _core_utils.XRefParseException)) {
+            onFailure(ex);
+            return;
+          }
+
+          pdfManager.requestLoadedStream();
+          pdfManager.onLoadedStream().then(function () {
+            ensureNotTerminated();
+            loadDocument(true).then(onSuccess, onFailure);
+          });
+        }, onFailure);
+      }
+
+      ensureNotTerminated();
+      var evaluatorOptions = {
+        forceDataSchema: data.disableCreateObjectURL,
+        maxImageSize: data.maxImageSize,
+        disableFontFace: data.disableFontFace,
+        nativeImageDecoderSupport: data.nativeImageDecoderSupport,
+        ignoreErrors: data.ignoreErrors,
+        isEvalSupported: data.isEvalSupported
+      };
+      getPdfManager(data, evaluatorOptions).then(function (newPdfManager) {
+        if (terminated) {
+          newPdfManager.terminate();
+          throw new Error('Worker was terminated');
+        }
+
+        pdfManager = newPdfManager;
+        pdfManager.onLoadedStream().then(function (stream) {
+          handler.send('DataLoaded', {
+            length: stream.bytes.byteLength
+          });
+        });
+      }).then(pdfManagerReady, onFailure);
+    }
+
+    handler.on('GetPage', function wphSetupGetPage(data) {
+      return pdfManager.getPage(data.pageIndex).then(function (page) {
+        return Promise.all([pdfManager.ensure(page, 'rotate'), pdfManager.ensure(page, 'ref'), pdfManager.ensure(page, 'userUnit'), pdfManager.ensure(page, 'view')]).then(function (_ref) {
+          var _ref2 = _slicedToArray(_ref, 4),
+              rotate = _ref2[0],
+              ref = _ref2[1],
+              userUnit = _ref2[2],
+              view = _ref2[3];
+
+          return {
+            rotate: rotate,
+            ref: ref,
+            userUnit: userUnit,
+            view: view
+          };
+        });
+      });
+    });
+    handler.on('GetPageIndex', function wphSetupGetPageIndex(data) {
+      var ref = _primitives.Ref.get(data.ref.num, data.ref.gen);
+
+      var catalog = pdfManager.pdfDocument.catalog;
+      return catalog.getPageIndex(ref);
+    });
+    handler.on('GetDestinations', function wphSetupGetDestinations(data) {
+      return pdfManager.ensureCatalog('destinations');
+    });
+    handler.on('GetDestination', function wphSetupGetDestination(data) {
+      return pdfManager.ensureCatalog('getDestination', [data.id]);
+    });
+    handler.on('GetPageLabels', function wphSetupGetPageLabels(data) {
+      return pdfManager.ensureCatalog('pageLabels');
+    });
+    handler.on('GetPageLayout', function wphSetupGetPageLayout(data) {
+      return pdfManager.ensureCatalog('pageLayout');
+    });
+    handler.on('GetPageMode', function wphSetupGetPageMode(data) {
+      return pdfManager.ensureCatalog('pageMode');
+    });
+    handler.on('GetViewerPreferences', function (data) {
+      return pdfManager.ensureCatalog('viewerPreferences');
+    });
+    handler.on('GetOpenActionDestination', function (data) {
+      return pdfManager.ensureCatalog('openActionDestination');
+    });
+    handler.on('GetAttachments', function wphSetupGetAttachments(data) {
+      return pdfManager.ensureCatalog('attachments');
+    });
+    handler.on('GetJavaScript', function wphSetupGetJavaScript(data) {
+      return pdfManager.ensureCatalog('javaScript');
+    });
+    handler.on('GetOutline', function wphSetupGetOutline(data) {
+      return pdfManager.ensureCatalog('documentOutline');
+    });
+    handler.on('GetPermissions', function (data) {
+      return pdfManager.ensureCatalog('permissions');
+    });
+    handler.on('GetMetadata', function wphSetupGetMetadata(data) {
+      return Promise.all([pdfManager.ensureDoc('documentInfo'), pdfManager.ensureCatalog('metadata')]);
+    });
+    handler.on('GetData', function wphSetupGetData(data) {
+      pdfManager.requestLoadedStream();
+      return pdfManager.onLoadedStream().then(function (stream) {
+        return stream.bytes;
+      });
+    });
+    handler.on('GetStats', function wphSetupGetStats(data) {
+      return pdfManager.pdfDocument.xref.stats;
+    });
+    handler.on('GetAnnotations', function (_ref3) {
+      var pageIndex = _ref3.pageIndex,
+          intent = _ref3.intent;
+      return pdfManager.getPage(pageIndex).then(function (page) {
+        return page.getAnnotationsData(intent);
+      });
+    });
+    handler.on('RenderPageRequest', function wphSetupRenderPage(data) {
+      var pageIndex = data.pageIndex;
+      pdfManager.getPage(pageIndex).then(function (page) {
+        var task = new WorkerTask('RenderPageRequest: page ' + pageIndex);
+        startWorkerTask(task);
+        var start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0;
+        page.getOperatorList({
+          handler: handler,
+          task: task,
+          intent: data.intent,
+          renderInteractiveForms: data.renderInteractiveForms
+        }).then(function (operatorList) {
+          finishWorkerTask(task);
+
+          if (start) {
+            (0, _util.info)("page=".concat(pageIndex + 1, " - getOperatorList: time=") + "".concat(Date.now() - start, "ms, len=").concat(operatorList.totalLength));
+          }
+        }, function (e) {
+          finishWorkerTask(task);
+
+          if (task.terminated) {
+            return;
+          }
+
+          handler.send('UnsupportedFeature', {
+            featureId: _util.UNSUPPORTED_FEATURES.unknown
+          });
+          var minimumStackMessage = 'worker.js: while trying to getPage() and getOperatorList()';
+          var wrappedException;
+
+          if (typeof e === 'string') {
+            wrappedException = {
+              message: e,
+              stack: minimumStackMessage
+            };
+          } else if (_typeof(e) === 'object') {
+            wrappedException = {
+              message: e.message || e.toString(),
+              stack: e.stack || minimumStackMessage
+            };
+          } else {
+            wrappedException = {
+              message: 'Unknown exception type: ' + _typeof(e),
+              stack: minimumStackMessage
+            };
+          }
+
+          handler.send('PageError', {
+            pageIndex: pageIndex,
+            error: wrappedException,
+            intent: data.intent
+          });
+        });
+      });
+    }, this);
+    handler.on('GetTextContent', function wphExtractText(data, sink) {
+      var pageIndex = data.pageIndex;
+
+      sink.onPull = function (desiredSize) {};
+
+      sink.onCancel = function (reason) {};
+
+      pdfManager.getPage(pageIndex).then(function (page) {
+        var task = new WorkerTask('GetTextContent: page ' + pageIndex);
+        startWorkerTask(task);
+        var start = verbosity >= _util.VerbosityLevel.INFOS ? Date.now() : 0;
+        page.extractTextContent({
+          handler: handler,
+          task: task,
+          sink: sink,
+          normalizeWhitespace: data.normalizeWhitespace,
+          combineTextItems: data.combineTextItems
+        }).then(function () {
+          finishWorkerTask(task);
+
+          if (start) {
+            (0, _util.info)("page=".concat(pageIndex + 1, " - getTextContent: time=") + "".concat(Date.now() - start, "ms"));
+          }
+
+          sink.close();
+        }, function (reason) {
+          finishWorkerTask(task);
+
+          if (task.terminated) {
+            return;
+          }
+
+          sink.error(reason);
+          throw reason;
+        });
+      });
+    });
+    handler.on('FontFallback', function (data) {
+      return pdfManager.fontFallback(data.id, handler);
+    });
+    handler.on('Cleanup', function wphCleanup(data) {
+      return pdfManager.cleanup();
+    });
+    handler.on('Terminate', function wphTerminate(data) {
+      terminated = true;
+
+      if (pdfManager) {
+        pdfManager.terminate();
+        pdfManager = null;
+      }
+
+      if (cancelXHRs) {
+        cancelXHRs();
+      }
+
+      (0, _primitives.clearPrimitiveCaches)();
+      var waitOn = [];
+      WorkerTasks.forEach(function (task) {
+        waitOn.push(task.finished);
+        task.terminate();
+      });
+      return Promise.all(waitOn).then(function () {
+        handler.destroy();
+        handler = null;
+      });
+    });
+    handler.on('Ready', function wphReady(data) {
+      setupDoc(docParams);
+      docParams = null;
+    });
+    return workerHandlerName;
+  },
+  initializeFromPort: function initializeFromPort(port) {
+    var handler = new _message_handler.MessageHandler('worker', 'main', port);
+    WorkerMessageHandler.setup(handler, port);
+    handler.send('ready', null);
+  }
+};
+exports.WorkerMessageHandler = WorkerMessageHandler;
+
+function isMessagePort(maybePort) {
+  return typeof maybePort.postMessage === 'function' && 'onmessage' in maybePort;
+}
+
+if (typeof window === 'undefined' && !(0, _is_node["default"])() && typeof self !== 'undefined' && isMessagePort(self)) {
+  WorkerMessageHandler.initializeFromPort(self);
+}
+
+/***/ }),
+/* 2 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = __w_pdfjs_require__(3);
+
+/***/ }),
+/* 3 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+/* WEBPACK VAR INJECTION */(function(module) {
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var runtime = function (exports) {
+  "use strict";
+
+  var Op = Object.prototype;
+  var hasOwn = Op.hasOwnProperty;
+  var undefined;
+  var $Symbol = typeof Symbol === "function" ? Symbol : {};
+  var iteratorSymbol = $Symbol.iterator || "@@iterator";
+  var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator";
+  var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";
+
+  function wrap(innerFn, outerFn, self, tryLocsList) {
+    var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator;
+    var generator = Object.create(protoGenerator.prototype);
+    var context = new Context(tryLocsList || []);
+    generator._invoke = makeInvokeMethod(innerFn, self, context);
+    return generator;
+  }
+
+  exports.wrap = wrap;
+
+  function tryCatch(fn, obj, arg) {
+    try {
+      return {
+        type: "normal",
+        arg: fn.call(obj, arg)
+      };
+    } catch (err) {
+      return {
+        type: "throw",
+        arg: err
+      };
+    }
+  }
+
+  var GenStateSuspendedStart = "suspendedStart";
+  var GenStateSuspendedYield = "suspendedYield";
+  var GenStateExecuting = "executing";
+  var GenStateCompleted = "completed";
+  var ContinueSentinel = {};
+
+  function Generator() {}
+
+  function GeneratorFunction() {}
+
+  function GeneratorFunctionPrototype() {}
+
+  var IteratorPrototype = {};
+
+  IteratorPrototype[iteratorSymbol] = function () {
+    return this;
+  };
+
+  var getProto = Object.getPrototypeOf;
+  var NativeIteratorPrototype = getProto && getProto(getProto(values([])));
+
+  if (NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) {
+    IteratorPrototype = NativeIteratorPrototype;
+  }
+
+  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);
+  GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype;
+  GeneratorFunctionPrototype.constructor = GeneratorFunction;
+  GeneratorFunctionPrototype[toStringTagSymbol] = GeneratorFunction.displayName = "GeneratorFunction";
+
+  function defineIteratorMethods(prototype) {
+    ["next", "throw", "return"].forEach(function (method) {
+      prototype[method] = function (arg) {
+        return this._invoke(method, arg);
+      };
+    });
+  }
+
+  exports.isGeneratorFunction = function (genFun) {
+    var ctor = typeof genFun === "function" && genFun.constructor;
+    return ctor ? ctor === GeneratorFunction || (ctor.displayName || ctor.name) === "GeneratorFunction" : false;
+  };
+
+  exports.mark = function (genFun) {
+    if (Object.setPrototypeOf) {
+      Object.setPrototypeOf(genFun, GeneratorFunctionPrototype);
+    } else {
+      genFun.__proto__ = GeneratorFunctionPrototype;
+
+      if (!(toStringTagSymbol in genFun)) {
+        genFun[toStringTagSymbol] = "GeneratorFunction";
+      }
+    }
+
+    genFun.prototype = Object.create(Gp);
+    return genFun;
+  };
+
+  exports.awrap = function (arg) {
+    return {
+      __await: arg
+    };
+  };
+
+  function AsyncIterator(generator) {
+    function invoke(method, arg, resolve, reject) {
+      var record = tryCatch(generator[method], generator, arg);
+
+      if (record.type === "throw") {
+        reject(record.arg);
+      } else {
+        var result = record.arg;
+        var value = result.value;
+
+        if (value && _typeof(value) === "object" && hasOwn.call(value, "__await")) {
+          return Promise.resolve(value.__await).then(function (value) {
+            invoke("next", value, resolve, reject);
+          }, function (err) {
+            invoke("throw", err, resolve, reject);
+          });
+        }
+
+        return Promise.resolve(value).then(function (unwrapped) {
+          result.value = unwrapped;
+          resolve(result);
+        }, function (error) {
+          return invoke("throw", error, resolve, reject);
+        });
+      }
+    }
+
+    var previousPromise;
+
+    function enqueue(method, arg) {
+      function callInvokeWithMethodAndArg() {
+        return new Promise(function (resolve, reject) {
+          invoke(method, arg, resolve, reject);
+        });
+      }
+
+      return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
+    }
+
+    this._invoke = enqueue;
+  }
+
+  defineIteratorMethods(AsyncIterator.prototype);
+
+  AsyncIterator.prototype[asyncIteratorSymbol] = function () {
+    return this;
+  };
+
+  exports.AsyncIterator = AsyncIterator;
+
+  exports.async = function (innerFn, outerFn, self, tryLocsList) {
+    var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList));
+    return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
+      return result.done ? result.value : iter.next();
+    });
+  };
+
+  function makeInvokeMethod(innerFn, self, context) {
+    var state = GenStateSuspendedStart;
+    return function invoke(method, arg) {
+      if (state === GenStateExecuting) {
+        throw new Error("Generator is already running");
+      }
+
+      if (state === GenStateCompleted) {
+        if (method === "throw") {
+          throw arg;
+        }
+
+        return doneResult();
+      }
+
+      context.method = method;
+      context.arg = arg;
+
+      while (true) {
+        var delegate = context.delegate;
+
+        if (delegate) {
+          var delegateResult = maybeInvokeDelegate(delegate, context);
+
+          if (delegateResult) {
+            if (delegateResult === ContinueSentinel) continue;
+            return delegateResult;
+          }
+        }
+
+        if (context.method === "next") {
+          context.sent = context._sent = context.arg;
+        } else if (context.method === "throw") {
+          if (state === GenStateSuspendedStart) {
+            state = GenStateCompleted;
+            throw context.arg;
+          }
+
+          context.dispatchException(context.arg);
+        } else if (context.method === "return") {
+          context.abrupt("return", context.arg);
+        }
+
+        state = GenStateExecuting;
+        var record = tryCatch(innerFn, self, context);
+
+        if (record.type === "normal") {
+          state = context.done ? GenStateCompleted : GenStateSuspendedYield;
+
+          if (record.arg === ContinueSentinel) {
+            continue;
+          }
+
+          return {
+            value: record.arg,
+            done: context.done
+          };
+        } else if (record.type === "throw") {
+          state = GenStateCompleted;
+          context.method = "throw";
+          context.arg = record.arg;
+        }
+      }
+    };
+  }
+
+  function maybeInvokeDelegate(delegate, context) {
+    var method = delegate.iterator[context.method];
+
+    if (method === undefined) {
+      context.delegate = null;
+
+      if (context.method === "throw") {
+        if (delegate.iterator["return"]) {
+          context.method = "return";
+          context.arg = undefined;
+          maybeInvokeDelegate(delegate, context);
+
+          if (context.method === "throw") {
+            return ContinueSentinel;
+          }
+        }
+
+        context.method = "throw";
+        context.arg = new TypeError("The iterator does not provide a 'throw' method");
+      }
+
+      return ContinueSentinel;
+    }
+
+    var record = tryCatch(method, delegate.iterator, context.arg);
+
+    if (record.type === "throw") {
+      context.method = "throw";
+      context.arg = record.arg;
+      context.delegate = null;
+      return ContinueSentinel;
+    }
+
+    var info = record.arg;
+
+    if (!info) {
+      context.method = "throw";
+      context.arg = new TypeError("iterator result is not an object");
+      context.delegate = null;
+      return ContinueSentinel;
+    }
+
+    if (info.done) {
+      context[delegate.resultName] = info.value;
+      context.next = delegate.nextLoc;
+
+      if (context.method !== "return") {
+        context.method = "next";
+        context.arg = undefined;
+      }
+    } else {
+      return info;
+    }
+
+    context.delegate = null;
+    return ContinueSentinel;
+  }
+
+  defineIteratorMethods(Gp);
+  Gp[toStringTagSymbol] = "Generator";
+
+  Gp[iteratorSymbol] = function () {
+    return this;
+  };
+
+  Gp.toString = function () {
+    return "[object Generator]";
+  };
+
+  function pushTryEntry(locs) {
+    var entry = {
+      tryLoc: locs[0]
+    };
+
+    if (1 in locs) {
+      entry.catchLoc = locs[1];
+    }
+
+    if (2 in locs) {
+      entry.finallyLoc = locs[2];
+      entry.afterLoc = locs[3];
+    }
+
+    this.tryEntries.push(entry);
+  }
+
+  function resetTryEntry(entry) {
+    var record = entry.completion || {};
+    record.type = "normal";
+    delete record.arg;
+    entry.completion = record;
+  }
+
+  function Context(tryLocsList) {
+    this.tryEntries = [{
+      tryLoc: "root"
+    }];
+    tryLocsList.forEach(pushTryEntry, this);
+    this.reset(true);
+  }
+
+  exports.keys = function (object) {
+    var keys = [];
+
+    for (var key in object) {
+      keys.push(key);
+    }
+
+    keys.reverse();
+    return function next() {
+      while (keys.length) {
+        var key = keys.pop();
+
+        if (key in object) {
+          next.value = key;
+          next.done = false;
+          return next;
+        }
+      }
+
+      next.done = true;
+      return next;
+    };
+  };
+
+  function values(iterable) {
+    if (iterable) {
+      var iteratorMethod = iterable[iteratorSymbol];
+
+      if (iteratorMethod) {
+        return iteratorMethod.call(iterable);
+      }
+
+      if (typeof iterable.next === "function") {
+        return iterable;
+      }
+
+      if (!isNaN(iterable.length)) {
+        var i = -1,
+            next = function next() {
+          while (++i < iterable.length) {
+            if (hasOwn.call(iterable, i)) {
+              next.value = iterable[i];
+              next.done = false;
+              return next;
+            }
+          }
+
+          next.value = undefined;
+          next.done = true;
+          return next;
+        };
+
+        return next.next = next;
+      }
+    }
+
+    return {
+      next: doneResult
+    };
+  }
+
+  exports.values = values;
+
+  function doneResult() {
+    return {
+      value: undefined,
+      done: true
+    };
+  }
+
+  Context.prototype = {
+    constructor: Context,
+    reset: function reset(skipTempReset) {
+      this.prev = 0;
+      this.next = 0;
+      this.sent = this._sent = undefined;
+      this.done = false;
+      this.delegate = null;
+      this.method = "next";
+      this.arg = undefined;
+      this.tryEntries.forEach(resetTryEntry);
+
+      if (!skipTempReset) {
+        for (var name in this) {
+          if (name.charAt(0) === "t" && hasOwn.call(this, name) && !isNaN(+name.slice(1))) {
+            this[name] = undefined;
+          }
+        }
+      }
+    },
+    stop: function stop() {
+      this.done = true;
+      var rootEntry = this.tryEntries[0];
+      var rootRecord = rootEntry.completion;
+
+      if (rootRecord.type === "throw") {
+        throw rootRecord.arg;
+      }
+
+      return this.rval;
+    },
+    dispatchException: function dispatchException(exception) {
+      if (this.done) {
+        throw exception;
+      }
+
+      var context = this;
+
+      function handle(loc, caught) {
+        record.type = "throw";
+        record.arg = exception;
+        context.next = loc;
+
+        if (caught) {
+          context.method = "next";
+          context.arg = undefined;
+        }
+
+        return !!caught;
+      }
+
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+        var record = entry.completion;
+
+        if (entry.tryLoc === "root") {
+          return handle("end");
+        }
+
+        if (entry.tryLoc <= this.prev) {
+          var hasCatch = hasOwn.call(entry, "catchLoc");
+          var hasFinally = hasOwn.call(entry, "finallyLoc");
+
+          if (hasCatch && hasFinally) {
+            if (this.prev < entry.catchLoc) {
+              return handle(entry.catchLoc, true);
+            } else if (this.prev < entry.finallyLoc) {
+              return handle(entry.finallyLoc);
+            }
+          } else if (hasCatch) {
+            if (this.prev < entry.catchLoc) {
+              return handle(entry.catchLoc, true);
+            }
+          } else if (hasFinally) {
+            if (this.prev < entry.finallyLoc) {
+              return handle(entry.finallyLoc);
+            }
+          } else {
+            throw new Error("try statement without catch or finally");
+          }
+        }
+      }
+    },
+    abrupt: function abrupt(type, arg) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
+          var finallyEntry = entry;
+          break;
+        }
+      }
+
+      if (finallyEntry && (type === "break" || type === "continue") && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc) {
+        finallyEntry = null;
+      }
+
+      var record = finallyEntry ? finallyEntry.completion : {};
+      record.type = type;
+      record.arg = arg;
+
+      if (finallyEntry) {
+        this.method = "next";
+        this.next = finallyEntry.finallyLoc;
+        return ContinueSentinel;
+      }
+
+      return this.complete(record);
+    },
+    complete: function complete(record, afterLoc) {
+      if (record.type === "throw") {
+        throw record.arg;
+      }
+
+      if (record.type === "break" || record.type === "continue") {
+        this.next = record.arg;
+      } else if (record.type === "return") {
+        this.rval = this.arg = record.arg;
+        this.method = "return";
+        this.next = "end";
+      } else if (record.type === "normal" && afterLoc) {
+        this.next = afterLoc;
+      }
+
+      return ContinueSentinel;
+    },
+    finish: function finish(finallyLoc) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.finallyLoc === finallyLoc) {
+          this.complete(entry.completion, entry.afterLoc);
+          resetTryEntry(entry);
+          return ContinueSentinel;
+        }
+      }
+    },
+    "catch": function _catch(tryLoc) {
+      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
+        var entry = this.tryEntries[i];
+
+        if (entry.tryLoc === tryLoc) {
+          var record = entry.completion;
+
+          if (record.type === "throw") {
+            var thrown = record.arg;
+            resetTryEntry(entry);
+          }
+
+          return thrown;
+        }
+      }
+
+      throw new Error("illegal catch attempt");
+    },
+    delegateYield: function delegateYield(iterable, resultName, nextLoc) {
+      this.delegate = {
+        iterator: values(iterable),
+        resultName: resultName,
+        nextLoc: nextLoc
+      };
+
+      if (this.method === "next") {
+        this.arg = undefined;
+      }
+
+      return ContinueSentinel;
+    }
+  };
+  return exports;
+}(( false ? undefined : _typeof(module)) === "object" ? module.exports : {});
+
+try {
+  regeneratorRuntime = runtime;
+} catch (accidentalStrictMode) {
+  Function("r", "regeneratorRuntime = r")(runtime);
+}
+/* WEBPACK VAR INJECTION */}.call(this, __w_pdfjs_require__(4)(module)))
+
+/***/ }),
+/* 4 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (module) {
+  if (!module.webpackPolyfill) {
+    module.deprecate = function () {};
+
+    module.paths = [];
+    if (!module.children) module.children = [];
+    Object.defineProperty(module, "loaded", {
+      enumerable: true,
+      get: function get() {
+        return module.l;
+      }
+    });
+    Object.defineProperty(module, "id", {
+      enumerable: true,
+      get: function get() {
+        return module.i;
+      }
+    });
+    module.webpackPolyfill = 1;
+  }
+
+  return module;
+};
+
+/***/ }),
+/* 5 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.arrayByteLength = arrayByteLength;
+exports.arraysToBytes = arraysToBytes;
+exports.assert = assert;
+exports.bytesToString = bytesToString;
+exports.createPromiseCapability = createPromiseCapability;
+exports.getVerbosityLevel = getVerbosityLevel;
+exports.info = info;
+exports.isArrayBuffer = isArrayBuffer;
+exports.isArrayEqual = isArrayEqual;
+exports.isBool = isBool;
+exports.isEmptyObj = isEmptyObj;
+exports.isNum = isNum;
+exports.isString = isString;
+exports.isSpace = isSpace;
+exports.isSameOrigin = isSameOrigin;
+exports.createValidAbsoluteUrl = createValidAbsoluteUrl;
+exports.isLittleEndian = isLittleEndian;
+exports.isEvalSupported = isEvalSupported;
+exports.log2 = log2;
+exports.readInt8 = readInt8;
+exports.readUint16 = readUint16;
+exports.readUint32 = readUint32;
+exports.removeNullCharacters = removeNullCharacters;
+exports.setVerbosityLevel = setVerbosityLevel;
+exports.shadow = shadow;
+exports.string32 = string32;
+exports.stringToBytes = stringToBytes;
+exports.stringToPDFString = stringToPDFString;
+exports.stringToUTF8String = stringToUTF8String;
+exports.utf8StringToString = utf8StringToString;
+exports.warn = warn;
+exports.unreachable = unreachable;
+Object.defineProperty(exports, "ReadableStream", {
+  enumerable: true,
+  get: function get() {
+    return _streams_polyfill.ReadableStream;
+  }
+});
+Object.defineProperty(exports, "URL", {
+  enumerable: true,
+  get: function get() {
+    return _url_polyfill.URL;
+  }
+});
+exports.createObjectURL = exports.FormatError = exports.Util = exports.UnknownErrorException = exports.UnexpectedResponseException = exports.TextRenderingMode = exports.StreamType = exports.PermissionFlag = exports.PasswordResponses = exports.PasswordException = exports.NativeImageDecoding = exports.MissingPDFException = exports.InvalidPDFException = exports.AbortException = exports.CMapCompressionType = exports.ImageKind = exports.FontType = exports.AnnotationType = exports.AnnotationFlag = exports.AnnotationFieldFlag = exports.AnnotationBorderStyleType = exports.UNSUPPORTED_FEATURES = exports.VerbosityLevel = exports.OPS = exports.IDENTITY_MATRIX = exports.FONT_IDENTITY_MATRIX = void 0;
+
+__w_pdfjs_require__(6);
+
+var _streams_polyfill = __w_pdfjs_require__(147);
+
+var _url_polyfill = __w_pdfjs_require__(149);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var IDENTITY_MATRIX = [1, 0, 0, 1, 0, 0];
+exports.IDENTITY_MATRIX = IDENTITY_MATRIX;
+var FONT_IDENTITY_MATRIX = [0.001, 0, 0, 0.001, 0, 0];
+exports.FONT_IDENTITY_MATRIX = FONT_IDENTITY_MATRIX;
+var NativeImageDecoding = {
+  NONE: 'none',
+  DECODE: 'decode',
+  DISPLAY: 'display'
+};
+exports.NativeImageDecoding = NativeImageDecoding;
+var PermissionFlag = {
+  PRINT: 0x04,
+  MODIFY_CONTENTS: 0x08,
+  COPY: 0x10,
+  MODIFY_ANNOTATIONS: 0x20,
+  FILL_INTERACTIVE_FORMS: 0x100,
+  COPY_FOR_ACCESSIBILITY: 0x200,
+  ASSEMBLE: 0x400,
+  PRINT_HIGH_QUALITY: 0x800
+};
+exports.PermissionFlag = PermissionFlag;
+var TextRenderingMode = {
+  FILL: 0,
+  STROKE: 1,
+  FILL_STROKE: 2,
+  INVISIBLE: 3,
+  FILL_ADD_TO_PATH: 4,
+  STROKE_ADD_TO_PATH: 5,
+  FILL_STROKE_ADD_TO_PATH: 6,
+  ADD_TO_PATH: 7,
+  FILL_STROKE_MASK: 3,
+  ADD_TO_PATH_FLAG: 4
+};
+exports.TextRenderingMode = TextRenderingMode;
+var ImageKind = {
+  GRAYSCALE_1BPP: 1,
+  RGB_24BPP: 2,
+  RGBA_32BPP: 3
+};
+exports.ImageKind = ImageKind;
+var AnnotationType = {
+  TEXT: 1,
+  LINK: 2,
+  FREETEXT: 3,
+  LINE: 4,
+  SQUARE: 5,
+  CIRCLE: 6,
+  POLYGON: 7,
+  POLYLINE: 8,
+  HIGHLIGHT: 9,
+  UNDERLINE: 10,
+  SQUIGGLY: 11,
+  STRIKEOUT: 12,
+  STAMP: 13,
+  CARET: 14,
+  INK: 15,
+  POPUP: 16,
+  FILEATTACHMENT: 17,
+  SOUND: 18,
+  MOVIE: 19,
+  WIDGET: 20,
+  SCREEN: 21,
+  PRINTERMARK: 22,
+  TRAPNET: 23,
+  WATERMARK: 24,
+  THREED: 25,
+  REDACT: 26
+};
+exports.AnnotationType = AnnotationType;
+var AnnotationFlag = {
+  INVISIBLE: 0x01,
+  HIDDEN: 0x02,
+  PRINT: 0x04,
+  NOZOOM: 0x08,
+  NOROTATE: 0x10,
+  NOVIEW: 0x20,
+  READONLY: 0x40,
+  LOCKED: 0x80,
+  TOGGLENOVIEW: 0x100,
+  LOCKEDCONTENTS: 0x200
+};
+exports.AnnotationFlag = AnnotationFlag;
+var AnnotationFieldFlag = {
+  READONLY: 0x0000001,
+  REQUIRED: 0x0000002,
+  NOEXPORT: 0x0000004,
+  MULTILINE: 0x0001000,
+  PASSWORD: 0x0002000,
+  NOTOGGLETOOFF: 0x0004000,
+  RADIO: 0x0008000,
+  PUSHBUTTON: 0x0010000,
+  COMBO: 0x0020000,
+  EDIT: 0x0040000,
+  SORT: 0x0080000,
+  FILESELECT: 0x0100000,
+  MULTISELECT: 0x0200000,
+  DONOTSPELLCHECK: 0x0400000,
+  DONOTSCROLL: 0x0800000,
+  COMB: 0x1000000,
+  RICHTEXT: 0x2000000,
+  RADIOSINUNISON: 0x2000000,
+  COMMITONSELCHANGE: 0x4000000
+};
+exports.AnnotationFieldFlag = AnnotationFieldFlag;
+var AnnotationBorderStyleType = {
+  SOLID: 1,
+  DASHED: 2,
+  BEVELED: 3,
+  INSET: 4,
+  UNDERLINE: 5
+};
+exports.AnnotationBorderStyleType = AnnotationBorderStyleType;
+var StreamType = {
+  UNKNOWN: 0,
+  FLATE: 1,
+  LZW: 2,
+  DCT: 3,
+  JPX: 4,
+  JBIG: 5,
+  A85: 6,
+  AHX: 7,
+  CCF: 8,
+  RL: 9
+};
+exports.StreamType = StreamType;
+var FontType = {
+  UNKNOWN: 0,
+  TYPE1: 1,
+  TYPE1C: 2,
+  CIDFONTTYPE0: 3,
+  CIDFONTTYPE0C: 4,
+  TRUETYPE: 5,
+  CIDFONTTYPE2: 6,
+  TYPE3: 7,
+  OPENTYPE: 8,
+  TYPE0: 9,
+  MMTYPE1: 10
+};
+exports.FontType = FontType;
+var VerbosityLevel = {
+  ERRORS: 0,
+  WARNINGS: 1,
+  INFOS: 5
+};
+exports.VerbosityLevel = VerbosityLevel;
+var CMapCompressionType = {
+  NONE: 0,
+  BINARY: 1,
+  STREAM: 2
+};
+exports.CMapCompressionType = CMapCompressionType;
+var OPS = {
+  dependency: 1,
+  setLineWidth: 2,
+  setLineCap: 3,
+  setLineJoin: 4,
+  setMiterLimit: 5,
+  setDash: 6,
+  setRenderingIntent: 7,
+  setFlatness: 8,
+  setGState: 9,
+  save: 10,
+  restore: 11,
+  transform: 12,
+  moveTo: 13,
+  lineTo: 14,
+  curveTo: 15,
+  curveTo2: 16,
+  curveTo3: 17,
+  closePath: 18,
+  rectangle: 19,
+  stroke: 20,
+  closeStroke: 21,
+  fill: 22,
+  eoFill: 23,
+  fillStroke: 24,
+  eoFillStroke: 25,
+  closeFillStroke: 26,
+  closeEOFillStroke: 27,
+  endPath: 28,
+  clip: 29,
+  eoClip: 30,
+  beginText: 31,
+  endText: 32,
+  setCharSpacing: 33,
+  setWordSpacing: 34,
+  setHScale: 35,
+  setLeading: 36,
+  setFont: 37,
+  setTextRenderingMode: 38,
+  setTextRise: 39,
+  moveText: 40,
+  setLeadingMoveText: 41,
+  setTextMatrix: 42,
+  nextLine: 43,
+  showText: 44,
+  showSpacedText: 45,
+  nextLineShowText: 46,
+  nextLineSetSpacingShowText: 47,
+  setCharWidth: 48,
+  setCharWidthAndBounds: 49,
+  setStrokeColorSpace: 50,
+  setFillColorSpace: 51,
+  setStrokeColor: 52,
+  setStrokeColorN: 53,
+  setFillColor: 54,
+  setFillColorN: 55,
+  setStrokeGray: 56,
+  setFillGray: 57,
+  setStrokeRGBColor: 58,
+  setFillRGBColor: 59,
+  setStrokeCMYKColor: 60,
+  setFillCMYKColor: 61,
+  shadingFill: 62,
+  beginInlineImage: 63,
+  beginImageData: 64,
+  endInlineImage: 65,
+  paintXObject: 66,
+  markPoint: 67,
+  markPointProps: 68,
+  beginMarkedContent: 69,
+  beginMarkedContentProps: 70,
+  endMarkedContent: 71,
+  beginCompat: 72,
+  endCompat: 73,
+  paintFormXObjectBegin: 74,
+  paintFormXObjectEnd: 75,
+  beginGroup: 76,
+  endGroup: 77,
+  beginAnnotations: 78,
+  endAnnotations: 79,
+  beginAnnotation: 80,
+  endAnnotation: 81,
+  paintJpegXObject: 82,
+  paintImageMaskXObject: 83,
+  paintImageMaskXObjectGroup: 84,
+  paintImageXObject: 85,
+  paintInlineImageXObject: 86,
+  paintInlineImageXObjectGroup: 87,
+  paintImageXObjectRepeat: 88,
+  paintImageMaskXObjectRepeat: 89,
+  paintSolidColorImageMask: 90,
+  constructPath: 91
+};
+exports.OPS = OPS;
+var UNSUPPORTED_FEATURES = {
+  unknown: 'unknown',
+  forms: 'forms',
+  javaScript: 'javaScript',
+  smask: 'smask',
+  shadingPattern: 'shadingPattern',
+  font: 'font'
+};
+exports.UNSUPPORTED_FEATURES = UNSUPPORTED_FEATURES;
+var PasswordResponses = {
+  NEED_PASSWORD: 1,
+  INCORRECT_PASSWORD: 2
+};
+exports.PasswordResponses = PasswordResponses;
+var verbosity = VerbosityLevel.WARNINGS;
+
+function setVerbosityLevel(level) {
+  if (Number.isInteger(level)) {
+    verbosity = level;
+  }
+}
+
+function getVerbosityLevel() {
+  return verbosity;
+}
+
+function info(msg) {
+  if (verbosity >= VerbosityLevel.INFOS) {
+    console.log('Info: ' + msg);
+  }
+}
+
+function warn(msg) {
+  if (verbosity >= VerbosityLevel.WARNINGS) {
+    console.log('Warning: ' + msg);
+  }
+}
+
+function unreachable(msg) {
+  throw new Error(msg);
+}
+
+function assert(cond, msg) {
+  if (!cond) {
+    unreachable(msg);
+  }
+}
+
+function isSameOrigin(baseUrl, otherUrl) {
+  try {
+    var base = new _url_polyfill.URL(baseUrl);
+
+    if (!base.origin || base.origin === 'null') {
+      return false;
+    }
+  } catch (e) {
+    return false;
+  }
+
+  var other = new _url_polyfill.URL(otherUrl, base);
+  return base.origin === other.origin;
+}
+
+function _isValidProtocol(url) {
+  if (!url) {
+    return false;
+  }
+
+  switch (url.protocol) {
+    case 'http:':
+    case 'https:':
+    case 'ftp:':
+    case 'mailto:':
+    case 'tel:':
+      return true;
+
+    default:
+      return false;
+  }
+}
+
+function createValidAbsoluteUrl(url, baseUrl) {
+  if (!url) {
+    return null;
+  }
+
+  try {
+    var absoluteUrl = baseUrl ? new _url_polyfill.URL(url, baseUrl) : new _url_polyfill.URL(url);
+
+    if (_isValidProtocol(absoluteUrl)) {
+      return absoluteUrl;
+    }
+  } catch (ex) {}
+
+  return null;
+}
+
+function shadow(obj, prop, value) {
+  Object.defineProperty(obj, prop, {
+    value: value,
+    enumerable: true,
+    configurable: true,
+    writable: false
+  });
+  return value;
+}
+
+var PasswordException = function PasswordExceptionClosure() {
+  function PasswordException(msg, code) {
+    this.name = 'PasswordException';
+    this.message = msg;
+    this.code = code;
+  }
+
+  PasswordException.prototype = new Error();
+  PasswordException.constructor = PasswordException;
+  return PasswordException;
+}();
+
+exports.PasswordException = PasswordException;
+
+var UnknownErrorException = function UnknownErrorExceptionClosure() {
+  function UnknownErrorException(msg, details) {
+    this.name = 'UnknownErrorException';
+    this.message = msg;
+    this.details = details;
+  }
+
+  UnknownErrorException.prototype = new Error();
+  UnknownErrorException.constructor = UnknownErrorException;
+  return UnknownErrorException;
+}();
+
+exports.UnknownErrorException = UnknownErrorException;
+
+var InvalidPDFException = function InvalidPDFExceptionClosure() {
+  function InvalidPDFException(msg) {
+    this.name = 'InvalidPDFException';
+    this.message = msg;
+  }
+
+  InvalidPDFException.prototype = new Error();
+  InvalidPDFException.constructor = InvalidPDFException;
+  return InvalidPDFException;
+}();
+
+exports.InvalidPDFException = InvalidPDFException;
+
+var MissingPDFException = function MissingPDFExceptionClosure() {
+  function MissingPDFException(msg) {
+    this.name = 'MissingPDFException';
+    this.message = msg;
+  }
+
+  MissingPDFException.prototype = new Error();
+  MissingPDFException.constructor = MissingPDFException;
+  return MissingPDFException;
+}();
+
+exports.MissingPDFException = MissingPDFException;
+
+var UnexpectedResponseException = function UnexpectedResponseExceptionClosure() {
+  function UnexpectedResponseException(msg, status) {
+    this.name = 'UnexpectedResponseException';
+    this.message = msg;
+    this.status = status;
+  }
+
+  UnexpectedResponseException.prototype = new Error();
+  UnexpectedResponseException.constructor = UnexpectedResponseException;
+  return UnexpectedResponseException;
+}();
+
+exports.UnexpectedResponseException = UnexpectedResponseException;
+
+var FormatError = function FormatErrorClosure() {
+  function FormatError(msg) {
+    this.message = msg;
+  }
+
+  FormatError.prototype = new Error();
+  FormatError.prototype.name = 'FormatError';
+  FormatError.constructor = FormatError;
+  return FormatError;
+}();
+
+exports.FormatError = FormatError;
+
+var AbortException = function AbortExceptionClosure() {
+  function AbortException(msg) {
+    this.name = 'AbortException';
+    this.message = msg;
+  }
+
+  AbortException.prototype = new Error();
+  AbortException.constructor = AbortException;
+  return AbortException;
+}();
+
+exports.AbortException = AbortException;
+var NullCharactersRegExp = /\x00/g;
+
+function removeNullCharacters(str) {
+  if (typeof str !== 'string') {
+    warn('The argument for removeNullCharacters must be a string.');
+    return str;
+  }
+
+  return str.replace(NullCharactersRegExp, '');
+}
+
+function bytesToString(bytes) {
+  assert(bytes !== null && _typeof(bytes) === 'object' && bytes.length !== undefined, 'Invalid argument for bytesToString');
+  var length = bytes.length;
+  var MAX_ARGUMENT_COUNT = 8192;
+
+  if (length < MAX_ARGUMENT_COUNT) {
+    return String.fromCharCode.apply(null, bytes);
+  }
+
+  var strBuf = [];
+
+  for (var i = 0; i < length; i += MAX_ARGUMENT_COUNT) {
+    var chunkEnd = Math.min(i + MAX_ARGUMENT_COUNT, length);
+    var chunk = bytes.subarray(i, chunkEnd);
+    strBuf.push(String.fromCharCode.apply(null, chunk));
+  }
+
+  return strBuf.join('');
+}
+
+function stringToBytes(str) {
+  assert(typeof str === 'string', 'Invalid argument for stringToBytes');
+  var length = str.length;
+  var bytes = new Uint8Array(length);
+
+  for (var i = 0; i < length; ++i) {
+    bytes[i] = str.charCodeAt(i) & 0xFF;
+  }
+
+  return bytes;
+}
+
+function arrayByteLength(arr) {
+  if (arr.length !== undefined) {
+    return arr.length;
+  }
+
+  assert(arr.byteLength !== undefined);
+  return arr.byteLength;
+}
+
+function arraysToBytes(arr) {
+  if (arr.length === 1 && arr[0] instanceof Uint8Array) {
+    return arr[0];
+  }
+
+  var resultLength = 0;
+  var i,
+      ii = arr.length;
+  var item, itemLength;
+
+  for (i = 0; i < ii; i++) {
+    item = arr[i];
+    itemLength = arrayByteLength(item);
+    resultLength += itemLength;
+  }
+
+  var pos = 0;
+  var data = new Uint8Array(resultLength);
+
+  for (i = 0; i < ii; i++) {
+    item = arr[i];
+
+    if (!(item instanceof Uint8Array)) {
+      if (typeof item === 'string') {
+        item = stringToBytes(item);
+      } else {
+        item = new Uint8Array(item);
+      }
+    }
+
+    itemLength = item.byteLength;
+    data.set(item, pos);
+    pos += itemLength;
+  }
+
+  return data;
+}
+
+function string32(value) {
+  return String.fromCharCode(value >> 24 & 0xff, value >> 16 & 0xff, value >> 8 & 0xff, value & 0xff);
+}
+
+function log2(x) {
+  if (x <= 0) {
+    return 0;
+  }
+
+  return Math.ceil(Math.log2(x));
+}
+
+function readInt8(data, start) {
+  return data[start] << 24 >> 24;
+}
+
+function readUint16(data, offset) {
+  return data[offset] << 8 | data[offset + 1];
+}
+
+function readUint32(data, offset) {
+  return (data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3]) >>> 0;
+}
+
+function isLittleEndian() {
+  var buffer8 = new Uint8Array(4);
+  buffer8[0] = 1;
+  var view32 = new Uint32Array(buffer8.buffer, 0, 1);
+  return view32[0] === 1;
+}
+
+function isEvalSupported() {
+  try {
+    new Function('');
+    return true;
+  } catch (e) {
+    return false;
+  }
+}
+
+var Util = function UtilClosure() {
+  function Util() {}
+
+  var rgbBuf = ['rgb(', 0, ',', 0, ',', 0, ')'];
+
+  Util.makeCssRgb = function Util_makeCssRgb(r, g, b) {
+    rgbBuf[1] = r;
+    rgbBuf[3] = g;
+    rgbBuf[5] = b;
+    return rgbBuf.join('');
+  };
+
+  Util.transform = function Util_transform(m1, m2) {
+    return [m1[0] * m2[0] + m1[2] * m2[1], m1[1] * m2[0] + m1[3] * m2[1], m1[0] * m2[2] + m1[2] * m2[3], m1[1] * m2[2] + m1[3] * m2[3], m1[0] * m2[4] + m1[2] * m2[5] + m1[4], m1[1] * m2[4] + m1[3] * m2[5] + m1[5]];
+  };
+
+  Util.applyTransform = function Util_applyTransform(p, m) {
+    var xt = p[0] * m[0] + p[1] * m[2] + m[4];
+    var yt = p[0] * m[1] + p[1] * m[3] + m[5];
+    return [xt, yt];
+  };
+
+  Util.applyInverseTransform = function Util_applyInverseTransform(p, m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    var xt = (p[0] * m[3] - p[1] * m[2] + m[2] * m[5] - m[4] * m[3]) / d;
+    var yt = (-p[0] * m[1] + p[1] * m[0] + m[4] * m[1] - m[5] * m[0]) / d;
+    return [xt, yt];
+  };
+
+  Util.getAxialAlignedBoundingBox = function Util_getAxialAlignedBoundingBox(r, m) {
+    var p1 = Util.applyTransform(r, m);
+    var p2 = Util.applyTransform(r.slice(2, 4), m);
+    var p3 = Util.applyTransform([r[0], r[3]], m);
+    var p4 = Util.applyTransform([r[2], r[1]], m);
+    return [Math.min(p1[0], p2[0], p3[0], p4[0]), Math.min(p1[1], p2[1], p3[1], p4[1]), Math.max(p1[0], p2[0], p3[0], p4[0]), Math.max(p1[1], p2[1], p3[1], p4[1])];
+  };
+
+  Util.inverseTransform = function Util_inverseTransform(m) {
+    var d = m[0] * m[3] - m[1] * m[2];
+    return [m[3] / d, -m[1] / d, -m[2] / d, m[0] / d, (m[2] * m[5] - m[4] * m[3]) / d, (m[4] * m[1] - m[5] * m[0]) / d];
+  };
+
+  Util.apply3dTransform = function Util_apply3dTransform(m, v) {
+    return [m[0] * v[0] + m[1] * v[1] + m[2] * v[2], m[3] * v[0] + m[4] * v[1] + m[5] * v[2], m[6] * v[0] + m[7] * v[1] + m[8] * v[2]];
+  };
+
+  Util.singularValueDecompose2dScale = function Util_singularValueDecompose2dScale(m) {
+    var transpose = [m[0], m[2], m[1], m[3]];
+    var a = m[0] * transpose[0] + m[1] * transpose[2];
+    var b = m[0] * transpose[1] + m[1] * transpose[3];
+    var c = m[2] * transpose[0] + m[3] * transpose[2];
+    var d = m[2] * transpose[1] + m[3] * transpose[3];
+    var first = (a + d) / 2;
+    var second = Math.sqrt((a + d) * (a + d) - 4 * (a * d - c * b)) / 2;
+    var sx = first + second || 1;
+    var sy = first - second || 1;
+    return [Math.sqrt(sx), Math.sqrt(sy)];
+  };
+
+  Util.normalizeRect = function Util_normalizeRect(rect) {
+    var r = rect.slice(0);
+
+    if (rect[0] > rect[2]) {
+      r[0] = rect[2];
+      r[2] = rect[0];
+    }
+
+    if (rect[1] > rect[3]) {
+      r[1] = rect[3];
+      r[3] = rect[1];
+    }
+
+    return r;
+  };
+
+  Util.intersect = function Util_intersect(rect1, rect2) {
+    function compare(a, b) {
+      return a - b;
+    }
+
+    var orderedX = [rect1[0], rect1[2], rect2[0], rect2[2]].sort(compare),
+        orderedY = [rect1[1], rect1[3], rect2[1], rect2[3]].sort(compare),
+        result = [];
+    rect1 = Util.normalizeRect(rect1);
+    rect2 = Util.normalizeRect(rect2);
+
+    if (orderedX[0] === rect1[0] && orderedX[1] === rect2[0] || orderedX[0] === rect2[0] && orderedX[1] === rect1[0]) {
+      result[0] = orderedX[1];
+      result[2] = orderedX[2];
+    } else {
+      return false;
+    }
+
+    if (orderedY[0] === rect1[1] && orderedY[1] === rect2[1] || orderedY[0] === rect2[1] && orderedY[1] === rect1[1]) {
+      result[1] = orderedY[1];
+      result[3] = orderedY[2];
+    } else {
+      return false;
+    }
+
+    return result;
+  };
+
+  return Util;
+}();
+
+exports.Util = Util;
+var PDFStringTranslateTable = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2D8, 0x2C7, 0x2C6, 0x2D9, 0x2DD, 0x2DB, 0x2DA, 0x2DC, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x2022, 0x2020, 0x2021, 0x2026, 0x2014, 0x2013, 0x192, 0x2044, 0x2039, 0x203A, 0x2212, 0x2030, 0x201E, 0x201C, 0x201D, 0x2018, 0x2019, 0x201A, 0x2122, 0xFB01, 0xFB02, 0x141, 0x152, 0x160, 0x178, 0x17D, 0x131, 0x142, 0x153, 0x161, 0x17E, 0, 0x20AC];
+
+function stringToPDFString(str) {
+  var i,
+      n = str.length,
+      strBuf = [];
+
+  if (str[0] === '\xFE' && str[1] === '\xFF') {
+    for (i = 2; i < n; i += 2) {
+      strBuf.push(String.fromCharCode(str.charCodeAt(i) << 8 | str.charCodeAt(i + 1)));
+    }
+  } else {
+    for (i = 0; i < n; ++i) {
+      var code = PDFStringTranslateTable[str.charCodeAt(i)];
+      strBuf.push(code ? String.fromCharCode(code) : str.charAt(i));
+    }
+  }
+
+  return strBuf.join('');
+}
+
+function stringToUTF8String(str) {
+  return decodeURIComponent(escape(str));
+}
+
+function utf8StringToString(str) {
+  return unescape(encodeURIComponent(str));
+}
+
+function isEmptyObj(obj) {
+  for (var key in obj) {
+    return false;
+  }
+
+  return true;
+}
+
+function isBool(v) {
+  return typeof v === 'boolean';
+}
+
+function isNum(v) {
+  return typeof v === 'number';
+}
+
+function isString(v) {
+  return typeof v === 'string';
+}
+
+function isArrayBuffer(v) {
+  return _typeof(v) === 'object' && v !== null && v.byteLength !== undefined;
+}
+
+function isArrayEqual(arr1, arr2) {
+  if (arr1.length !== arr2.length) {
+    return false;
+  }
+
+  return arr1.every(function (element, index) {
+    return element === arr2[index];
+  });
+}
+
+function isSpace(ch) {
+  return ch === 0x20 || ch === 0x09 || ch === 0x0D || ch === 0x0A;
+}
+
+function createPromiseCapability() {
+  var capability = Object.create(null);
+  var isSettled = false;
+  Object.defineProperty(capability, 'settled', {
+    get: function get() {
+      return isSettled;
+    }
+  });
+  capability.promise = new Promise(function (resolve, reject) {
+    capability.resolve = function (data) {
+      isSettled = true;
+      resolve(data);
+    };
+
+    capability.reject = function (reason) {
+      isSettled = true;
+      reject(reason);
+    };
+  });
+  return capability;
+}
+
+var createObjectURL = function createObjectURLClosure() {
+  var digits = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
+  return function createObjectURL(data, contentType) {
+    var forceDataSchema = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+
+    if (!forceDataSchema && _url_polyfill.URL.createObjectURL) {
+      var blob = new Blob([data], {
+        type: contentType
+      });
+      return _url_polyfill.URL.createObjectURL(blob);
+    }
+
+    var buffer = 'data:' + contentType + ';base64,';
+
+    for (var i = 0, ii = data.length; i < ii; i += 3) {
+      var b1 = data[i] & 0xFF;
+      var b2 = data[i + 1] & 0xFF;
+      var b3 = data[i + 2] & 0xFF;
+      var d1 = b1 >> 2,
+          d2 = (b1 & 3) << 4 | b2 >> 4;
+      var d3 = i + 1 < ii ? (b2 & 0xF) << 2 | b3 >> 6 : 64;
+      var d4 = i + 2 < ii ? b3 & 0x3F : 64;
+      buffer += digits[d1] + digits[d2] + digits[d3] + digits[d4];
+    }
+
+    return buffer;
+  };
+}();
+
+exports.createObjectURL = createObjectURL;
+
+/***/ }),
+/* 6 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var globalScope = __w_pdfjs_require__(7);
+
+if (!globalScope._pdfjsCompatibilityChecked) {
+  globalScope._pdfjsCompatibilityChecked = true;
+
+  var isNodeJS = __w_pdfjs_require__(8);
+
+  var hasDOM = (typeof window === "undefined" ? "undefined" : _typeof(window)) === 'object' && (typeof document === "undefined" ? "undefined" : _typeof(document)) === 'object';
+
+  (function checkNodeBtoa() {
+    if (globalScope.btoa || !isNodeJS()) {
+      return;
+    }
+
+    globalScope.btoa = function (chars) {
+      return Buffer.from(chars, 'binary').toString('base64');
+    };
+  })();
+
+  (function checkNodeAtob() {
+    if (globalScope.atob || !isNodeJS()) {
+      return;
+    }
+
+    globalScope.atob = function (input) {
+      return Buffer.from(input, 'base64').toString('binary');
+    };
+  })();
+
+  (function checkChildNodeRemove() {
+    if (!hasDOM) {
+      return;
+    }
+
+    if (typeof Element.prototype.remove !== 'undefined') {
+      return;
+    }
+
+    Element.prototype.remove = function () {
+      if (this.parentNode) {
+        this.parentNode.removeChild(this);
+      }
+    };
+  })();
+
+  (function checkDOMTokenListAddRemove() {
+    if (!hasDOM || isNodeJS()) {
+      return;
+    }
+
+    var div = document.createElement('div');
+    div.classList.add('testOne', 'testTwo');
+
+    if (div.classList.contains('testOne') === true && div.classList.contains('testTwo') === true) {
+      return;
+    }
+
+    var OriginalDOMTokenListAdd = DOMTokenList.prototype.add;
+    var OriginalDOMTokenListRemove = DOMTokenList.prototype.remove;
+
+    DOMTokenList.prototype.add = function () {
+      for (var _len = arguments.length, tokens = new Array(_len), _key = 0; _key < _len; _key++) {
+        tokens[_key] = arguments[_key];
+      }
+
+      for (var _i = 0, _tokens = tokens; _i < _tokens.length; _i++) {
+        var token = _tokens[_i];
+        OriginalDOMTokenListAdd.call(this, token);
+      }
+    };
+
+    DOMTokenList.prototype.remove = function () {
+      for (var _len2 = arguments.length, tokens = new Array(_len2), _key2 = 0; _key2 < _len2; _key2++) {
+        tokens[_key2] = arguments[_key2];
+      }
+
+      for (var _i2 = 0, _tokens2 = tokens; _i2 < _tokens2.length; _i2++) {
+        var token = _tokens2[_i2];
+        OriginalDOMTokenListRemove.call(this, token);
+      }
+    };
+  })();
+
+  (function checkDOMTokenListToggle() {
+    if (!hasDOM || isNodeJS()) {
+      return;
+    }
+
+    var div = document.createElement('div');
+
+    if (div.classList.toggle('test', 0) === false) {
+      return;
+    }
+
+    DOMTokenList.prototype.toggle = function (token) {
+      var force = arguments.length > 1 ? !!arguments[1] : !this.contains(token);
+      return this[force ? 'add' : 'remove'](token), force;
+    };
+  })();
+
+  (function checkStringStartsWith() {
+    if (String.prototype.startsWith) {
+      return;
+    }
+
+    __w_pdfjs_require__(9);
+  })();
+
+  (function checkStringEndsWith() {
+    if (String.prototype.endsWith) {
+      return;
+    }
+
+    __w_pdfjs_require__(40);
+  })();
+
+  (function checkStringIncludes() {
+    if (String.prototype.includes) {
+      return;
+    }
+
+    __w_pdfjs_require__(42);
+  })();
+
+  (function checkArrayIncludes() {
+    if (Array.prototype.includes) {
+      return;
+    }
+
+    __w_pdfjs_require__(44);
+  })();
+
+  (function checkArrayFrom() {
+    if (Array.from) {
+      return;
+    }
+
+    __w_pdfjs_require__(51);
+  })();
+
+  (function checkObjectAssign() {
+    if (Object.assign) {
+      return;
+    }
+
+    __w_pdfjs_require__(74);
+  })();
+
+  (function checkMathLog2() {
+    if (Math.log2) {
+      return;
+    }
+
+    Math.log2 = __w_pdfjs_require__(79);
+  })();
+
+  (function checkNumberIsNaN() {
+    if (Number.isNaN) {
+      return;
+    }
+
+    Number.isNaN = __w_pdfjs_require__(81);
+  })();
+
+  (function checkNumberIsInteger() {
+    if (Number.isInteger) {
+      return;
+    }
+
+    Number.isInteger = __w_pdfjs_require__(83);
+  })();
+
+  (function checkPromise() {
+    if (globalScope.Promise && globalScope.Promise.prototype && globalScope.Promise.prototype["finally"]) {
+      return;
+    }
+
+    globalScope.Promise = __w_pdfjs_require__(86);
+  })();
+
+  (function checkWeakMap() {
+    if (globalScope.WeakMap) {
+      return;
+    }
+
+    globalScope.WeakMap = __w_pdfjs_require__(106);
+  })();
+
+  (function checkWeakSet() {
+    if (globalScope.WeakSet) {
+      return;
+    }
+
+    globalScope.WeakSet = __w_pdfjs_require__(123);
+  })();
+
+  (function checkStringCodePointAt() {
+    if (String.codePointAt) {
+      return;
+    }
+
+    String.codePointAt = __w_pdfjs_require__(127);
+  })();
+
+  (function checkStringFromCodePoint() {
+    if (String.fromCodePoint) {
+      return;
+    }
+
+    String.fromCodePoint = __w_pdfjs_require__(129);
+  })();
+
+  (function checkSymbol() {
+    if (globalScope.Symbol) {
+      return;
+    }
+
+    __w_pdfjs_require__(131);
+  })();
+
+  (function checkStringPadStart() {
+    if (String.prototype.padStart) {
+      return;
+    }
+
+    __w_pdfjs_require__(138);
+  })();
+
+  (function checkStringPadEnd() {
+    if (String.prototype.padEnd) {
+      return;
+    }
+
+    __w_pdfjs_require__(142);
+  })();
+
+  (function checkObjectValues() {
+    if (Object.values) {
+      return;
+    }
+
+    Object.values = __w_pdfjs_require__(144);
+  })();
+}
+
+/***/ }),
+/* 7 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = typeof window !== 'undefined' && window.Math === Math ? window : typeof global !== 'undefined' && global.Math === Math ? global : typeof self !== 'undefined' && self.Math === Math ? self : {};
+
+/***/ }),
+/* 8 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+module.exports = function isNodeJS() {
+  return (typeof process === "undefined" ? "undefined" : _typeof(process)) === 'object' && process + '' === '[object process]' && !process.versions['nw'] && !process.versions['electron'];
+};
+
+/***/ }),
+/* 9 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(10);
+
+module.exports = __w_pdfjs_require__(13).String.startsWith;
+
+/***/ }),
+/* 10 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var toLength = __w_pdfjs_require__(32);
+
+var context = __w_pdfjs_require__(34);
+
+var STARTS_WITH = 'startsWith';
+var $startsWith = ''[STARTS_WITH];
+$export($export.P + $export.F * __w_pdfjs_require__(39)(STARTS_WITH), 'String', {
+  startsWith: function startsWith(searchString) {
+    var that = context(this, searchString, STARTS_WITH);
+    var index = toLength(Math.min(arguments.length > 1 ? arguments[1] : undefined, that.length));
+    var search = String(searchString);
+    return $startsWith ? $startsWith.call(that, search, index) : that.slice(index, index + search.length) === search;
+  }
+});
+
+/***/ }),
+/* 11 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var core = __w_pdfjs_require__(13);
+
+var hide = __w_pdfjs_require__(14);
+
+var redefine = __w_pdfjs_require__(24);
+
+var ctx = __w_pdfjs_require__(30);
+
+var PROTOTYPE = 'prototype';
+
+var $export = function $export(type, name, source) {
+  var IS_FORCED = type & $export.F;
+  var IS_GLOBAL = type & $export.G;
+  var IS_STATIC = type & $export.S;
+  var IS_PROTO = type & $export.P;
+  var IS_BIND = type & $export.B;
+  var target = IS_GLOBAL ? global : IS_STATIC ? global[name] || (global[name] = {}) : (global[name] || {})[PROTOTYPE];
+  var exports = IS_GLOBAL ? core : core[name] || (core[name] = {});
+  var expProto = exports[PROTOTYPE] || (exports[PROTOTYPE] = {});
+  var key, own, out, exp;
+  if (IS_GLOBAL) source = name;
+
+  for (key in source) {
+    own = !IS_FORCED && target && target[key] !== undefined;
+    out = (own ? target : source)[key];
+    exp = IS_BIND && own ? ctx(out, global) : IS_PROTO && typeof out == 'function' ? ctx(Function.call, out) : out;
+    if (target) redefine(target, key, out, type & $export.U);
+    if (exports[key] != out) hide(exports, key, exp);
+    if (IS_PROTO && expProto[key] != out) expProto[key] = out;
+  }
+};
+
+global.core = core;
+$export.F = 1;
+$export.G = 2;
+$export.S = 4;
+$export.P = 8;
+$export.B = 16;
+$export.W = 32;
+$export.U = 64;
+$export.R = 128;
+module.exports = $export;
+
+/***/ }),
+/* 12 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = module.exports = typeof window != 'undefined' && window.Math == Math ? window : typeof self != 'undefined' && self.Math == Math ? self : Function('return this')();
+if (typeof __g == 'number') __g = global;
+
+/***/ }),
+/* 13 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var core = module.exports = {
+  version: '2.6.9'
+};
+if (typeof __e == 'number') __e = core;
+
+/***/ }),
+/* 14 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var dP = __w_pdfjs_require__(15);
+
+var createDesc = __w_pdfjs_require__(23);
+
+module.exports = __w_pdfjs_require__(19) ? function (object, key, value) {
+  return dP.f(object, key, createDesc(1, value));
+} : function (object, key, value) {
+  object[key] = value;
+  return object;
+};
+
+/***/ }),
+/* 15 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(16);
+
+var IE8_DOM_DEFINE = __w_pdfjs_require__(18);
+
+var toPrimitive = __w_pdfjs_require__(22);
+
+var dP = Object.defineProperty;
+exports.f = __w_pdfjs_require__(19) ? Object.defineProperty : function defineProperty(O, P, Attributes) {
+  anObject(O);
+  P = toPrimitive(P, true);
+  anObject(Attributes);
+  if (IE8_DOM_DEFINE) try {
+    return dP(O, P, Attributes);
+  } catch (e) {}
+  if ('get' in Attributes || 'set' in Attributes) throw TypeError('Accessors not supported!');
+  if ('value' in Attributes) O[P] = Attributes.value;
+  return O;
+};
+
+/***/ }),
+/* 16 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+module.exports = function (it) {
+  if (!isObject(it)) throw TypeError(it + ' is not an object!');
+  return it;
+};
+
+/***/ }),
+/* 17 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+module.exports = function (it) {
+  return _typeof(it) === 'object' ? it !== null : typeof it === 'function';
+};
+
+/***/ }),
+/* 18 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = !__w_pdfjs_require__(19) && !__w_pdfjs_require__(20)(function () {
+  return Object.defineProperty(__w_pdfjs_require__(21)('div'), 'a', {
+    get: function get() {
+      return 7;
+    }
+  }).a != 7;
+});
+
+/***/ }),
+/* 19 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = !__w_pdfjs_require__(20)(function () {
+  return Object.defineProperty({}, 'a', {
+    get: function get() {
+      return 7;
+    }
+  }).a != 7;
+});
+
+/***/ }),
+/* 20 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (exec) {
+  try {
+    return !!exec();
+  } catch (e) {
+    return true;
+  }
+};
+
+/***/ }),
+/* 21 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var document = __w_pdfjs_require__(12).document;
+
+var is = isObject(document) && isObject(document.createElement);
+
+module.exports = function (it) {
+  return is ? document.createElement(it) : {};
+};
+
+/***/ }),
+/* 22 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+module.exports = function (it, S) {
+  if (!isObject(it)) return it;
+  var fn, val;
+  if (S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
+  if (typeof (fn = it.valueOf) == 'function' && !isObject(val = fn.call(it))) return val;
+  if (!S && typeof (fn = it.toString) == 'function' && !isObject(val = fn.call(it))) return val;
+  throw TypeError("Can't convert object to primitive value");
+};
+
+/***/ }),
+/* 23 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (bitmap, value) {
+  return {
+    enumerable: !(bitmap & 1),
+    configurable: !(bitmap & 2),
+    writable: !(bitmap & 4),
+    value: value
+  };
+};
+
+/***/ }),
+/* 24 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var hide = __w_pdfjs_require__(14);
+
+var has = __w_pdfjs_require__(25);
+
+var SRC = __w_pdfjs_require__(26)('src');
+
+var $toString = __w_pdfjs_require__(27);
+
+var TO_STRING = 'toString';
+var TPL = ('' + $toString).split(TO_STRING);
+
+__w_pdfjs_require__(13).inspectSource = function (it) {
+  return $toString.call(it);
+};
+
+(module.exports = function (O, key, val, safe) {
+  var isFunction = typeof val == 'function';
+  if (isFunction) has(val, 'name') || hide(val, 'name', key);
+  if (O[key] === val) return;
+  if (isFunction) has(val, SRC) || hide(val, SRC, O[key] ? '' + O[key] : TPL.join(String(key)));
+
+  if (O === global) {
+    O[key] = val;
+  } else if (!safe) {
+    delete O[key];
+    hide(O, key, val);
+  } else if (O[key]) {
+    O[key] = val;
+  } else {
+    hide(O, key, val);
+  }
+})(Function.prototype, TO_STRING, function toString() {
+  return typeof this == 'function' && this[SRC] || $toString.call(this);
+});
+
+/***/ }),
+/* 25 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var hasOwnProperty = {}.hasOwnProperty;
+
+module.exports = function (it, key) {
+  return hasOwnProperty.call(it, key);
+};
+
+/***/ }),
+/* 26 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var id = 0;
+var px = Math.random();
+
+module.exports = function (key) {
+  return 'Symbol('.concat(key === undefined ? '' : key, ')_', (++id + px).toString(36));
+};
+
+/***/ }),
+/* 27 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = __w_pdfjs_require__(28)('native-function-to-string', Function.toString);
+
+/***/ }),
+/* 28 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var core = __w_pdfjs_require__(13);
+
+var global = __w_pdfjs_require__(12);
+
+var SHARED = '__core-js_shared__';
+var store = global[SHARED] || (global[SHARED] = {});
+(module.exports = function (key, value) {
+  return store[key] || (store[key] = value !== undefined ? value : {});
+})('versions', []).push({
+  version: core.version,
+  mode: __w_pdfjs_require__(29) ? 'pure' : 'global',
+  copyright: '© 2019 Denis Pushkarev (zloirock.ru)'
+});
+
+/***/ }),
+/* 29 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = false;
+
+/***/ }),
+/* 30 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var aFunction = __w_pdfjs_require__(31);
+
+module.exports = function (fn, that, length) {
+  aFunction(fn);
+  if (that === undefined) return fn;
+
+  switch (length) {
+    case 1:
+      return function (a) {
+        return fn.call(that, a);
+      };
+
+    case 2:
+      return function (a, b) {
+        return fn.call(that, a, b);
+      };
+
+    case 3:
+      return function (a, b, c) {
+        return fn.call(that, a, b, c);
+      };
+  }
+
+  return function () {
+    return fn.apply(that, arguments);
+  };
+};
+
+/***/ }),
+/* 31 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it) {
+  if (typeof it != 'function') throw TypeError(it + ' is not a function!');
+  return it;
+};
+
+/***/ }),
+/* 32 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(33);
+
+var min = Math.min;
+
+module.exports = function (it) {
+  return it > 0 ? min(toInteger(it), 0x1fffffffffffff) : 0;
+};
+
+/***/ }),
+/* 33 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ceil = Math.ceil;
+var floor = Math.floor;
+
+module.exports = function (it) {
+  return isNaN(it = +it) ? 0 : (it > 0 ? floor : ceil)(it);
+};
+
+/***/ }),
+/* 34 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isRegExp = __w_pdfjs_require__(35);
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function (that, searchString, NAME) {
+  if (isRegExp(searchString)) throw TypeError('String#' + NAME + " doesn't accept regex!");
+  return String(defined(that));
+};
+
+/***/ }),
+/* 35 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var cof = __w_pdfjs_require__(36);
+
+var MATCH = __w_pdfjs_require__(37)('match');
+
+module.exports = function (it) {
+  var isRegExp;
+  return isObject(it) && ((isRegExp = it[MATCH]) !== undefined ? !!isRegExp : cof(it) == 'RegExp');
+};
+
+/***/ }),
+/* 36 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toString = {}.toString;
+
+module.exports = function (it) {
+  return toString.call(it).slice(8, -1);
+};
+
+/***/ }),
+/* 37 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var store = __w_pdfjs_require__(28)('wks');
+
+var uid = __w_pdfjs_require__(26);
+
+var _Symbol = __w_pdfjs_require__(12).Symbol;
+
+var USE_SYMBOL = typeof _Symbol == 'function';
+
+var $exports = module.exports = function (name) {
+  return store[name] || (store[name] = USE_SYMBOL && _Symbol[name] || (USE_SYMBOL ? _Symbol : uid)('Symbol.' + name));
+};
+
+$exports.store = store;
+
+/***/ }),
+/* 38 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it) {
+  if (it == undefined) throw TypeError("Can't call method on  " + it);
+  return it;
+};
+
+/***/ }),
+/* 39 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var MATCH = __w_pdfjs_require__(37)('match');
+
+module.exports = function (KEY) {
+  var re = /./;
+
+  try {
+    '/./'[KEY](re);
+  } catch (e) {
+    try {
+      re[MATCH] = false;
+      return !'/./'[KEY](re);
+    } catch (f) {}
+  }
+
+  return true;
+};
+
+/***/ }),
+/* 40 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(41);
+
+module.exports = __w_pdfjs_require__(13).String.endsWith;
+
+/***/ }),
+/* 41 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var toLength = __w_pdfjs_require__(32);
+
+var context = __w_pdfjs_require__(34);
+
+var ENDS_WITH = 'endsWith';
+var $endsWith = ''[ENDS_WITH];
+$export($export.P + $export.F * __w_pdfjs_require__(39)(ENDS_WITH), 'String', {
+  endsWith: function endsWith(searchString) {
+    var that = context(this, searchString, ENDS_WITH);
+    var endPosition = arguments.length > 1 ? arguments[1] : undefined;
+    var len = toLength(that.length);
+    var end = endPosition === undefined ? len : Math.min(toLength(endPosition), len);
+    var search = String(searchString);
+    return $endsWith ? $endsWith.call(that, search, end) : that.slice(end - search.length, end) === search;
+  }
+});
+
+/***/ }),
+/* 42 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(43);
+
+module.exports = __w_pdfjs_require__(13).String.includes;
+
+/***/ }),
+/* 43 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var context = __w_pdfjs_require__(34);
+
+var INCLUDES = 'includes';
+$export($export.P + $export.F * __w_pdfjs_require__(39)(INCLUDES), 'String', {
+  includes: function includes(searchString) {
+    return !!~context(this, searchString, INCLUDES).indexOf(searchString, arguments.length > 1 ? arguments[1] : undefined);
+  }
+});
+
+/***/ }),
+/* 44 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(45);
+
+module.exports = __w_pdfjs_require__(13).Array.includes;
+
+/***/ }),
+/* 45 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var $includes = __w_pdfjs_require__(46)(true);
+
+$export($export.P, 'Array', {
+  includes: function includes(el) {
+    return $includes(this, el, arguments.length > 1 ? arguments[1] : undefined);
+  }
+});
+
+__w_pdfjs_require__(50)('includes');
+
+/***/ }),
+/* 46 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toIObject = __w_pdfjs_require__(47);
+
+var toLength = __w_pdfjs_require__(32);
+
+var toAbsoluteIndex = __w_pdfjs_require__(49);
+
+module.exports = function (IS_INCLUDES) {
+  return function ($this, el, fromIndex) {
+    var O = toIObject($this);
+    var length = toLength(O.length);
+    var index = toAbsoluteIndex(fromIndex, length);
+    var value;
+    if (IS_INCLUDES && el != el) while (length > index) {
+      value = O[index++];
+      if (value != value) return true;
+    } else for (; length > index; index++) {
+      if (IS_INCLUDES || index in O) {
+        if (O[index] === el) return IS_INCLUDES || index || 0;
+      }
+    }
+    return !IS_INCLUDES && -1;
+  };
+};
+
+/***/ }),
+/* 47 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var IObject = __w_pdfjs_require__(48);
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function (it) {
+  return IObject(defined(it));
+};
+
+/***/ }),
+/* 48 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(36);
+
+module.exports = Object('z').propertyIsEnumerable(0) ? Object : function (it) {
+  return cof(it) == 'String' ? it.split('') : Object(it);
+};
+
+/***/ }),
+/* 49 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(33);
+
+var max = Math.max;
+var min = Math.min;
+
+module.exports = function (index, length) {
+  index = toInteger(index);
+  return index < 0 ? max(index + length, 0) : min(index, length);
+};
+
+/***/ }),
+/* 50 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var UNSCOPABLES = __w_pdfjs_require__(37)('unscopables');
+
+var ArrayProto = Array.prototype;
+if (ArrayProto[UNSCOPABLES] == undefined) __w_pdfjs_require__(14)(ArrayProto, UNSCOPABLES, {});
+
+module.exports = function (key) {
+  ArrayProto[UNSCOPABLES][key] = true;
+};
+
+/***/ }),
+/* 51 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(52);
+
+__w_pdfjs_require__(67);
+
+module.exports = __w_pdfjs_require__(13).Array.from;
+
+/***/ }),
+/* 52 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $at = __w_pdfjs_require__(53)(true);
+
+__w_pdfjs_require__(54)(String, 'String', function (iterated) {
+  this._t = String(iterated);
+  this._i = 0;
+}, function () {
+  var O = this._t;
+  var index = this._i;
+  var point;
+  if (index >= O.length) return {
+    value: undefined,
+    done: true
+  };
+  point = $at(O, index);
+  this._i += point.length;
+  return {
+    value: point,
+    done: false
+  };
+});
+
+/***/ }),
+/* 53 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(33);
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function (TO_STRING) {
+  return function (that, pos) {
+    var s = String(defined(that));
+    var i = toInteger(pos);
+    var l = s.length;
+    var a, b;
+    if (i < 0 || i >= l) return TO_STRING ? '' : undefined;
+    a = s.charCodeAt(i);
+    return a < 0xd800 || a > 0xdbff || i + 1 === l || (b = s.charCodeAt(i + 1)) < 0xdc00 || b > 0xdfff ? TO_STRING ? s.charAt(i) : a : TO_STRING ? s.slice(i, i + 2) : (a - 0xd800 << 10) + (b - 0xdc00) + 0x10000;
+  };
+};
+
+/***/ }),
+/* 54 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var LIBRARY = __w_pdfjs_require__(29);
+
+var $export = __w_pdfjs_require__(11);
+
+var redefine = __w_pdfjs_require__(24);
+
+var hide = __w_pdfjs_require__(14);
+
+var Iterators = __w_pdfjs_require__(55);
+
+var $iterCreate = __w_pdfjs_require__(56);
+
+var setToStringTag = __w_pdfjs_require__(64);
+
+var getPrototypeOf = __w_pdfjs_require__(65);
+
+var ITERATOR = __w_pdfjs_require__(37)('iterator');
+
+var BUGGY = !([].keys && 'next' in [].keys());
+var FF_ITERATOR = '@@iterator';
+var KEYS = 'keys';
+var VALUES = 'values';
+
+var returnThis = function returnThis() {
+  return this;
+};
+
+module.exports = function (Base, NAME, Constructor, next, DEFAULT, IS_SET, FORCED) {
+  $iterCreate(Constructor, NAME, next);
+
+  var getMethod = function getMethod(kind) {
+    if (!BUGGY && kind in proto) return proto[kind];
+
+    switch (kind) {
+      case KEYS:
+        return function keys() {
+          return new Constructor(this, kind);
+        };
+
+      case VALUES:
+        return function values() {
+          return new Constructor(this, kind);
+        };
+    }
+
+    return function entries() {
+      return new Constructor(this, kind);
+    };
+  };
+
+  var TAG = NAME + ' Iterator';
+  var DEF_VALUES = DEFAULT == VALUES;
+  var VALUES_BUG = false;
+  var proto = Base.prototype;
+  var $native = proto[ITERATOR] || proto[FF_ITERATOR] || DEFAULT && proto[DEFAULT];
+  var $default = $native || getMethod(DEFAULT);
+  var $entries = DEFAULT ? !DEF_VALUES ? $default : getMethod('entries') : undefined;
+  var $anyNative = NAME == 'Array' ? proto.entries || $native : $native;
+  var methods, key, IteratorPrototype;
+
+  if ($anyNative) {
+    IteratorPrototype = getPrototypeOf($anyNative.call(new Base()));
+
+    if (IteratorPrototype !== Object.prototype && IteratorPrototype.next) {
+      setToStringTag(IteratorPrototype, TAG, true);
+      if (!LIBRARY && typeof IteratorPrototype[ITERATOR] != 'function') hide(IteratorPrototype, ITERATOR, returnThis);
+    }
+  }
+
+  if (DEF_VALUES && $native && $native.name !== VALUES) {
+    VALUES_BUG = true;
+
+    $default = function values() {
+      return $native.call(this);
+    };
+  }
+
+  if ((!LIBRARY || FORCED) && (BUGGY || VALUES_BUG || !proto[ITERATOR])) {
+    hide(proto, ITERATOR, $default);
+  }
+
+  Iterators[NAME] = $default;
+  Iterators[TAG] = returnThis;
+
+  if (DEFAULT) {
+    methods = {
+      values: DEF_VALUES ? $default : getMethod(VALUES),
+      keys: IS_SET ? $default : getMethod(KEYS),
+      entries: $entries
+    };
+    if (FORCED) for (key in methods) {
+      if (!(key in proto)) redefine(proto, key, methods[key]);
+    } else $export($export.P + $export.F * (BUGGY || VALUES_BUG), NAME, methods);
+  }
+
+  return methods;
+};
+
+/***/ }),
+/* 55 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = {};
+
+/***/ }),
+/* 56 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var create = __w_pdfjs_require__(57);
+
+var descriptor = __w_pdfjs_require__(23);
+
+var setToStringTag = __w_pdfjs_require__(64);
+
+var IteratorPrototype = {};
+
+__w_pdfjs_require__(14)(IteratorPrototype, __w_pdfjs_require__(37)('iterator'), function () {
+  return this;
+});
+
+module.exports = function (Constructor, NAME, next) {
+  Constructor.prototype = create(IteratorPrototype, {
+    next: descriptor(1, next)
+  });
+  setToStringTag(Constructor, NAME + ' Iterator');
+};
+
+/***/ }),
+/* 57 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(16);
+
+var dPs = __w_pdfjs_require__(58);
+
+var enumBugKeys = __w_pdfjs_require__(62);
+
+var IE_PROTO = __w_pdfjs_require__(61)('IE_PROTO');
+
+var Empty = function Empty() {};
+
+var PROTOTYPE = 'prototype';
+
+var _createDict = function createDict() {
+  var iframe = __w_pdfjs_require__(21)('iframe');
+
+  var i = enumBugKeys.length;
+  var lt = '<';
+  var gt = '>';
+  var iframeDocument;
+  iframe.style.display = 'none';
+
+  __w_pdfjs_require__(63).appendChild(iframe);
+
+  iframe.src = 'javascript:';
+  iframeDocument = iframe.contentWindow.document;
+  iframeDocument.open();
+  iframeDocument.write(lt + 'script' + gt + 'document.F=Object' + lt + '/script' + gt);
+  iframeDocument.close();
+  _createDict = iframeDocument.F;
+
+  while (i--) {
+    delete _createDict[PROTOTYPE][enumBugKeys[i]];
+  }
+
+  return _createDict();
+};
+
+module.exports = Object.create || function create(O, Properties) {
+  var result;
+
+  if (O !== null) {
+    Empty[PROTOTYPE] = anObject(O);
+    result = new Empty();
+    Empty[PROTOTYPE] = null;
+    result[IE_PROTO] = O;
+  } else result = _createDict();
+
+  return Properties === undefined ? result : dPs(result, Properties);
+};
+
+/***/ }),
+/* 58 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var dP = __w_pdfjs_require__(15);
+
+var anObject = __w_pdfjs_require__(16);
+
+var getKeys = __w_pdfjs_require__(59);
+
+module.exports = __w_pdfjs_require__(19) ? Object.defineProperties : function defineProperties(O, Properties) {
+  anObject(O);
+  var keys = getKeys(Properties);
+  var length = keys.length;
+  var i = 0;
+  var P;
+
+  while (length > i) {
+    dP.f(O, P = keys[i++], Properties[P]);
+  }
+
+  return O;
+};
+
+/***/ }),
+/* 59 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $keys = __w_pdfjs_require__(60);
+
+var enumBugKeys = __w_pdfjs_require__(62);
+
+module.exports = Object.keys || function keys(O) {
+  return $keys(O, enumBugKeys);
+};
+
+/***/ }),
+/* 60 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var has = __w_pdfjs_require__(25);
+
+var toIObject = __w_pdfjs_require__(47);
+
+var arrayIndexOf = __w_pdfjs_require__(46)(false);
+
+var IE_PROTO = __w_pdfjs_require__(61)('IE_PROTO');
+
+module.exports = function (object, names) {
+  var O = toIObject(object);
+  var i = 0;
+  var result = [];
+  var key;
+
+  for (key in O) {
+    if (key != IE_PROTO) has(O, key) && result.push(key);
+  }
+
+  while (names.length > i) {
+    if (has(O, key = names[i++])) {
+      ~arrayIndexOf(result, key) || result.push(key);
+    }
+  }
+
+  return result;
+};
+
+/***/ }),
+/* 61 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var shared = __w_pdfjs_require__(28)('keys');
+
+var uid = __w_pdfjs_require__(26);
+
+module.exports = function (key) {
+  return shared[key] || (shared[key] = uid(key));
+};
+
+/***/ }),
+/* 62 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = 'constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf'.split(',');
+
+/***/ }),
+/* 63 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var document = __w_pdfjs_require__(12).document;
+
+module.exports = document && document.documentElement;
+
+/***/ }),
+/* 64 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var def = __w_pdfjs_require__(15).f;
+
+var has = __w_pdfjs_require__(25);
+
+var TAG = __w_pdfjs_require__(37)('toStringTag');
+
+module.exports = function (it, tag, stat) {
+  if (it && !has(it = stat ? it : it.prototype, TAG)) def(it, TAG, {
+    configurable: true,
+    value: tag
+  });
+};
+
+/***/ }),
+/* 65 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var has = __w_pdfjs_require__(25);
+
+var toObject = __w_pdfjs_require__(66);
+
+var IE_PROTO = __w_pdfjs_require__(61)('IE_PROTO');
+
+var ObjectProto = Object.prototype;
+
+module.exports = Object.getPrototypeOf || function (O) {
+  O = toObject(O);
+  if (has(O, IE_PROTO)) return O[IE_PROTO];
+
+  if (typeof O.constructor == 'function' && O instanceof O.constructor) {
+    return O.constructor.prototype;
+  }
+
+  return O instanceof Object ? ObjectProto : null;
+};
+
+/***/ }),
+/* 66 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function (it) {
+  return Object(defined(it));
+};
+
+/***/ }),
+/* 67 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(30);
+
+var $export = __w_pdfjs_require__(11);
+
+var toObject = __w_pdfjs_require__(66);
+
+var call = __w_pdfjs_require__(68);
+
+var isArrayIter = __w_pdfjs_require__(69);
+
+var toLength = __w_pdfjs_require__(32);
+
+var createProperty = __w_pdfjs_require__(70);
+
+var getIterFn = __w_pdfjs_require__(71);
+
+$export($export.S + $export.F * !__w_pdfjs_require__(73)(function (iter) {
+  Array.from(iter);
+}), 'Array', {
+  from: function from(arrayLike) {
+    var O = toObject(arrayLike);
+    var C = typeof this == 'function' ? this : Array;
+    var aLen = arguments.length;
+    var mapfn = aLen > 1 ? arguments[1] : undefined;
+    var mapping = mapfn !== undefined;
+    var index = 0;
+    var iterFn = getIterFn(O);
+    var length, result, step, iterator;
+    if (mapping) mapfn = ctx(mapfn, aLen > 2 ? arguments[2] : undefined, 2);
+
+    if (iterFn != undefined && !(C == Array && isArrayIter(iterFn))) {
+      for (iterator = iterFn.call(O), result = new C(); !(step = iterator.next()).done; index++) {
+        createProperty(result, index, mapping ? call(iterator, mapfn, [step.value, index], true) : step.value);
+      }
+    } else {
+      length = toLength(O.length);
+
+      for (result = new C(length); length > index; index++) {
+        createProperty(result, index, mapping ? mapfn(O[index], index) : O[index]);
+      }
+    }
+
+    result.length = index;
+    return result;
+  }
+});
+
+/***/ }),
+/* 68 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(16);
+
+module.exports = function (iterator, fn, value, entries) {
+  try {
+    return entries ? fn(anObject(value)[0], value[1]) : fn(value);
+  } catch (e) {
+    var ret = iterator['return'];
+    if (ret !== undefined) anObject(ret.call(iterator));
+    throw e;
+  }
+};
+
+/***/ }),
+/* 69 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var Iterators = __w_pdfjs_require__(55);
+
+var ITERATOR = __w_pdfjs_require__(37)('iterator');
+
+var ArrayProto = Array.prototype;
+
+module.exports = function (it) {
+  return it !== undefined && (Iterators.Array === it || ArrayProto[ITERATOR] === it);
+};
+
+/***/ }),
+/* 70 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $defineProperty = __w_pdfjs_require__(15);
+
+var createDesc = __w_pdfjs_require__(23);
+
+module.exports = function (object, index, value) {
+  if (index in object) $defineProperty.f(object, index, createDesc(0, value));else object[index] = value;
+};
+
+/***/ }),
+/* 71 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var classof = __w_pdfjs_require__(72);
+
+var ITERATOR = __w_pdfjs_require__(37)('iterator');
+
+var Iterators = __w_pdfjs_require__(55);
+
+module.exports = __w_pdfjs_require__(13).getIteratorMethod = function (it) {
+  if (it != undefined) return it[ITERATOR] || it['@@iterator'] || Iterators[classof(it)];
+};
+
+/***/ }),
+/* 72 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(36);
+
+var TAG = __w_pdfjs_require__(37)('toStringTag');
+
+var ARG = cof(function () {
+  return arguments;
+}()) == 'Arguments';
+
+var tryGet = function tryGet(it, key) {
+  try {
+    return it[key];
+  } catch (e) {}
+};
+
+module.exports = function (it) {
+  var O, T, B;
+  return it === undefined ? 'Undefined' : it === null ? 'Null' : typeof (T = tryGet(O = Object(it), TAG)) == 'string' ? T : ARG ? cof(O) : (B = cof(O)) == 'Object' && typeof O.callee == 'function' ? 'Arguments' : B;
+};
+
+/***/ }),
+/* 73 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ITERATOR = __w_pdfjs_require__(37)('iterator');
+
+var SAFE_CLOSING = false;
+
+try {
+  var riter = [7][ITERATOR]();
+
+  riter['return'] = function () {
+    SAFE_CLOSING = true;
+  };
+
+  Array.from(riter, function () {
+    throw 2;
+  });
+} catch (e) {}
+
+module.exports = function (exec, skipClosing) {
+  if (!skipClosing && !SAFE_CLOSING) return false;
+  var safe = false;
+
+  try {
+    var arr = [7];
+    var iter = arr[ITERATOR]();
+
+    iter.next = function () {
+      return {
+        done: safe = true
+      };
+    };
+
+    arr[ITERATOR] = function () {
+      return iter;
+    };
+
+    exec(arr);
+  } catch (e) {}
+
+  return safe;
+};
+
+/***/ }),
+/* 74 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(75);
+
+module.exports = __w_pdfjs_require__(13).Object.assign;
+
+/***/ }),
+/* 75 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+$export($export.S + $export.F, 'Object', {
+  assign: __w_pdfjs_require__(76)
+});
+
+/***/ }),
+/* 76 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var DESCRIPTORS = __w_pdfjs_require__(19);
+
+var getKeys = __w_pdfjs_require__(59);
+
+var gOPS = __w_pdfjs_require__(77);
+
+var pIE = __w_pdfjs_require__(78);
+
+var toObject = __w_pdfjs_require__(66);
+
+var IObject = __w_pdfjs_require__(48);
+
+var $assign = Object.assign;
+module.exports = !$assign || __w_pdfjs_require__(20)(function () {
+  var A = {};
+  var B = {};
+  var S = Symbol();
+  var K = 'abcdefghijklmnopqrst';
+  A[S] = 7;
+  K.split('').forEach(function (k) {
+    B[k] = k;
+  });
+  return $assign({}, A)[S] != 7 || Object.keys($assign({}, B)).join('') != K;
+}) ? function assign(target, source) {
+  var T = toObject(target);
+  var aLen = arguments.length;
+  var index = 1;
+  var getSymbols = gOPS.f;
+  var isEnum = pIE.f;
+
+  while (aLen > index) {
+    var S = IObject(arguments[index++]);
+    var keys = getSymbols ? getKeys(S).concat(getSymbols(S)) : getKeys(S);
+    var length = keys.length;
+    var j = 0;
+    var key;
+
+    while (length > j) {
+      key = keys[j++];
+      if (!DESCRIPTORS || isEnum.call(S, key)) T[key] = S[key];
+    }
+  }
+
+  return T;
+} : $assign;
+
+/***/ }),
+/* 77 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = Object.getOwnPropertySymbols;
+
+/***/ }),
+/* 78 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = {}.propertyIsEnumerable;
+
+/***/ }),
+/* 79 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(80);
+
+module.exports = __w_pdfjs_require__(13).Math.log2;
+
+/***/ }),
+/* 80 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+$export($export.S, 'Math', {
+  log2: function log2(x) {
+    return Math.log(x) / Math.LN2;
+  }
+});
+
+/***/ }),
+/* 81 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(82);
+
+module.exports = __w_pdfjs_require__(13).Number.isNaN;
+
+/***/ }),
+/* 82 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+$export($export.S, 'Number', {
+  isNaN: function isNaN(number) {
+    return number != number;
+  }
+});
+
+/***/ }),
+/* 83 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(84);
+
+module.exports = __w_pdfjs_require__(13).Number.isInteger;
+
+/***/ }),
+/* 84 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+$export($export.S, 'Number', {
+  isInteger: __w_pdfjs_require__(85)
+});
+
+/***/ }),
+/* 85 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var floor = Math.floor;
+
+module.exports = function isInteger(it) {
+  return !isObject(it) && isFinite(it) && floor(it) === it;
+};
+
+/***/ }),
+/* 86 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(87);
+
+__w_pdfjs_require__(52);
+
+__w_pdfjs_require__(88);
+
+__w_pdfjs_require__(91);
+
+__w_pdfjs_require__(104);
+
+__w_pdfjs_require__(105);
+
+module.exports = __w_pdfjs_require__(13).Promise;
+
+/***/ }),
+/* 87 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var classof = __w_pdfjs_require__(72);
+
+var test = {};
+test[__w_pdfjs_require__(37)('toStringTag')] = 'z';
+
+if (test + '' != '[object z]') {
+  __w_pdfjs_require__(24)(Object.prototype, 'toString', function toString() {
+    return '[object ' + classof(this) + ']';
+  }, true);
+}
+
+/***/ }),
+/* 88 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $iterators = __w_pdfjs_require__(89);
+
+var getKeys = __w_pdfjs_require__(59);
+
+var redefine = __w_pdfjs_require__(24);
+
+var global = __w_pdfjs_require__(12);
+
+var hide = __w_pdfjs_require__(14);
+
+var Iterators = __w_pdfjs_require__(55);
+
+var wks = __w_pdfjs_require__(37);
+
+var ITERATOR = wks('iterator');
+var TO_STRING_TAG = wks('toStringTag');
+var ArrayValues = Iterators.Array;
+var DOMIterables = {
+  CSSRuleList: true,
+  CSSStyleDeclaration: false,
+  CSSValueList: false,
+  ClientRectList: false,
+  DOMRectList: false,
+  DOMStringList: false,
+  DOMTokenList: true,
+  DataTransferItemList: false,
+  FileList: false,
+  HTMLAllCollection: false,
+  HTMLCollection: false,
+  HTMLFormElement: false,
+  HTMLSelectElement: false,
+  MediaList: true,
+  MimeTypeArray: false,
+  NamedNodeMap: false,
+  NodeList: true,
+  PaintRequestList: false,
+  Plugin: false,
+  PluginArray: false,
+  SVGLengthList: false,
+  SVGNumberList: false,
+  SVGPathSegList: false,
+  SVGPointList: false,
+  SVGStringList: false,
+  SVGTransformList: false,
+  SourceBufferList: false,
+  StyleSheetList: true,
+  TextTrackCueList: false,
+  TextTrackList: false,
+  TouchList: false
+};
+
+for (var collections = getKeys(DOMIterables), i = 0; i < collections.length; i++) {
+  var NAME = collections[i];
+  var explicit = DOMIterables[NAME];
+  var Collection = global[NAME];
+  var proto = Collection && Collection.prototype;
+  var key;
+
+  if (proto) {
+    if (!proto[ITERATOR]) hide(proto, ITERATOR, ArrayValues);
+    if (!proto[TO_STRING_TAG]) hide(proto, TO_STRING_TAG, NAME);
+    Iterators[NAME] = ArrayValues;
+    if (explicit) for (key in $iterators) {
+      if (!proto[key]) redefine(proto, key, $iterators[key], true);
+    }
+  }
+}
+
+/***/ }),
+/* 89 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var addToUnscopables = __w_pdfjs_require__(50);
+
+var step = __w_pdfjs_require__(90);
+
+var Iterators = __w_pdfjs_require__(55);
+
+var toIObject = __w_pdfjs_require__(47);
+
+module.exports = __w_pdfjs_require__(54)(Array, 'Array', function (iterated, kind) {
+  this._t = toIObject(iterated);
+  this._i = 0;
+  this._k = kind;
+}, function () {
+  var O = this._t;
+  var kind = this._k;
+  var index = this._i++;
+
+  if (!O || index >= O.length) {
+    this._t = undefined;
+    return step(1);
+  }
+
+  if (kind == 'keys') return step(0, index);
+  if (kind == 'values') return step(0, O[index]);
+  return step(0, [index, O[index]]);
+}, 'values');
+Iterators.Arguments = Iterators.Array;
+addToUnscopables('keys');
+addToUnscopables('values');
+addToUnscopables('entries');
+
+/***/ }),
+/* 90 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (done, value) {
+  return {
+    value: value,
+    done: !!done
+  };
+};
+
+/***/ }),
+/* 91 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var LIBRARY = __w_pdfjs_require__(29);
+
+var global = __w_pdfjs_require__(12);
+
+var ctx = __w_pdfjs_require__(30);
+
+var classof = __w_pdfjs_require__(72);
+
+var $export = __w_pdfjs_require__(11);
+
+var isObject = __w_pdfjs_require__(17);
+
+var aFunction = __w_pdfjs_require__(31);
+
+var anInstance = __w_pdfjs_require__(92);
+
+var forOf = __w_pdfjs_require__(93);
+
+var speciesConstructor = __w_pdfjs_require__(94);
+
+var task = __w_pdfjs_require__(95).set;
+
+var microtask = __w_pdfjs_require__(97)();
+
+var newPromiseCapabilityModule = __w_pdfjs_require__(98);
+
+var perform = __w_pdfjs_require__(99);
+
+var userAgent = __w_pdfjs_require__(100);
+
+var promiseResolve = __w_pdfjs_require__(101);
+
+var PROMISE = 'Promise';
+var TypeError = global.TypeError;
+var process = global.process;
+var versions = process && process.versions;
+var v8 = versions && versions.v8 || '';
+var $Promise = global[PROMISE];
+var isNode = classof(process) == 'process';
+
+var empty = function empty() {};
+
+var Internal, newGenericPromiseCapability, OwnPromiseCapability, Wrapper;
+var newPromiseCapability = newGenericPromiseCapability = newPromiseCapabilityModule.f;
+var USE_NATIVE = !!function () {
+  try {
+    var promise = $Promise.resolve(1);
+
+    var FakePromise = (promise.constructor = {})[__w_pdfjs_require__(37)('species')] = function (exec) {
+      exec(empty, empty);
+    };
+
+    return (isNode || typeof PromiseRejectionEvent == 'function') && promise.then(empty) instanceof FakePromise && v8.indexOf('6.6') !== 0 && userAgent.indexOf('Chrome/66') === -1;
+  } catch (e) {}
+}();
+
+var isThenable = function isThenable(it) {
+  var then;
+  return isObject(it) && typeof (then = it.then) == 'function' ? then : false;
+};
+
+var notify = function notify(promise, isReject) {
+  if (promise._n) return;
+  promise._n = true;
+  var chain = promise._c;
+  microtask(function () {
+    var value = promise._v;
+    var ok = promise._s == 1;
+    var i = 0;
+
+    var run = function run(reaction) {
+      var handler = ok ? reaction.ok : reaction.fail;
+      var resolve = reaction.resolve;
+      var reject = reaction.reject;
+      var domain = reaction.domain;
+      var result, then, exited;
+
+      try {
+        if (handler) {
+          if (!ok) {
+            if (promise._h == 2) onHandleUnhandled(promise);
+            promise._h = 1;
+          }
+
+          if (handler === true) result = value;else {
+            if (domain) domain.enter();
+            result = handler(value);
+
+            if (domain) {
+              domain.exit();
+              exited = true;
+            }
+          }
+
+          if (result === reaction.promise) {
+            reject(TypeError('Promise-chain cycle'));
+          } else if (then = isThenable(result)) {
+            then.call(result, resolve, reject);
+          } else resolve(result);
+        } else reject(value);
+      } catch (e) {
+        if (domain && !exited) domain.exit();
+        reject(e);
+      }
+    };
+
+    while (chain.length > i) {
+      run(chain[i++]);
+    }
+
+    promise._c = [];
+    promise._n = false;
+    if (isReject && !promise._h) onUnhandled(promise);
+  });
+};
+
+var onUnhandled = function onUnhandled(promise) {
+  task.call(global, function () {
+    var value = promise._v;
+    var unhandled = isUnhandled(promise);
+    var result, handler, console;
+
+    if (unhandled) {
+      result = perform(function () {
+        if (isNode) {
+          process.emit('unhandledRejection', value, promise);
+        } else if (handler = global.onunhandledrejection) {
+          handler({
+            promise: promise,
+            reason: value
+          });
+        } else if ((console = global.console) && console.error) {
+          console.error('Unhandled promise rejection', value);
+        }
+      });
+      promise._h = isNode || isUnhandled(promise) ? 2 : 1;
+    }
+
+    promise._a = undefined;
+    if (unhandled && result.e) throw result.v;
+  });
+};
+
+var isUnhandled = function isUnhandled(promise) {
+  return promise._h !== 1 && (promise._a || promise._c).length === 0;
+};
+
+var onHandleUnhandled = function onHandleUnhandled(promise) {
+  task.call(global, function () {
+    var handler;
+
+    if (isNode) {
+      process.emit('rejectionHandled', promise);
+    } else if (handler = global.onrejectionhandled) {
+      handler({
+        promise: promise,
+        reason: promise._v
+      });
+    }
+  });
+};
+
+var $reject = function $reject(value) {
+  var promise = this;
+  if (promise._d) return;
+  promise._d = true;
+  promise = promise._w || promise;
+  promise._v = value;
+  promise._s = 2;
+  if (!promise._a) promise._a = promise._c.slice();
+  notify(promise, true);
+};
+
+var $resolve = function $resolve(value) {
+  var promise = this;
+  var then;
+  if (promise._d) return;
+  promise._d = true;
+  promise = promise._w || promise;
+
+  try {
+    if (promise === value) throw TypeError("Promise can't be resolved itself");
+
+    if (then = isThenable(value)) {
+      microtask(function () {
+        var wrapper = {
+          _w: promise,
+          _d: false
+        };
+
+        try {
+          then.call(value, ctx($resolve, wrapper, 1), ctx($reject, wrapper, 1));
+        } catch (e) {
+          $reject.call(wrapper, e);
+        }
+      });
+    } else {
+      promise._v = value;
+      promise._s = 1;
+      notify(promise, false);
+    }
+  } catch (e) {
+    $reject.call({
+      _w: promise,
+      _d: false
+    }, e);
+  }
+};
+
+if (!USE_NATIVE) {
+  $Promise = function Promise(executor) {
+    anInstance(this, $Promise, PROMISE, '_h');
+    aFunction(executor);
+    Internal.call(this);
+
+    try {
+      executor(ctx($resolve, this, 1), ctx($reject, this, 1));
+    } catch (err) {
+      $reject.call(this, err);
+    }
+  };
+
+  Internal = function Promise(executor) {
+    this._c = [];
+    this._a = undefined;
+    this._s = 0;
+    this._d = false;
+    this._v = undefined;
+    this._h = 0;
+    this._n = false;
+  };
+
+  Internal.prototype = __w_pdfjs_require__(102)($Promise.prototype, {
+    then: function then(onFulfilled, onRejected) {
+      var reaction = newPromiseCapability(speciesConstructor(this, $Promise));
+      reaction.ok = typeof onFulfilled == 'function' ? onFulfilled : true;
+      reaction.fail = typeof onRejected == 'function' && onRejected;
+      reaction.domain = isNode ? process.domain : undefined;
+
+      this._c.push(reaction);
+
+      if (this._a) this._a.push(reaction);
+      if (this._s) notify(this, false);
+      return reaction.promise;
+    },
+    'catch': function _catch(onRejected) {
+      return this.then(undefined, onRejected);
+    }
+  });
+
+  OwnPromiseCapability = function OwnPromiseCapability() {
+    var promise = new Internal();
+    this.promise = promise;
+    this.resolve = ctx($resolve, promise, 1);
+    this.reject = ctx($reject, promise, 1);
+  };
+
+  newPromiseCapabilityModule.f = newPromiseCapability = function newPromiseCapability(C) {
+    return C === $Promise || C === Wrapper ? new OwnPromiseCapability(C) : newGenericPromiseCapability(C);
+  };
+}
+
+$export($export.G + $export.W + $export.F * !USE_NATIVE, {
+  Promise: $Promise
+});
+
+__w_pdfjs_require__(64)($Promise, PROMISE);
+
+__w_pdfjs_require__(103)(PROMISE);
+
+Wrapper = __w_pdfjs_require__(13)[PROMISE];
+$export($export.S + $export.F * !USE_NATIVE, PROMISE, {
+  reject: function reject(r) {
+    var capability = newPromiseCapability(this);
+    var $$reject = capability.reject;
+    $$reject(r);
+    return capability.promise;
+  }
+});
+$export($export.S + $export.F * (LIBRARY || !USE_NATIVE), PROMISE, {
+  resolve: function resolve(x) {
+    return promiseResolve(LIBRARY && this === Wrapper ? $Promise : this, x);
+  }
+});
+$export($export.S + $export.F * !(USE_NATIVE && __w_pdfjs_require__(73)(function (iter) {
+  $Promise.all(iter)['catch'](empty);
+})), PROMISE, {
+  all: function all(iterable) {
+    var C = this;
+    var capability = newPromiseCapability(C);
+    var resolve = capability.resolve;
+    var reject = capability.reject;
+    var result = perform(function () {
+      var values = [];
+      var index = 0;
+      var remaining = 1;
+      forOf(iterable, false, function (promise) {
+        var $index = index++;
+        var alreadyCalled = false;
+        values.push(undefined);
+        remaining++;
+        C.resolve(promise).then(function (value) {
+          if (alreadyCalled) return;
+          alreadyCalled = true;
+          values[$index] = value;
+          --remaining || resolve(values);
+        }, reject);
+      });
+      --remaining || resolve(values);
+    });
+    if (result.e) reject(result.v);
+    return capability.promise;
+  },
+  race: function race(iterable) {
+    var C = this;
+    var capability = newPromiseCapability(C);
+    var reject = capability.reject;
+    var result = perform(function () {
+      forOf(iterable, false, function (promise) {
+        C.resolve(promise).then(capability.resolve, reject);
+      });
+    });
+    if (result.e) reject(result.v);
+    return capability.promise;
+  }
+});
+
+/***/ }),
+/* 92 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (it, Constructor, name, forbiddenField) {
+  if (!(it instanceof Constructor) || forbiddenField !== undefined && forbiddenField in it) {
+    throw TypeError(name + ': incorrect invocation!');
+  }
+
+  return it;
+};
+
+/***/ }),
+/* 93 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(30);
+
+var call = __w_pdfjs_require__(68);
+
+var isArrayIter = __w_pdfjs_require__(69);
+
+var anObject = __w_pdfjs_require__(16);
+
+var toLength = __w_pdfjs_require__(32);
+
+var getIterFn = __w_pdfjs_require__(71);
+
+var BREAK = {};
+var RETURN = {};
+
+var _exports = module.exports = function (iterable, entries, fn, that, ITERATOR) {
+  var iterFn = ITERATOR ? function () {
+    return iterable;
+  } : getIterFn(iterable);
+  var f = ctx(fn, that, entries ? 2 : 1);
+  var index = 0;
+  var length, step, iterator, result;
+  if (typeof iterFn != 'function') throw TypeError(iterable + ' is not iterable!');
+  if (isArrayIter(iterFn)) for (length = toLength(iterable.length); length > index; index++) {
+    result = entries ? f(anObject(step = iterable[index])[0], step[1]) : f(iterable[index]);
+    if (result === BREAK || result === RETURN) return result;
+  } else for (iterator = iterFn.call(iterable); !(step = iterator.next()).done;) {
+    result = call(iterator, f, step.value, entries);
+    if (result === BREAK || result === RETURN) return result;
+  }
+};
+
+_exports.BREAK = BREAK;
+_exports.RETURN = RETURN;
+
+/***/ }),
+/* 94 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(16);
+
+var aFunction = __w_pdfjs_require__(31);
+
+var SPECIES = __w_pdfjs_require__(37)('species');
+
+module.exports = function (O, D) {
+  var C = anObject(O).constructor;
+  var S;
+  return C === undefined || (S = anObject(C)[SPECIES]) == undefined ? D : aFunction(S);
+};
+
+/***/ }),
+/* 95 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(30);
+
+var invoke = __w_pdfjs_require__(96);
+
+var html = __w_pdfjs_require__(63);
+
+var cel = __w_pdfjs_require__(21);
+
+var global = __w_pdfjs_require__(12);
+
+var process = global.process;
+var setTask = global.setImmediate;
+var clearTask = global.clearImmediate;
+var MessageChannel = global.MessageChannel;
+var Dispatch = global.Dispatch;
+var counter = 0;
+var queue = {};
+var ONREADYSTATECHANGE = 'onreadystatechange';
+var defer, channel, port;
+
+var run = function run() {
+  var id = +this;
+
+  if (queue.hasOwnProperty(id)) {
+    var fn = queue[id];
+    delete queue[id];
+    fn();
+  }
+};
+
+var listener = function listener(event) {
+  run.call(event.data);
+};
+
+if (!setTask || !clearTask) {
+  setTask = function setImmediate(fn) {
+    var args = [];
+    var i = 1;
+
+    while (arguments.length > i) {
+      args.push(arguments[i++]);
+    }
+
+    queue[++counter] = function () {
+      invoke(typeof fn == 'function' ? fn : Function(fn), args);
+    };
+
+    defer(counter);
+    return counter;
+  };
+
+  clearTask = function clearImmediate(id) {
+    delete queue[id];
+  };
+
+  if (__w_pdfjs_require__(36)(process) == 'process') {
+    defer = function defer(id) {
+      process.nextTick(ctx(run, id, 1));
+    };
+  } else if (Dispatch && Dispatch.now) {
+    defer = function defer(id) {
+      Dispatch.now(ctx(run, id, 1));
+    };
+  } else if (MessageChannel) {
+    channel = new MessageChannel();
+    port = channel.port2;
+    channel.port1.onmessage = listener;
+    defer = ctx(port.postMessage, port, 1);
+  } else if (global.addEventListener && typeof postMessage == 'function' && !global.importScripts) {
+    defer = function defer(id) {
+      global.postMessage(id + '', '*');
+    };
+
+    global.addEventListener('message', listener, false);
+  } else if (ONREADYSTATECHANGE in cel('script')) {
+    defer = function defer(id) {
+      html.appendChild(cel('script'))[ONREADYSTATECHANGE] = function () {
+        html.removeChild(this);
+        run.call(id);
+      };
+    };
+  } else {
+    defer = function defer(id) {
+      setTimeout(ctx(run, id, 1), 0);
+    };
+  }
+}
+
+module.exports = {
+  set: setTask,
+  clear: clearTask
+};
+
+/***/ }),
+/* 96 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (fn, args, that) {
+  var un = that === undefined;
+
+  switch (args.length) {
+    case 0:
+      return un ? fn() : fn.call(that);
+
+    case 1:
+      return un ? fn(args[0]) : fn.call(that, args[0]);
+
+    case 2:
+      return un ? fn(args[0], args[1]) : fn.call(that, args[0], args[1]);
+
+    case 3:
+      return un ? fn(args[0], args[1], args[2]) : fn.call(that, args[0], args[1], args[2]);
+
+    case 4:
+      return un ? fn(args[0], args[1], args[2], args[3]) : fn.call(that, args[0], args[1], args[2], args[3]);
+  }
+
+  return fn.apply(that, args);
+};
+
+/***/ }),
+/* 97 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var macrotask = __w_pdfjs_require__(95).set;
+
+var Observer = global.MutationObserver || global.WebKitMutationObserver;
+var process = global.process;
+var Promise = global.Promise;
+var isNode = __w_pdfjs_require__(36)(process) == 'process';
+
+module.exports = function () {
+  var head, last, notify;
+
+  var flush = function flush() {
+    var parent, fn;
+    if (isNode && (parent = process.domain)) parent.exit();
+
+    while (head) {
+      fn = head.fn;
+      head = head.next;
+
+      try {
+        fn();
+      } catch (e) {
+        if (head) notify();else last = undefined;
+        throw e;
+      }
+    }
+
+    last = undefined;
+    if (parent) parent.enter();
+  };
+
+  if (isNode) {
+    notify = function notify() {
+      process.nextTick(flush);
+    };
+  } else if (Observer && !(global.navigator && global.navigator.standalone)) {
+    var toggle = true;
+    var node = document.createTextNode('');
+    new Observer(flush).observe(node, {
+      characterData: true
+    });
+
+    notify = function notify() {
+      node.data = toggle = !toggle;
+    };
+  } else if (Promise && Promise.resolve) {
+    var promise = Promise.resolve(undefined);
+
+    notify = function notify() {
+      promise.then(flush);
+    };
+  } else {
+    notify = function notify() {
+      macrotask.call(global, flush);
+    };
+  }
+
+  return function (fn) {
+    var task = {
+      fn: fn,
+      next: undefined
+    };
+    if (last) last.next = task;
+
+    if (!head) {
+      head = task;
+      notify();
+    }
+
+    last = task;
+  };
+};
+
+/***/ }),
+/* 98 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var aFunction = __w_pdfjs_require__(31);
+
+function PromiseCapability(C) {
+  var resolve, reject;
+  this.promise = new C(function ($$resolve, $$reject) {
+    if (resolve !== undefined || reject !== undefined) throw TypeError('Bad Promise constructor');
+    resolve = $$resolve;
+    reject = $$reject;
+  });
+  this.resolve = aFunction(resolve);
+  this.reject = aFunction(reject);
+}
+
+module.exports.f = function (C) {
+  return new PromiseCapability(C);
+};
+
+/***/ }),
+/* 99 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+module.exports = function (exec) {
+  try {
+    return {
+      e: false,
+      v: exec()
+    };
+  } catch (e) {
+    return {
+      e: true,
+      v: e
+    };
+  }
+};
+
+/***/ }),
+/* 100 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var navigator = global.navigator;
+module.exports = navigator && navigator.userAgent || '';
+
+/***/ }),
+/* 101 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var anObject = __w_pdfjs_require__(16);
+
+var isObject = __w_pdfjs_require__(17);
+
+var newPromiseCapability = __w_pdfjs_require__(98);
+
+module.exports = function (C, x) {
+  anObject(C);
+  if (isObject(x) && x.constructor === C) return x;
+  var promiseCapability = newPromiseCapability.f(C);
+  var resolve = promiseCapability.resolve;
+  resolve(x);
+  return promiseCapability.promise;
+};
+
+/***/ }),
+/* 102 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var redefine = __w_pdfjs_require__(24);
+
+module.exports = function (target, src, safe) {
+  for (var key in src) {
+    redefine(target, key, src[key], safe);
+  }
+
+  return target;
+};
+
+/***/ }),
+/* 103 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var dP = __w_pdfjs_require__(15);
+
+var DESCRIPTORS = __w_pdfjs_require__(19);
+
+var SPECIES = __w_pdfjs_require__(37)('species');
+
+module.exports = function (KEY) {
+  var C = global[KEY];
+  if (DESCRIPTORS && C && !C[SPECIES]) dP.f(C, SPECIES, {
+    configurable: true,
+    get: function get() {
+      return this;
+    }
+  });
+};
+
+/***/ }),
+/* 104 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var core = __w_pdfjs_require__(13);
+
+var global = __w_pdfjs_require__(12);
+
+var speciesConstructor = __w_pdfjs_require__(94);
+
+var promiseResolve = __w_pdfjs_require__(101);
+
+$export($export.P + $export.R, 'Promise', {
+  'finally': function _finally(onFinally) {
+    var C = speciesConstructor(this, core.Promise || global.Promise);
+    var isFunction = typeof onFinally == 'function';
+    return this.then(isFunction ? function (x) {
+      return promiseResolve(C, onFinally()).then(function () {
+        return x;
+      });
+    } : onFinally, isFunction ? function (e) {
+      return promiseResolve(C, onFinally()).then(function () {
+        throw e;
+      });
+    } : onFinally);
+  }
+});
+
+/***/ }),
+/* 105 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var newPromiseCapability = __w_pdfjs_require__(98);
+
+var perform = __w_pdfjs_require__(99);
+
+$export($export.S, 'Promise', {
+  'try': function _try(callbackfn) {
+    var promiseCapability = newPromiseCapability.f(this);
+    var result = perform(callbackfn);
+    (result.e ? promiseCapability.reject : promiseCapability.resolve)(result.v);
+    return promiseCapability.promise;
+  }
+});
+
+/***/ }),
+/* 106 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(87);
+
+__w_pdfjs_require__(88);
+
+__w_pdfjs_require__(107);
+
+__w_pdfjs_require__(119);
+
+__w_pdfjs_require__(121);
+
+module.exports = __w_pdfjs_require__(13).WeakMap;
+
+/***/ }),
+/* 107 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var each = __w_pdfjs_require__(108)(0);
+
+var redefine = __w_pdfjs_require__(24);
+
+var meta = __w_pdfjs_require__(112);
+
+var assign = __w_pdfjs_require__(76);
+
+var weak = __w_pdfjs_require__(113);
+
+var isObject = __w_pdfjs_require__(17);
+
+var validate = __w_pdfjs_require__(114);
+
+var NATIVE_WEAK_MAP = __w_pdfjs_require__(114);
+
+var IS_IE11 = !global.ActiveXObject && 'ActiveXObject' in global;
+var WEAK_MAP = 'WeakMap';
+var getWeak = meta.getWeak;
+var isExtensible = Object.isExtensible;
+var uncaughtFrozenStore = weak.ufstore;
+var InternalMap;
+
+var wrapper = function wrapper(get) {
+  return function WeakMap() {
+    return get(this, arguments.length > 0 ? arguments[0] : undefined);
+  };
+};
+
+var methods = {
+  get: function get(key) {
+    if (isObject(key)) {
+      var data = getWeak(key);
+      if (data === true) return uncaughtFrozenStore(validate(this, WEAK_MAP)).get(key);
+      return data ? data[this._i] : undefined;
+    }
+  },
+  set: function set(key, value) {
+    return weak.def(validate(this, WEAK_MAP), key, value);
+  }
+};
+
+var $WeakMap = module.exports = __w_pdfjs_require__(115)(WEAK_MAP, wrapper, methods, weak, true, true);
+
+if (NATIVE_WEAK_MAP && IS_IE11) {
+  InternalMap = weak.getConstructor(wrapper, WEAK_MAP);
+  assign(InternalMap.prototype, methods);
+  meta.NEED = true;
+  each(['delete', 'has', 'get', 'set'], function (key) {
+    var proto = $WeakMap.prototype;
+    var method = proto[key];
+    redefine(proto, key, function (a, b) {
+      if (isObject(a) && !isExtensible(a)) {
+        if (!this._f) this._f = new InternalMap();
+
+        var result = this._f[key](a, b);
+
+        return key == 'set' ? this : result;
+      }
+
+      return method.call(this, a, b);
+    });
+  });
+}
+
+/***/ }),
+/* 108 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var ctx = __w_pdfjs_require__(30);
+
+var IObject = __w_pdfjs_require__(48);
+
+var toObject = __w_pdfjs_require__(66);
+
+var toLength = __w_pdfjs_require__(32);
+
+var asc = __w_pdfjs_require__(109);
+
+module.exports = function (TYPE, $create) {
+  var IS_MAP = TYPE == 1;
+  var IS_FILTER = TYPE == 2;
+  var IS_SOME = TYPE == 3;
+  var IS_EVERY = TYPE == 4;
+  var IS_FIND_INDEX = TYPE == 6;
+  var NO_HOLES = TYPE == 5 || IS_FIND_INDEX;
+  var create = $create || asc;
+  return function ($this, callbackfn, that) {
+    var O = toObject($this);
+    var self = IObject(O);
+    var f = ctx(callbackfn, that, 3);
+    var length = toLength(self.length);
+    var index = 0;
+    var result = IS_MAP ? create($this, length) : IS_FILTER ? create($this, 0) : undefined;
+    var val, res;
+
+    for (; length > index; index++) {
+      if (NO_HOLES || index in self) {
+        val = self[index];
+        res = f(val, index, O);
+
+        if (TYPE) {
+          if (IS_MAP) result[index] = res;else if (res) switch (TYPE) {
+            case 3:
+              return true;
+
+            case 5:
+              return val;
+
+            case 6:
+              return index;
+
+            case 2:
+              result.push(val);
+          } else if (IS_EVERY) return false;
+        }
+      }
+    }
+
+    return IS_FIND_INDEX ? -1 : IS_SOME || IS_EVERY ? IS_EVERY : result;
+  };
+};
+
+/***/ }),
+/* 109 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var speciesConstructor = __w_pdfjs_require__(110);
+
+module.exports = function (original, length) {
+  return new (speciesConstructor(original))(length);
+};
+
+/***/ }),
+/* 110 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var isArray = __w_pdfjs_require__(111);
+
+var SPECIES = __w_pdfjs_require__(37)('species');
+
+module.exports = function (original) {
+  var C;
+
+  if (isArray(original)) {
+    C = original.constructor;
+    if (typeof C == 'function' && (C === Array || isArray(C.prototype))) C = undefined;
+
+    if (isObject(C)) {
+      C = C[SPECIES];
+      if (C === null) C = undefined;
+    }
+  }
+
+  return C === undefined ? Array : C;
+};
+
+/***/ }),
+/* 111 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var cof = __w_pdfjs_require__(36);
+
+module.exports = Array.isArray || function isArray(arg) {
+  return cof(arg) == 'Array';
+};
+
+/***/ }),
+/* 112 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var META = __w_pdfjs_require__(26)('meta');
+
+var isObject = __w_pdfjs_require__(17);
+
+var has = __w_pdfjs_require__(25);
+
+var setDesc = __w_pdfjs_require__(15).f;
+
+var id = 0;
+
+var isExtensible = Object.isExtensible || function () {
+  return true;
+};
+
+var FREEZE = !__w_pdfjs_require__(20)(function () {
+  return isExtensible(Object.preventExtensions({}));
+});
+
+var setMeta = function setMeta(it) {
+  setDesc(it, META, {
+    value: {
+      i: 'O' + ++id,
+      w: {}
+    }
+  });
+};
+
+var fastKey = function fastKey(it, create) {
+  if (!isObject(it)) return _typeof(it) == 'symbol' ? it : (typeof it == 'string' ? 'S' : 'P') + it;
+
+  if (!has(it, META)) {
+    if (!isExtensible(it)) return 'F';
+    if (!create) return 'E';
+    setMeta(it);
+  }
+
+  return it[META].i;
+};
+
+var getWeak = function getWeak(it, create) {
+  if (!has(it, META)) {
+    if (!isExtensible(it)) return true;
+    if (!create) return false;
+    setMeta(it);
+  }
+
+  return it[META].w;
+};
+
+var onFreeze = function onFreeze(it) {
+  if (FREEZE && meta.NEED && isExtensible(it) && !has(it, META)) setMeta(it);
+  return it;
+};
+
+var meta = module.exports = {
+  KEY: META,
+  NEED: false,
+  fastKey: fastKey,
+  getWeak: getWeak,
+  onFreeze: onFreeze
+};
+
+/***/ }),
+/* 113 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var redefineAll = __w_pdfjs_require__(102);
+
+var getWeak = __w_pdfjs_require__(112).getWeak;
+
+var anObject = __w_pdfjs_require__(16);
+
+var isObject = __w_pdfjs_require__(17);
+
+var anInstance = __w_pdfjs_require__(92);
+
+var forOf = __w_pdfjs_require__(93);
+
+var createArrayMethod = __w_pdfjs_require__(108);
+
+var $has = __w_pdfjs_require__(25);
+
+var validate = __w_pdfjs_require__(114);
+
+var arrayFind = createArrayMethod(5);
+var arrayFindIndex = createArrayMethod(6);
+var id = 0;
+
+var uncaughtFrozenStore = function uncaughtFrozenStore(that) {
+  return that._l || (that._l = new UncaughtFrozenStore());
+};
+
+var UncaughtFrozenStore = function UncaughtFrozenStore() {
+  this.a = [];
+};
+
+var findUncaughtFrozen = function findUncaughtFrozen(store, key) {
+  return arrayFind(store.a, function (it) {
+    return it[0] === key;
+  });
+};
+
+UncaughtFrozenStore.prototype = {
+  get: function get(key) {
+    var entry = findUncaughtFrozen(this, key);
+    if (entry) return entry[1];
+  },
+  has: function has(key) {
+    return !!findUncaughtFrozen(this, key);
+  },
+  set: function set(key, value) {
+    var entry = findUncaughtFrozen(this, key);
+    if (entry) entry[1] = value;else this.a.push([key, value]);
+  },
+  'delete': function _delete(key) {
+    var index = arrayFindIndex(this.a, function (it) {
+      return it[0] === key;
+    });
+    if (~index) this.a.splice(index, 1);
+    return !!~index;
+  }
+};
+module.exports = {
+  getConstructor: function getConstructor(wrapper, NAME, IS_MAP, ADDER) {
+    var C = wrapper(function (that, iterable) {
+      anInstance(that, C, NAME, '_i');
+      that._t = NAME;
+      that._i = id++;
+      that._l = undefined;
+      if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
+    });
+    redefineAll(C.prototype, {
+      'delete': function _delete(key) {
+        if (!isObject(key)) return false;
+        var data = getWeak(key);
+        if (data === true) return uncaughtFrozenStore(validate(this, NAME))['delete'](key);
+        return data && $has(data, this._i) && delete data[this._i];
+      },
+      has: function has(key) {
+        if (!isObject(key)) return false;
+        var data = getWeak(key);
+        if (data === true) return uncaughtFrozenStore(validate(this, NAME)).has(key);
+        return data && $has(data, this._i);
+      }
+    });
+    return C;
+  },
+  def: function def(that, key, value) {
+    var data = getWeak(anObject(key), true);
+    if (data === true) uncaughtFrozenStore(that).set(key, value);else data[that._i] = value;
+    return that;
+  },
+  ufstore: uncaughtFrozenStore
+};
+
+/***/ }),
+/* 114 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+module.exports = function (it, TYPE) {
+  if (!isObject(it) || it._t !== TYPE) throw TypeError('Incompatible receiver, ' + TYPE + ' required!');
+  return it;
+};
+
+/***/ }),
+/* 115 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var $export = __w_pdfjs_require__(11);
+
+var redefine = __w_pdfjs_require__(24);
+
+var redefineAll = __w_pdfjs_require__(102);
+
+var meta = __w_pdfjs_require__(112);
+
+var forOf = __w_pdfjs_require__(93);
+
+var anInstance = __w_pdfjs_require__(92);
+
+var isObject = __w_pdfjs_require__(17);
+
+var fails = __w_pdfjs_require__(20);
+
+var $iterDetect = __w_pdfjs_require__(73);
+
+var setToStringTag = __w_pdfjs_require__(64);
+
+var inheritIfRequired = __w_pdfjs_require__(116);
+
+module.exports = function (NAME, wrapper, methods, common, IS_MAP, IS_WEAK) {
+  var Base = global[NAME];
+  var C = Base;
+  var ADDER = IS_MAP ? 'set' : 'add';
+  var proto = C && C.prototype;
+  var O = {};
+
+  var fixMethod = function fixMethod(KEY) {
+    var fn = proto[KEY];
+    redefine(proto, KEY, KEY == 'delete' ? function (a) {
+      return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'has' ? function has(a) {
+      return IS_WEAK && !isObject(a) ? false : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'get' ? function get(a) {
+      return IS_WEAK && !isObject(a) ? undefined : fn.call(this, a === 0 ? 0 : a);
+    } : KEY == 'add' ? function add(a) {
+      fn.call(this, a === 0 ? 0 : a);
+      return this;
+    } : function set(a, b) {
+      fn.call(this, a === 0 ? 0 : a, b);
+      return this;
+    });
+  };
+
+  if (typeof C != 'function' || !(IS_WEAK || proto.forEach && !fails(function () {
+    new C().entries().next();
+  }))) {
+    C = common.getConstructor(wrapper, NAME, IS_MAP, ADDER);
+    redefineAll(C.prototype, methods);
+    meta.NEED = true;
+  } else {
+    var instance = new C();
+    var HASNT_CHAINING = instance[ADDER](IS_WEAK ? {} : -0, 1) != instance;
+    var THROWS_ON_PRIMITIVES = fails(function () {
+      instance.has(1);
+    });
+    var ACCEPT_ITERABLES = $iterDetect(function (iter) {
+      new C(iter);
+    });
+    var BUGGY_ZERO = !IS_WEAK && fails(function () {
+      var $instance = new C();
+      var index = 5;
+
+      while (index--) {
+        $instance[ADDER](index, index);
+      }
+
+      return !$instance.has(-0);
+    });
+
+    if (!ACCEPT_ITERABLES) {
+      C = wrapper(function (target, iterable) {
+        anInstance(target, C, NAME);
+        var that = inheritIfRequired(new Base(), target, C);
+        if (iterable != undefined) forOf(iterable, IS_MAP, that[ADDER], that);
+        return that;
+      });
+      C.prototype = proto;
+      proto.constructor = C;
+    }
+
+    if (THROWS_ON_PRIMITIVES || BUGGY_ZERO) {
+      fixMethod('delete');
+      fixMethod('has');
+      IS_MAP && fixMethod('get');
+    }
+
+    if (BUGGY_ZERO || HASNT_CHAINING) fixMethod(ADDER);
+    if (IS_WEAK && proto.clear) delete proto.clear;
+  }
+
+  setToStringTag(C, NAME);
+  O[NAME] = C;
+  $export($export.G + $export.W + $export.F * (C != Base), O);
+  if (!IS_WEAK) common.setStrong(C, NAME, IS_MAP);
+  return C;
+};
+
+/***/ }),
+/* 116 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var setPrototypeOf = __w_pdfjs_require__(117).set;
+
+module.exports = function (that, target, C) {
+  var S = target.constructor;
+  var P;
+
+  if (S !== C && typeof S == 'function' && (P = S.prototype) !== C.prototype && isObject(P) && setPrototypeOf) {
+    setPrototypeOf(that, P);
+  }
+
+  return that;
+};
+
+/***/ }),
+/* 117 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var isObject = __w_pdfjs_require__(17);
+
+var anObject = __w_pdfjs_require__(16);
+
+var check = function check(O, proto) {
+  anObject(O);
+  if (!isObject(proto) && proto !== null) throw TypeError(proto + ": can't set as prototype!");
+};
+
+module.exports = {
+  set: Object.setPrototypeOf || ('__proto__' in {} ? function (test, buggy, set) {
+    try {
+      set = __w_pdfjs_require__(30)(Function.call, __w_pdfjs_require__(118).f(Object.prototype, '__proto__').set, 2);
+      set(test, []);
+      buggy = !(test instanceof Array);
+    } catch (e) {
+      buggy = true;
+    }
+
+    return function setPrototypeOf(O, proto) {
+      check(O, proto);
+      if (buggy) O.__proto__ = proto;else set(O, proto);
+      return O;
+    };
+  }({}, false) : undefined),
+  check: check
+};
+
+/***/ }),
+/* 118 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var pIE = __w_pdfjs_require__(78);
+
+var createDesc = __w_pdfjs_require__(23);
+
+var toIObject = __w_pdfjs_require__(47);
+
+var toPrimitive = __w_pdfjs_require__(22);
+
+var has = __w_pdfjs_require__(25);
+
+var IE8_DOM_DEFINE = __w_pdfjs_require__(18);
+
+var gOPD = Object.getOwnPropertyDescriptor;
+exports.f = __w_pdfjs_require__(19) ? gOPD : function getOwnPropertyDescriptor(O, P) {
+  O = toIObject(O);
+  P = toPrimitive(P, true);
+  if (IE8_DOM_DEFINE) try {
+    return gOPD(O, P);
+  } catch (e) {}
+  if (has(O, P)) return createDesc(!pIE.f.call(O, P), O[P]);
+};
+
+/***/ }),
+/* 119 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(120)('WeakMap');
+
+/***/ }),
+/* 120 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+module.exports = function (COLLECTION) {
+  $export($export.S, COLLECTION, {
+    of: function of() {
+      var length = arguments.length;
+      var A = new Array(length);
+
+      while (length--) {
+        A[length] = arguments[length];
+      }
+
+      return new this(A);
+    }
+  });
+};
+
+/***/ }),
+/* 121 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(122)('WeakMap');
+
+/***/ }),
+/* 122 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var aFunction = __w_pdfjs_require__(31);
+
+var ctx = __w_pdfjs_require__(30);
+
+var forOf = __w_pdfjs_require__(93);
+
+module.exports = function (COLLECTION) {
+  $export($export.S, COLLECTION, {
+    from: function from(source) {
+      var mapFn = arguments[1];
+      var mapping, A, n, cb;
+      aFunction(this);
+      mapping = mapFn !== undefined;
+      if (mapping) aFunction(mapFn);
+      if (source == undefined) return new this();
+      A = [];
+
+      if (mapping) {
+        n = 0;
+        cb = ctx(mapFn, arguments[2], 2);
+        forOf(source, false, function (nextItem) {
+          A.push(cb(nextItem, n++));
+        });
+      } else {
+        forOf(source, false, A.push, A);
+      }
+
+      return new this(A);
+    }
+  });
+};
+
+/***/ }),
+/* 123 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(87);
+
+__w_pdfjs_require__(88);
+
+__w_pdfjs_require__(124);
+
+__w_pdfjs_require__(125);
+
+__w_pdfjs_require__(126);
+
+module.exports = __w_pdfjs_require__(13).WeakSet;
+
+/***/ }),
+/* 124 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var weak = __w_pdfjs_require__(113);
+
+var validate = __w_pdfjs_require__(114);
+
+var WEAK_SET = 'WeakSet';
+
+__w_pdfjs_require__(115)(WEAK_SET, function (get) {
+  return function WeakSet() {
+    return get(this, arguments.length > 0 ? arguments[0] : undefined);
+  };
+}, {
+  add: function add(value) {
+    return weak.def(validate(this, WEAK_SET), value, true);
+  }
+}, weak, false, true);
+
+/***/ }),
+/* 125 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(120)('WeakSet');
+
+/***/ }),
+/* 126 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(122)('WeakSet');
+
+/***/ }),
+/* 127 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(128);
+
+module.exports = __w_pdfjs_require__(13).String.codePointAt;
+
+/***/ }),
+/* 128 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var $at = __w_pdfjs_require__(53)(false);
+
+$export($export.P, 'String', {
+  codePointAt: function codePointAt(pos) {
+    return $at(this, pos);
+  }
+});
+
+/***/ }),
+/* 129 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(130);
+
+module.exports = __w_pdfjs_require__(13).String.fromCodePoint;
+
+/***/ }),
+/* 130 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var toAbsoluteIndex = __w_pdfjs_require__(49);
+
+var fromCharCode = String.fromCharCode;
+var $fromCodePoint = String.fromCodePoint;
+$export($export.S + $export.F * (!!$fromCodePoint && $fromCodePoint.length != 1), 'String', {
+  fromCodePoint: function fromCodePoint(x) {
+    var res = [];
+    var aLen = arguments.length;
+    var i = 0;
+    var code;
+
+    while (aLen > i) {
+      code = +arguments[i++];
+      if (toAbsoluteIndex(code, 0x10ffff) !== code) throw RangeError(code + ' is not a valid code point');
+      res.push(code < 0x10000 ? fromCharCode(code) : fromCharCode(((code -= 0x10000) >> 10) + 0xd800, code % 0x400 + 0xdc00));
+    }
+
+    return res.join('');
+  }
+});
+
+/***/ }),
+/* 131 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(132);
+
+__w_pdfjs_require__(87);
+
+module.exports = __w_pdfjs_require__(13).Symbol;
+
+/***/ }),
+/* 132 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var global = __w_pdfjs_require__(12);
+
+var has = __w_pdfjs_require__(25);
+
+var DESCRIPTORS = __w_pdfjs_require__(19);
+
+var $export = __w_pdfjs_require__(11);
+
+var redefine = __w_pdfjs_require__(24);
+
+var META = __w_pdfjs_require__(112).KEY;
+
+var $fails = __w_pdfjs_require__(20);
+
+var shared = __w_pdfjs_require__(28);
+
+var setToStringTag = __w_pdfjs_require__(64);
+
+var uid = __w_pdfjs_require__(26);
+
+var wks = __w_pdfjs_require__(37);
+
+var wksExt = __w_pdfjs_require__(133);
+
+var wksDefine = __w_pdfjs_require__(134);
+
+var enumKeys = __w_pdfjs_require__(135);
+
+var isArray = __w_pdfjs_require__(111);
+
+var anObject = __w_pdfjs_require__(16);
+
+var isObject = __w_pdfjs_require__(17);
+
+var toObject = __w_pdfjs_require__(66);
+
+var toIObject = __w_pdfjs_require__(47);
+
+var toPrimitive = __w_pdfjs_require__(22);
+
+var createDesc = __w_pdfjs_require__(23);
+
+var _create = __w_pdfjs_require__(57);
+
+var gOPNExt = __w_pdfjs_require__(136);
+
+var $GOPD = __w_pdfjs_require__(118);
+
+var $GOPS = __w_pdfjs_require__(77);
+
+var $DP = __w_pdfjs_require__(15);
+
+var $keys = __w_pdfjs_require__(59);
+
+var gOPD = $GOPD.f;
+var dP = $DP.f;
+var gOPN = gOPNExt.f;
+var $Symbol = global.Symbol;
+var $JSON = global.JSON;
+
+var _stringify = $JSON && $JSON.stringify;
+
+var PROTOTYPE = 'prototype';
+var HIDDEN = wks('_hidden');
+var TO_PRIMITIVE = wks('toPrimitive');
+var isEnum = {}.propertyIsEnumerable;
+var SymbolRegistry = shared('symbol-registry');
+var AllSymbols = shared('symbols');
+var OPSymbols = shared('op-symbols');
+var ObjectProto = Object[PROTOTYPE];
+var USE_NATIVE = typeof $Symbol == 'function' && !!$GOPS.f;
+var QObject = global.QObject;
+var setter = !QObject || !QObject[PROTOTYPE] || !QObject[PROTOTYPE].findChild;
+var setSymbolDesc = DESCRIPTORS && $fails(function () {
+  return _create(dP({}, 'a', {
+    get: function get() {
+      return dP(this, 'a', {
+        value: 7
+      }).a;
+    }
+  })).a != 7;
+}) ? function (it, key, D) {
+  var protoDesc = gOPD(ObjectProto, key);
+  if (protoDesc) delete ObjectProto[key];
+  dP(it, key, D);
+  if (protoDesc && it !== ObjectProto) dP(ObjectProto, key, protoDesc);
+} : dP;
+
+var wrap = function wrap(tag) {
+  var sym = AllSymbols[tag] = _create($Symbol[PROTOTYPE]);
+
+  sym._k = tag;
+  return sym;
+};
+
+var isSymbol = USE_NATIVE && _typeof($Symbol.iterator) == 'symbol' ? function (it) {
+  return _typeof(it) == 'symbol';
+} : function (it) {
+  return it instanceof $Symbol;
+};
+
+var $defineProperty = function defineProperty(it, key, D) {
+  if (it === ObjectProto) $defineProperty(OPSymbols, key, D);
+  anObject(it);
+  key = toPrimitive(key, true);
+  anObject(D);
+
+  if (has(AllSymbols, key)) {
+    if (!D.enumerable) {
+      if (!has(it, HIDDEN)) dP(it, HIDDEN, createDesc(1, {}));
+      it[HIDDEN][key] = true;
+    } else {
+      if (has(it, HIDDEN) && it[HIDDEN][key]) it[HIDDEN][key] = false;
+      D = _create(D, {
+        enumerable: createDesc(0, false)
+      });
+    }
+
+    return setSymbolDesc(it, key, D);
+  }
+
+  return dP(it, key, D);
+};
+
+var $defineProperties = function defineProperties(it, P) {
+  anObject(it);
+  var keys = enumKeys(P = toIObject(P));
+  var i = 0;
+  var l = keys.length;
+  var key;
+
+  while (l > i) {
+    $defineProperty(it, key = keys[i++], P[key]);
+  }
+
+  return it;
+};
+
+var $create = function create(it, P) {
+  return P === undefined ? _create(it) : $defineProperties(_create(it), P);
+};
+
+var $propertyIsEnumerable = function propertyIsEnumerable(key) {
+  var E = isEnum.call(this, key = toPrimitive(key, true));
+  if (this === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return false;
+  return E || !has(this, key) || !has(AllSymbols, key) || has(this, HIDDEN) && this[HIDDEN][key] ? E : true;
+};
+
+var $getOwnPropertyDescriptor = function getOwnPropertyDescriptor(it, key) {
+  it = toIObject(it);
+  key = toPrimitive(key, true);
+  if (it === ObjectProto && has(AllSymbols, key) && !has(OPSymbols, key)) return;
+  var D = gOPD(it, key);
+  if (D && has(AllSymbols, key) && !(has(it, HIDDEN) && it[HIDDEN][key])) D.enumerable = true;
+  return D;
+};
+
+var $getOwnPropertyNames = function getOwnPropertyNames(it) {
+  var names = gOPN(toIObject(it));
+  var result = [];
+  var i = 0;
+  var key;
+
+  while (names.length > i) {
+    if (!has(AllSymbols, key = names[i++]) && key != HIDDEN && key != META) result.push(key);
+  }
+
+  return result;
+};
+
+var $getOwnPropertySymbols = function getOwnPropertySymbols(it) {
+  var IS_OP = it === ObjectProto;
+  var names = gOPN(IS_OP ? OPSymbols : toIObject(it));
+  var result = [];
+  var i = 0;
+  var key;
+
+  while (names.length > i) {
+    if (has(AllSymbols, key = names[i++]) && (IS_OP ? has(ObjectProto, key) : true)) result.push(AllSymbols[key]);
+  }
+
+  return result;
+};
+
+if (!USE_NATIVE) {
+  $Symbol = function _Symbol() {
+    if (this instanceof $Symbol) throw TypeError('Symbol is not a constructor!');
+    var tag = uid(arguments.length > 0 ? arguments[0] : undefined);
+
+    var $set = function $set(value) {
+      if (this === ObjectProto) $set.call(OPSymbols, value);
+      if (has(this, HIDDEN) && has(this[HIDDEN], tag)) this[HIDDEN][tag] = false;
+      setSymbolDesc(this, tag, createDesc(1, value));
+    };
+
+    if (DESCRIPTORS && setter) setSymbolDesc(ObjectProto, tag, {
+      configurable: true,
+      set: $set
+    });
+    return wrap(tag);
+  };
+
+  redefine($Symbol[PROTOTYPE], 'toString', function toString() {
+    return this._k;
+  });
+  $GOPD.f = $getOwnPropertyDescriptor;
+  $DP.f = $defineProperty;
+  __w_pdfjs_require__(137).f = gOPNExt.f = $getOwnPropertyNames;
+  __w_pdfjs_require__(78).f = $propertyIsEnumerable;
+  $GOPS.f = $getOwnPropertySymbols;
+
+  if (DESCRIPTORS && !__w_pdfjs_require__(29)) {
+    redefine(ObjectProto, 'propertyIsEnumerable', $propertyIsEnumerable, true);
+  }
+
+  wksExt.f = function (name) {
+    return wrap(wks(name));
+  };
+}
+
+$export($export.G + $export.W + $export.F * !USE_NATIVE, {
+  Symbol: $Symbol
+});
+
+for (var es6Symbols = 'hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables'.split(','), j = 0; es6Symbols.length > j;) {
+  wks(es6Symbols[j++]);
+}
+
+for (var wellKnownSymbols = $keys(wks.store), k = 0; wellKnownSymbols.length > k;) {
+  wksDefine(wellKnownSymbols[k++]);
+}
+
+$export($export.S + $export.F * !USE_NATIVE, 'Symbol', {
+  'for': function _for(key) {
+    return has(SymbolRegistry, key += '') ? SymbolRegistry[key] : SymbolRegistry[key] = $Symbol(key);
+  },
+  keyFor: function keyFor(sym) {
+    if (!isSymbol(sym)) throw TypeError(sym + ' is not a symbol!');
+
+    for (var key in SymbolRegistry) {
+      if (SymbolRegistry[key] === sym) return key;
+    }
+  },
+  useSetter: function useSetter() {
+    setter = true;
+  },
+  useSimple: function useSimple() {
+    setter = false;
+  }
+});
+$export($export.S + $export.F * !USE_NATIVE, 'Object', {
+  create: $create,
+  defineProperty: $defineProperty,
+  defineProperties: $defineProperties,
+  getOwnPropertyDescriptor: $getOwnPropertyDescriptor,
+  getOwnPropertyNames: $getOwnPropertyNames,
+  getOwnPropertySymbols: $getOwnPropertySymbols
+});
+var FAILS_ON_PRIMITIVES = $fails(function () {
+  $GOPS.f(1);
+});
+$export($export.S + $export.F * FAILS_ON_PRIMITIVES, 'Object', {
+  getOwnPropertySymbols: function getOwnPropertySymbols(it) {
+    return $GOPS.f(toObject(it));
+  }
+});
+$JSON && $export($export.S + $export.F * (!USE_NATIVE || $fails(function () {
+  var S = $Symbol();
+  return _stringify([S]) != '[null]' || _stringify({
+    a: S
+  }) != '{}' || _stringify(Object(S)) != '{}';
+})), 'JSON', {
+  stringify: function stringify(it) {
+    var args = [it];
+    var i = 1;
+    var replacer, $replacer;
+
+    while (arguments.length > i) {
+      args.push(arguments[i++]);
+    }
+
+    $replacer = replacer = args[1];
+    if (!isObject(replacer) && it === undefined || isSymbol(it)) return;
+    if (!isArray(replacer)) replacer = function replacer(key, value) {
+      if (typeof $replacer == 'function') value = $replacer.call(this, key, value);
+      if (!isSymbol(value)) return value;
+    };
+    args[1] = replacer;
+    return _stringify.apply($JSON, args);
+  }
+});
+$Symbol[PROTOTYPE][TO_PRIMITIVE] || __w_pdfjs_require__(14)($Symbol[PROTOTYPE], TO_PRIMITIVE, $Symbol[PROTOTYPE].valueOf);
+setToStringTag($Symbol, 'Symbol');
+setToStringTag(Math, 'Math', true);
+setToStringTag(global.JSON, 'JSON', true);
+
+/***/ }),
+/* 133 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+exports.f = __w_pdfjs_require__(37);
+
+/***/ }),
+/* 134 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var global = __w_pdfjs_require__(12);
+
+var core = __w_pdfjs_require__(13);
+
+var LIBRARY = __w_pdfjs_require__(29);
+
+var wksExt = __w_pdfjs_require__(133);
+
+var defineProperty = __w_pdfjs_require__(15).f;
+
+module.exports = function (name) {
+  var $Symbol = core.Symbol || (core.Symbol = LIBRARY ? {} : global.Symbol || {});
+  if (name.charAt(0) != '_' && !(name in $Symbol)) defineProperty($Symbol, name, {
+    value: wksExt.f(name)
+  });
+};
+
+/***/ }),
+/* 135 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var getKeys = __w_pdfjs_require__(59);
+
+var gOPS = __w_pdfjs_require__(77);
+
+var pIE = __w_pdfjs_require__(78);
+
+module.exports = function (it) {
+  var result = getKeys(it);
+  var getSymbols = gOPS.f;
+
+  if (getSymbols) {
+    var symbols = getSymbols(it);
+    var isEnum = pIE.f;
+    var i = 0;
+    var key;
+
+    while (symbols.length > i) {
+      if (isEnum.call(it, key = symbols[i++])) result.push(key);
+    }
+  }
+
+  return result;
+};
+
+/***/ }),
+/* 136 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var toIObject = __w_pdfjs_require__(47);
+
+var gOPN = __w_pdfjs_require__(137).f;
+
+var toString = {}.toString;
+var windowNames = (typeof window === "undefined" ? "undefined" : _typeof(window)) == 'object' && window && Object.getOwnPropertyNames ? Object.getOwnPropertyNames(window) : [];
+
+var getWindowNames = function getWindowNames(it) {
+  try {
+    return gOPN(it);
+  } catch (e) {
+    return windowNames.slice();
+  }
+};
+
+module.exports.f = function getOwnPropertyNames(it) {
+  return windowNames && toString.call(it) == '[object Window]' ? getWindowNames(it) : gOPN(toIObject(it));
+};
+
+/***/ }),
+/* 137 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $keys = __w_pdfjs_require__(60);
+
+var hiddenKeys = __w_pdfjs_require__(62).concat('length', 'prototype');
+
+exports.f = Object.getOwnPropertyNames || function getOwnPropertyNames(O) {
+  return $keys(O, hiddenKeys);
+};
+
+/***/ }),
+/* 138 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(139);
+
+module.exports = __w_pdfjs_require__(13).String.padStart;
+
+/***/ }),
+/* 139 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var $pad = __w_pdfjs_require__(140);
+
+var userAgent = __w_pdfjs_require__(100);
+
+var WEBKIT_BUG = /Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(userAgent);
+$export($export.P + $export.F * WEBKIT_BUG, 'String', {
+  padStart: function padStart(maxLength) {
+    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, true);
+  }
+});
+
+/***/ }),
+/* 140 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toLength = __w_pdfjs_require__(32);
+
+var repeat = __w_pdfjs_require__(141);
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function (that, maxLength, fillString, left) {
+  var S = String(defined(that));
+  var stringLength = S.length;
+  var fillStr = fillString === undefined ? ' ' : String(fillString);
+  var intMaxLength = toLength(maxLength);
+  if (intMaxLength <= stringLength || fillStr == '') return S;
+  var fillLen = intMaxLength - stringLength;
+  var stringFiller = repeat.call(fillStr, Math.ceil(fillLen / fillStr.length));
+  if (stringFiller.length > fillLen) stringFiller = stringFiller.slice(0, fillLen);
+  return left ? stringFiller + S : S + stringFiller;
+};
+
+/***/ }),
+/* 141 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var toInteger = __w_pdfjs_require__(33);
+
+var defined = __w_pdfjs_require__(38);
+
+module.exports = function repeat(count) {
+  var str = String(defined(this));
+  var res = '';
+  var n = toInteger(count);
+  if (n < 0 || n == Infinity) throw RangeError("Count can't be negative");
+
+  for (; n > 0; (n >>>= 1) && (str += str)) {
+    if (n & 1) res += str;
+  }
+
+  return res;
+};
+
+/***/ }),
+/* 142 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(143);
+
+module.exports = __w_pdfjs_require__(13).String.padEnd;
+
+/***/ }),
+/* 143 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var $pad = __w_pdfjs_require__(140);
+
+var userAgent = __w_pdfjs_require__(100);
+
+var WEBKIT_BUG = /Version\/10\.\d+(\.\d+)?( Mobile\/\w+)? Safari\//.test(userAgent);
+$export($export.P + $export.F * WEBKIT_BUG, 'String', {
+  padEnd: function padEnd(maxLength) {
+    return $pad(this, maxLength, arguments.length > 1 ? arguments[1] : undefined, false);
+  }
+});
+
+/***/ }),
+/* 144 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+__w_pdfjs_require__(145);
+
+module.exports = __w_pdfjs_require__(13).Object.values;
+
+/***/ }),
+/* 145 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var $export = __w_pdfjs_require__(11);
+
+var $values = __w_pdfjs_require__(146)(false);
+
+$export($export.S, 'Object', {
+  values: function values(it) {
+    return $values(it);
+  }
+});
+
+/***/ }),
+/* 146 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+var DESCRIPTORS = __w_pdfjs_require__(19);
+
+var getKeys = __w_pdfjs_require__(59);
+
+var toIObject = __w_pdfjs_require__(47);
+
+var isEnum = __w_pdfjs_require__(78).f;
+
+module.exports = function (isEntries) {
+  return function (it) {
+    var O = toIObject(it);
+    var keys = getKeys(O);
+    var length = keys.length;
+    var i = 0;
+    var result = [];
+    var key;
+
+    while (length > i) {
+      key = keys[i++];
+
+      if (!DESCRIPTORS || isEnum.call(O, key)) {
+        result.push(isEntries ? [key, O[key]] : O[key]);
+      }
+    }
+
+    return result;
+  };
+};
+
+/***/ }),
+/* 147 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+{
+  var isReadableStreamSupported = false;
+
+  if (typeof ReadableStream !== 'undefined') {
+    try {
+      new ReadableStream({
+        start: function start(controller) {
+          controller.close();
+        }
+      });
+      isReadableStreamSupported = true;
+    } catch (e) {}
+  }
+
+  if (isReadableStreamSupported) {
+    exports.ReadableStream = ReadableStream;
+  } else {
+    exports.ReadableStream = __w_pdfjs_require__(148).ReadableStream;
+  }
+}
+
+/***/ }),
+/* 148 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof2(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof2 = function _typeof2(obj) { return typeof obj; }; } else { _typeof2 = function _typeof2(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof2(obj); }
+
+(function (e, a) {
+  for (var i in a) {
+    e[i] = a[i];
+  }
+})(exports, function (modules) {
+  var installedModules = {};
+
+  function __w_pdfjs_require__(moduleId) {
+    if (installedModules[moduleId]) return installedModules[moduleId].exports;
+    var module = installedModules[moduleId] = {
+      i: moduleId,
+      l: false,
+      exports: {}
+    };
+    modules[moduleId].call(module.exports, module, module.exports, __w_pdfjs_require__);
+    module.l = true;
+    return module.exports;
+  }
+
+  __w_pdfjs_require__.m = modules;
+  __w_pdfjs_require__.c = installedModules;
+
+  __w_pdfjs_require__.i = function (value) {
+    return value;
+  };
+
+  __w_pdfjs_require__.d = function (exports, name, getter) {
+    if (!__w_pdfjs_require__.o(exports, name)) {
+      Object.defineProperty(exports, name, {
+        configurable: false,
+        enumerable: true,
+        get: getter
+      });
+    }
+  };
+
+  __w_pdfjs_require__.n = function (module) {
+    var getter = module && module.__esModule ? function getDefault() {
+      return module['default'];
+    } : function getModuleExports() {
+      return module;
+    };
+
+    __w_pdfjs_require__.d(getter, 'a', getter);
+
+    return getter;
+  };
+
+  __w_pdfjs_require__.o = function (object, property) {
+    return Object.prototype.hasOwnProperty.call(object, property);
+  };
+
+  __w_pdfjs_require__.p = "";
+  return __w_pdfjs_require__(__w_pdfjs_require__.s = 7);
+}([function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _typeof = typeof Symbol === "function" && _typeof2(Symbol.iterator) === "symbol" ? function (obj) {
+    return _typeof2(obj);
+  } : function (obj) {
+    return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : _typeof2(obj);
+  };
+
+  var _require = __w_pdfjs_require__(1),
+      assert = _require.assert;
+
+  function IsPropertyKey(argument) {
+    return typeof argument === 'string' || (typeof argument === 'undefined' ? 'undefined' : _typeof(argument)) === 'symbol';
+  }
+
+  exports.typeIsObject = function (x) {
+    return (typeof x === 'undefined' ? 'undefined' : _typeof(x)) === 'object' && x !== null || typeof x === 'function';
+  };
+
+  exports.createDataProperty = function (o, p, v) {
+    assert(exports.typeIsObject(o));
+    Object.defineProperty(o, p, {
+      value: v,
+      writable: true,
+      enumerable: true,
+      configurable: true
+    });
+  };
+
+  exports.createArrayFromList = function (elements) {
+    return elements.slice();
+  };
+
+  exports.ArrayBufferCopy = function (dest, destOffset, src, srcOffset, n) {
+    new Uint8Array(dest).set(new Uint8Array(src, srcOffset, n), destOffset);
+  };
+
+  exports.CreateIterResultObject = function (value, done) {
+    assert(typeof done === 'boolean');
+    var obj = {};
+    Object.defineProperty(obj, 'value', {
+      value: value,
+      enumerable: true,
+      writable: true,
+      configurable: true
+    });
+    Object.defineProperty(obj, 'done', {
+      value: done,
+      enumerable: true,
+      writable: true,
+      configurable: true
+    });
+    return obj;
+  };
+
+  exports.IsFiniteNonNegativeNumber = function (v) {
+    if (Number.isNaN(v)) {
+      return false;
+    }
+
+    if (v === Infinity) {
+      return false;
+    }
+
+    if (v < 0) {
+      return false;
+    }
+
+    return true;
+  };
+
+  function Call(F, V, args) {
+    if (typeof F !== 'function') {
+      throw new TypeError('Argument is not a function');
+    }
+
+    return Function.prototype.apply.call(F, V, args);
+  }
+
+  exports.InvokeOrNoop = function (O, P, args) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+    var method = O[P];
+
+    if (method === undefined) {
+      return undefined;
+    }
+
+    return Call(method, O, args);
+  };
+
+  exports.PromiseInvokeOrNoop = function (O, P, args) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+
+    try {
+      return Promise.resolve(exports.InvokeOrNoop(O, P, args));
+    } catch (returnValueE) {
+      return Promise.reject(returnValueE);
+    }
+  };
+
+  exports.PromiseInvokeOrPerformFallback = function (O, P, args, F, argsF) {
+    assert(O !== undefined);
+    assert(IsPropertyKey(P));
+    assert(Array.isArray(args));
+    assert(Array.isArray(argsF));
+    var method = void 0;
+
+    try {
+      method = O[P];
+    } catch (methodE) {
+      return Promise.reject(methodE);
+    }
+
+    if (method === undefined) {
+      return F.apply(null, argsF);
+    }
+
+    try {
+      return Promise.resolve(Call(method, O, args));
+    } catch (e) {
+      return Promise.reject(e);
+    }
+  };
+
+  exports.TransferArrayBuffer = function (O) {
+    return O.slice();
+  };
+
+  exports.ValidateAndNormalizeHighWaterMark = function (highWaterMark) {
+    highWaterMark = Number(highWaterMark);
+
+    if (Number.isNaN(highWaterMark) || highWaterMark < 0) {
+      throw new RangeError('highWaterMark property of a queuing strategy must be non-negative and non-NaN');
+    }
+
+    return highWaterMark;
+  };
+
+  exports.ValidateAndNormalizeQueuingStrategy = function (size, highWaterMark) {
+    if (size !== undefined && typeof size !== 'function') {
+      throw new TypeError('size property of a queuing strategy must be a function');
+    }
+
+    highWaterMark = exports.ValidateAndNormalizeHighWaterMark(highWaterMark);
+    return {
+      size: size,
+      highWaterMark: highWaterMark
+    };
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  function rethrowAssertionErrorRejection(e) {
+    if (e && e.constructor === AssertionError) {
+      setTimeout(function () {
+        throw e;
+      }, 0);
+    }
+  }
+
+  function AssertionError(message) {
+    this.name = 'AssertionError';
+    this.message = message || '';
+    this.stack = new Error().stack;
+  }
+
+  AssertionError.prototype = Object.create(Error.prototype);
+  AssertionError.prototype.constructor = AssertionError;
+
+  function assert(value, message) {
+    if (!value) {
+      throw new AssertionError(message);
+    }
+  }
+
+  module.exports = {
+    rethrowAssertionErrorRejection: rethrowAssertionErrorRejection,
+    AssertionError: AssertionError,
+    assert: assert
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(0),
+      InvokeOrNoop = _require.InvokeOrNoop,
+      PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
+      ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
+      typeIsObject = _require.typeIsObject;
+
+  var _require2 = __w_pdfjs_require__(1),
+      assert = _require2.assert,
+      rethrowAssertionErrorRejection = _require2.rethrowAssertionErrorRejection;
+
+  var _require3 = __w_pdfjs_require__(3),
+      DequeueValue = _require3.DequeueValue,
+      EnqueueValueWithSize = _require3.EnqueueValueWithSize,
+      PeekQueueValue = _require3.PeekQueueValue,
+      ResetQueue = _require3.ResetQueue;
+
+  var WritableStream = function () {
+    function WritableStream() {
+      var underlyingSink = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          size = _ref.size,
+          _ref$highWaterMark = _ref.highWaterMark,
+          highWaterMark = _ref$highWaterMark === undefined ? 1 : _ref$highWaterMark;
+
+      _classCallCheck(this, WritableStream);
+
+      this._state = 'writable';
+      this._storedError = undefined;
+      this._writer = undefined;
+      this._writableStreamController = undefined;
+      this._writeRequests = [];
+      this._inFlightWriteRequest = undefined;
+      this._closeRequest = undefined;
+      this._inFlightCloseRequest = undefined;
+      this._pendingAbortRequest = undefined;
+      this._backpressure = false;
+      var type = underlyingSink.type;
+
+      if (type !== undefined) {
+        throw new RangeError('Invalid type is specified');
+      }
+
+      this._writableStreamController = new WritableStreamDefaultController(this, underlyingSink, size, highWaterMark);
+
+      this._writableStreamController.__startSteps();
+    }
+
+    _createClass(WritableStream, [{
+      key: 'abort',
+      value: function abort(reason) {
+        if (IsWritableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('abort'));
+        }
+
+        if (IsWritableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('Cannot abort a stream that already has a writer'));
+        }
+
+        return WritableStreamAbort(this, reason);
+      }
+    }, {
+      key: 'getWriter',
+      value: function getWriter() {
+        if (IsWritableStream(this) === false) {
+          throw streamBrandCheckException('getWriter');
+        }
+
+        return AcquireWritableStreamDefaultWriter(this);
+      }
+    }, {
+      key: 'locked',
+      get: function get() {
+        if (IsWritableStream(this) === false) {
+          throw streamBrandCheckException('locked');
+        }
+
+        return IsWritableStreamLocked(this);
+      }
+    }]);
+
+    return WritableStream;
+  }();
+
+  module.exports = {
+    AcquireWritableStreamDefaultWriter: AcquireWritableStreamDefaultWriter,
+    IsWritableStream: IsWritableStream,
+    IsWritableStreamLocked: IsWritableStreamLocked,
+    WritableStream: WritableStream,
+    WritableStreamAbort: WritableStreamAbort,
+    WritableStreamDefaultControllerError: WritableStreamDefaultControllerError,
+    WritableStreamDefaultWriterCloseWithErrorPropagation: WritableStreamDefaultWriterCloseWithErrorPropagation,
+    WritableStreamDefaultWriterRelease: WritableStreamDefaultWriterRelease,
+    WritableStreamDefaultWriterWrite: WritableStreamDefaultWriterWrite,
+    WritableStreamCloseQueuedOrInFlight: WritableStreamCloseQueuedOrInFlight
+  };
+
+  function AcquireWritableStreamDefaultWriter(stream) {
+    return new WritableStreamDefaultWriter(stream);
+  }
+
+  function IsWritableStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_writableStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsWritableStreamLocked(stream) {
+    assert(IsWritableStream(stream) === true, 'IsWritableStreamLocked should only be used on known writable streams');
+
+    if (stream._writer === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamAbort(stream, reason) {
+    var state = stream._state;
+
+    if (state === 'closed') {
+      return Promise.resolve(undefined);
+    }
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    var error = new TypeError('Requested to abort');
+
+    if (stream._pendingAbortRequest !== undefined) {
+      return Promise.reject(error);
+    }
+
+    assert(state === 'writable' || state === 'erroring', 'state must be writable or erroring');
+    var wasAlreadyErroring = false;
+
+    if (state === 'erroring') {
+      wasAlreadyErroring = true;
+      reason = undefined;
+    }
+
+    var promise = new Promise(function (resolve, reject) {
+      stream._pendingAbortRequest = {
+        _resolve: resolve,
+        _reject: reject,
+        _reason: reason,
+        _wasAlreadyErroring: wasAlreadyErroring
+      };
+    });
+
+    if (wasAlreadyErroring === false) {
+      WritableStreamStartErroring(stream, error);
+    }
+
+    return promise;
+  }
+
+  function WritableStreamAddWriteRequest(stream) {
+    assert(IsWritableStreamLocked(stream) === true);
+    assert(stream._state === 'writable');
+    var promise = new Promise(function (resolve, reject) {
+      var writeRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._writeRequests.push(writeRequest);
+    });
+    return promise;
+  }
+
+  function WritableStreamDealWithRejection(stream, error) {
+    var state = stream._state;
+
+    if (state === 'writable') {
+      WritableStreamStartErroring(stream, error);
+      return;
+    }
+
+    assert(state === 'erroring');
+    WritableStreamFinishErroring(stream);
+  }
+
+  function WritableStreamStartErroring(stream, reason) {
+    assert(stream._storedError === undefined, 'stream._storedError === undefined');
+    assert(stream._state === 'writable', 'state must be writable');
+    var controller = stream._writableStreamController;
+    assert(controller !== undefined, 'controller must not be undefined');
+    stream._state = 'erroring';
+    stream._storedError = reason;
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, reason);
+    }
+
+    if (WritableStreamHasOperationMarkedInFlight(stream) === false && controller._started === true) {
+      WritableStreamFinishErroring(stream);
+    }
+  }
+
+  function WritableStreamFinishErroring(stream) {
+    assert(stream._state === 'erroring', 'stream._state === erroring');
+    assert(WritableStreamHasOperationMarkedInFlight(stream) === false, 'WritableStreamHasOperationMarkedInFlight(stream) === false');
+    stream._state = 'errored';
+
+    stream._writableStreamController.__errorSteps();
+
+    var storedError = stream._storedError;
+
+    for (var i = 0; i < stream._writeRequests.length; i++) {
+      var writeRequest = stream._writeRequests[i];
+
+      writeRequest._reject(storedError);
+    }
+
+    stream._writeRequests = [];
+
+    if (stream._pendingAbortRequest === undefined) {
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    var abortRequest = stream._pendingAbortRequest;
+    stream._pendingAbortRequest = undefined;
+
+    if (abortRequest._wasAlreadyErroring === true) {
+      abortRequest._reject(storedError);
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+      return;
+    }
+
+    var promise = stream._writableStreamController.__abortSteps(abortRequest._reason);
+
+    promise.then(function () {
+      abortRequest._resolve();
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+    }, function (reason) {
+      abortRequest._reject(reason);
+
+      WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream);
+    });
+  }
+
+  function WritableStreamFinishInFlightWrite(stream) {
+    assert(stream._inFlightWriteRequest !== undefined);
+
+    stream._inFlightWriteRequest._resolve(undefined);
+
+    stream._inFlightWriteRequest = undefined;
+  }
+
+  function WritableStreamFinishInFlightWriteWithError(stream, error) {
+    assert(stream._inFlightWriteRequest !== undefined);
+
+    stream._inFlightWriteRequest._reject(error);
+
+    stream._inFlightWriteRequest = undefined;
+    assert(stream._state === 'writable' || stream._state === 'erroring');
+    WritableStreamDealWithRejection(stream, error);
+  }
+
+  function WritableStreamFinishInFlightClose(stream) {
+    assert(stream._inFlightCloseRequest !== undefined);
+
+    stream._inFlightCloseRequest._resolve(undefined);
+
+    stream._inFlightCloseRequest = undefined;
+    var state = stream._state;
+    assert(state === 'writable' || state === 'erroring');
+
+    if (state === 'erroring') {
+      stream._storedError = undefined;
+
+      if (stream._pendingAbortRequest !== undefined) {
+        stream._pendingAbortRequest._resolve();
+
+        stream._pendingAbortRequest = undefined;
+      }
+    }
+
+    stream._state = 'closed';
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      defaultWriterClosedPromiseResolve(writer);
+    }
+
+    assert(stream._pendingAbortRequest === undefined, 'stream._pendingAbortRequest === undefined');
+    assert(stream._storedError === undefined, 'stream._storedError === undefined');
+  }
+
+  function WritableStreamFinishInFlightCloseWithError(stream, error) {
+    assert(stream._inFlightCloseRequest !== undefined);
+
+    stream._inFlightCloseRequest._reject(error);
+
+    stream._inFlightCloseRequest = undefined;
+    assert(stream._state === 'writable' || stream._state === 'erroring');
+
+    if (stream._pendingAbortRequest !== undefined) {
+      stream._pendingAbortRequest._reject(error);
+
+      stream._pendingAbortRequest = undefined;
+    }
+
+    WritableStreamDealWithRejection(stream, error);
+  }
+
+  function WritableStreamCloseQueuedOrInFlight(stream) {
+    if (stream._closeRequest === undefined && stream._inFlightCloseRequest === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamHasOperationMarkedInFlight(stream) {
+    if (stream._inFlightWriteRequest === undefined && stream._inFlightCloseRequest === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamMarkCloseRequestInFlight(stream) {
+    assert(stream._inFlightCloseRequest === undefined);
+    assert(stream._closeRequest !== undefined);
+    stream._inFlightCloseRequest = stream._closeRequest;
+    stream._closeRequest = undefined;
+  }
+
+  function WritableStreamMarkFirstWriteRequestInFlight(stream) {
+    assert(stream._inFlightWriteRequest === undefined, 'there must be no pending write request');
+    assert(stream._writeRequests.length !== 0, 'writeRequests must not be empty');
+    stream._inFlightWriteRequest = stream._writeRequests.shift();
+  }
+
+  function WritableStreamRejectCloseAndClosedPromiseIfNeeded(stream) {
+    assert(stream._state === 'errored', '_stream_.[[state]] is `"errored"`');
+
+    if (stream._closeRequest !== undefined) {
+      assert(stream._inFlightCloseRequest === undefined);
+
+      stream._closeRequest._reject(stream._storedError);
+
+      stream._closeRequest = undefined;
+    }
+
+    var writer = stream._writer;
+
+    if (writer !== undefined) {
+      defaultWriterClosedPromiseReject(writer, stream._storedError);
+
+      writer._closedPromise["catch"](function () {});
+    }
+  }
+
+  function WritableStreamUpdateBackpressure(stream, backpressure) {
+    assert(stream._state === 'writable');
+    assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
+    var writer = stream._writer;
+
+    if (writer !== undefined && backpressure !== stream._backpressure) {
+      if (backpressure === true) {
+        defaultWriterReadyPromiseReset(writer);
+      } else {
+        assert(backpressure === false);
+        defaultWriterReadyPromiseResolve(writer);
+      }
+    }
+
+    stream._backpressure = backpressure;
+  }
+
+  var WritableStreamDefaultWriter = function () {
+    function WritableStreamDefaultWriter(stream) {
+      _classCallCheck(this, WritableStreamDefaultWriter);
+
+      if (IsWritableStream(stream) === false) {
+        throw new TypeError('WritableStreamDefaultWriter can only be constructed with a WritableStream instance');
+      }
+
+      if (IsWritableStreamLocked(stream) === true) {
+        throw new TypeError('This stream has already been locked for exclusive writing by another writer');
+      }
+
+      this._ownerWritableStream = stream;
+      stream._writer = this;
+      var state = stream._state;
+
+      if (state === 'writable') {
+        if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._backpressure === true) {
+          defaultWriterReadyPromiseInitialize(this);
+        } else {
+          defaultWriterReadyPromiseInitializeAsResolved(this);
+        }
+
+        defaultWriterClosedPromiseInitialize(this);
+      } else if (state === 'erroring') {
+        defaultWriterReadyPromiseInitializeAsRejected(this, stream._storedError);
+
+        this._readyPromise["catch"](function () {});
+
+        defaultWriterClosedPromiseInitialize(this);
+      } else if (state === 'closed') {
+        defaultWriterReadyPromiseInitializeAsResolved(this);
+        defaultWriterClosedPromiseInitializeAsResolved(this);
+      } else {
+        assert(state === 'errored', 'state must be errored');
+        var storedError = stream._storedError;
+        defaultWriterReadyPromiseInitializeAsRejected(this, storedError);
+
+        this._readyPromise["catch"](function () {});
+
+        defaultWriterClosedPromiseInitializeAsRejected(this, storedError);
+
+        this._closedPromise["catch"](function () {});
+      }
+    }
+
+    _createClass(WritableStreamDefaultWriter, [{
+      key: 'abort',
+      value: function abort(reason) {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('abort'));
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          return Promise.reject(defaultWriterLockException('abort'));
+        }
+
+        return WritableStreamDefaultWriterAbort(this, reason);
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('close'));
+        }
+
+        var stream = this._ownerWritableStream;
+
+        if (stream === undefined) {
+          return Promise.reject(defaultWriterLockException('close'));
+        }
+
+        if (WritableStreamCloseQueuedOrInFlight(stream) === true) {
+          return Promise.reject(new TypeError('cannot close an already-closing stream'));
+        }
+
+        return WritableStreamDefaultWriterClose(this);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          throw defaultWriterBrandCheckException('releaseLock');
+        }
+
+        var stream = this._ownerWritableStream;
+
+        if (stream === undefined) {
+          return;
+        }
+
+        assert(stream._writer !== undefined);
+        WritableStreamDefaultWriterRelease(this);
+      }
+    }, {
+      key: 'write',
+      value: function write(chunk) {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('write'));
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          return Promise.reject(defaultWriterLockException('write to'));
+        }
+
+        return WritableStreamDefaultWriterWrite(this, chunk);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          throw defaultWriterBrandCheckException('desiredSize');
+        }
+
+        if (this._ownerWritableStream === undefined) {
+          throw defaultWriterLockException('desiredSize');
+        }
+
+        return WritableStreamDefaultWriterGetDesiredSize(this);
+      }
+    }, {
+      key: 'ready',
+      get: function get() {
+        if (IsWritableStreamDefaultWriter(this) === false) {
+          return Promise.reject(defaultWriterBrandCheckException('ready'));
+        }
+
+        return this._readyPromise;
+      }
+    }]);
+
+    return WritableStreamDefaultWriter;
+  }();
+
+  function IsWritableStreamDefaultWriter(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_ownerWritableStream')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamDefaultWriterAbort(writer, reason) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    return WritableStreamAbort(stream, reason);
+  }
+
+  function WritableStreamDefaultWriterClose(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var state = stream._state;
+
+    if (state === 'closed' || state === 'errored') {
+      return Promise.reject(new TypeError('The stream (in ' + state + ' state) is not in the writable state and cannot be closed'));
+    }
+
+    assert(state === 'writable' || state === 'erroring');
+    assert(WritableStreamCloseQueuedOrInFlight(stream) === false);
+    var promise = new Promise(function (resolve, reject) {
+      var closeRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+      stream._closeRequest = closeRequest;
+    });
+
+    if (stream._backpressure === true && state === 'writable') {
+      defaultWriterReadyPromiseResolve(writer);
+    }
+
+    WritableStreamDefaultControllerClose(stream._writableStreamController);
+    return promise;
+  }
+
+  function WritableStreamDefaultWriterCloseWithErrorPropagation(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var state = stream._state;
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
+      return Promise.resolve();
+    }
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(state === 'writable' || state === 'erroring');
+    return WritableStreamDefaultWriterClose(writer);
+  }
+
+  function WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, error) {
+    if (writer._closedPromiseState === 'pending') {
+      defaultWriterClosedPromiseReject(writer, error);
+    } else {
+      defaultWriterClosedPromiseResetToRejected(writer, error);
+    }
+
+    writer._closedPromise["catch"](function () {});
+  }
+
+  function WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, error) {
+    if (writer._readyPromiseState === 'pending') {
+      defaultWriterReadyPromiseReject(writer, error);
+    } else {
+      defaultWriterReadyPromiseResetToRejected(writer, error);
+    }
+
+    writer._readyPromise["catch"](function () {});
+  }
+
+  function WritableStreamDefaultWriterGetDesiredSize(writer) {
+    var stream = writer._ownerWritableStream;
+    var state = stream._state;
+
+    if (state === 'errored' || state === 'erroring') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return WritableStreamDefaultControllerGetDesiredSize(stream._writableStreamController);
+  }
+
+  function WritableStreamDefaultWriterRelease(writer) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    assert(stream._writer === writer);
+    var releasedError = new TypeError('Writer was released and can no longer be used to monitor the stream\'s closedness');
+    WritableStreamDefaultWriterEnsureReadyPromiseRejected(writer, releasedError);
+    WritableStreamDefaultWriterEnsureClosedPromiseRejected(writer, releasedError);
+    stream._writer = undefined;
+    writer._ownerWritableStream = undefined;
+  }
+
+  function WritableStreamDefaultWriterWrite(writer, chunk) {
+    var stream = writer._ownerWritableStream;
+    assert(stream !== undefined);
+    var controller = stream._writableStreamController;
+    var chunkSize = WritableStreamDefaultControllerGetChunkSize(controller, chunk);
+
+    if (stream !== writer._ownerWritableStream) {
+      return Promise.reject(defaultWriterLockException('write to'));
+    }
+
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === true || state === 'closed') {
+      return Promise.reject(new TypeError('The stream is closing or closed and cannot be written to'));
+    }
+
+    if (state === 'erroring') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(state === 'writable');
+    var promise = WritableStreamAddWriteRequest(stream);
+    WritableStreamDefaultControllerWrite(controller, chunk, chunkSize);
+    return promise;
+  }
+
+  var WritableStreamDefaultController = function () {
+    function WritableStreamDefaultController(stream, underlyingSink, size, highWaterMark) {
+      _classCallCheck(this, WritableStreamDefaultController);
+
+      if (IsWritableStream(stream) === false) {
+        throw new TypeError('WritableStreamDefaultController can only be constructed with a WritableStream instance');
+      }
+
+      if (stream._writableStreamController !== undefined) {
+        throw new TypeError('WritableStreamDefaultController instances can only be created by the WritableStream constructor');
+      }
+
+      this._controlledWritableStream = stream;
+      this._underlyingSink = underlyingSink;
+      this._queue = undefined;
+      this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._started = false;
+      var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
+      this._strategySize = normalizedStrategy.size;
+      this._strategyHWM = normalizedStrategy.highWaterMark;
+      var backpressure = WritableStreamDefaultControllerGetBackpressure(this);
+      WritableStreamUpdateBackpressure(stream, backpressure);
+    }
+
+    _createClass(WritableStreamDefaultController, [{
+      key: 'error',
+      value: function error(e) {
+        if (IsWritableStreamDefaultController(this) === false) {
+          throw new TypeError('WritableStreamDefaultController.prototype.error can only be used on a WritableStreamDefaultController');
+        }
+
+        var state = this._controlledWritableStream._state;
+
+        if (state !== 'writable') {
+          return;
+        }
+
+        WritableStreamDefaultControllerError(this, e);
+      }
+    }, {
+      key: '__abortSteps',
+      value: function __abortSteps(reason) {
+        return PromiseInvokeOrNoop(this._underlyingSink, 'abort', [reason]);
+      }
+    }, {
+      key: '__errorSteps',
+      value: function __errorSteps() {
+        ResetQueue(this);
+      }
+    }, {
+      key: '__startSteps',
+      value: function __startSteps() {
+        var _this = this;
+
+        var startResult = InvokeOrNoop(this._underlyingSink, 'start', [this]);
+        var stream = this._controlledWritableStream;
+        Promise.resolve(startResult).then(function () {
+          assert(stream._state === 'writable' || stream._state === 'erroring');
+          _this._started = true;
+          WritableStreamDefaultControllerAdvanceQueueIfNeeded(_this);
+        }, function (r) {
+          assert(stream._state === 'writable' || stream._state === 'erroring');
+          _this._started = true;
+          WritableStreamDealWithRejection(stream, r);
+        })["catch"](rethrowAssertionErrorRejection);
+      }
+    }]);
+
+    return WritableStreamDefaultController;
+  }();
+
+  function WritableStreamDefaultControllerClose(controller) {
+    EnqueueValueWithSize(controller, 'close', 0);
+    WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+  }
+
+  function WritableStreamDefaultControllerGetChunkSize(controller, chunk) {
+    var strategySize = controller._strategySize;
+
+    if (strategySize === undefined) {
+      return 1;
+    }
+
+    try {
+      return strategySize(chunk);
+    } catch (chunkSizeE) {
+      WritableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
+      return 1;
+    }
+  }
+
+  function WritableStreamDefaultControllerGetDesiredSize(controller) {
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  function WritableStreamDefaultControllerWrite(controller, chunk, chunkSize) {
+    var writeRecord = {
+      chunk: chunk
+    };
+
+    try {
+      EnqueueValueWithSize(controller, writeRecord, chunkSize);
+    } catch (enqueueE) {
+      WritableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
+      return;
+    }
+
+    var stream = controller._controlledWritableStream;
+
+    if (WritableStreamCloseQueuedOrInFlight(stream) === false && stream._state === 'writable') {
+      var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
+      WritableStreamUpdateBackpressure(stream, backpressure);
+    }
+
+    WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+  }
+
+  function IsWritableStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSink')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller) {
+    var stream = controller._controlledWritableStream;
+
+    if (controller._started === false) {
+      return;
+    }
+
+    if (stream._inFlightWriteRequest !== undefined) {
+      return;
+    }
+
+    var state = stream._state;
+
+    if (state === 'closed' || state === 'errored') {
+      return;
+    }
+
+    if (state === 'erroring') {
+      WritableStreamFinishErroring(stream);
+      return;
+    }
+
+    if (controller._queue.length === 0) {
+      return;
+    }
+
+    var writeRecord = PeekQueueValue(controller);
+
+    if (writeRecord === 'close') {
+      WritableStreamDefaultControllerProcessClose(controller);
+    } else {
+      WritableStreamDefaultControllerProcessWrite(controller, writeRecord.chunk);
+    }
+  }
+
+  function WritableStreamDefaultControllerErrorIfNeeded(controller, error) {
+    if (controller._controlledWritableStream._state === 'writable') {
+      WritableStreamDefaultControllerError(controller, error);
+    }
+  }
+
+  function WritableStreamDefaultControllerProcessClose(controller) {
+    var stream = controller._controlledWritableStream;
+    WritableStreamMarkCloseRequestInFlight(stream);
+    DequeueValue(controller);
+    assert(controller._queue.length === 0, 'queue must be empty once the final write record is dequeued');
+    var sinkClosePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'close', []);
+    sinkClosePromise.then(function () {
+      WritableStreamFinishInFlightClose(stream);
+    }, function (reason) {
+      WritableStreamFinishInFlightCloseWithError(stream, reason);
+    })["catch"](rethrowAssertionErrorRejection);
+  }
+
+  function WritableStreamDefaultControllerProcessWrite(controller, chunk) {
+    var stream = controller._controlledWritableStream;
+    WritableStreamMarkFirstWriteRequestInFlight(stream);
+    var sinkWritePromise = PromiseInvokeOrNoop(controller._underlyingSink, 'write', [chunk, controller]);
+    sinkWritePromise.then(function () {
+      WritableStreamFinishInFlightWrite(stream);
+      var state = stream._state;
+      assert(state === 'writable' || state === 'erroring');
+      DequeueValue(controller);
+
+      if (WritableStreamCloseQueuedOrInFlight(stream) === false && state === 'writable') {
+        var backpressure = WritableStreamDefaultControllerGetBackpressure(controller);
+        WritableStreamUpdateBackpressure(stream, backpressure);
+      }
+
+      WritableStreamDefaultControllerAdvanceQueueIfNeeded(controller);
+    }, function (reason) {
+      WritableStreamFinishInFlightWriteWithError(stream, reason);
+    })["catch"](rethrowAssertionErrorRejection);
+  }
+
+  function WritableStreamDefaultControllerGetBackpressure(controller) {
+    var desiredSize = WritableStreamDefaultControllerGetDesiredSize(controller);
+    return desiredSize <= 0;
+  }
+
+  function WritableStreamDefaultControllerError(controller, error) {
+    var stream = controller._controlledWritableStream;
+    assert(stream._state === 'writable');
+    WritableStreamStartErroring(stream, error);
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('WritableStream.prototype.' + name + ' can only be used on a WritableStream');
+  }
+
+  function defaultWriterBrandCheckException(name) {
+    return new TypeError('WritableStreamDefaultWriter.prototype.' + name + ' can only be used on a WritableStreamDefaultWriter');
+  }
+
+  function defaultWriterLockException(name) {
+    return new TypeError('Cannot ' + name + ' a stream using a released writer');
+  }
+
+  function defaultWriterClosedPromiseInitialize(writer) {
+    writer._closedPromise = new Promise(function (resolve, reject) {
+      writer._closedPromise_resolve = resolve;
+      writer._closedPromise_reject = reject;
+      writer._closedPromiseState = 'pending';
+    });
+  }
+
+  function defaultWriterClosedPromiseInitializeAsRejected(writer, reason) {
+    writer._closedPromise = Promise.reject(reason);
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseInitializeAsResolved(writer) {
+    writer._closedPromise = Promise.resolve(undefined);
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'resolved';
+  }
+
+  function defaultWriterClosedPromiseReject(writer, reason) {
+    assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
+    assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
+    assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
+
+    writer._closedPromise_reject(reason);
+
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseResetToRejected(writer, reason) {
+    assert(writer._closedPromise_resolve === undefined, 'writer._closedPromise_resolve === undefined');
+    assert(writer._closedPromise_reject === undefined, 'writer._closedPromise_reject === undefined');
+    assert(writer._closedPromiseState !== 'pending', 'writer._closedPromiseState is not pending');
+    writer._closedPromise = Promise.reject(reason);
+    writer._closedPromiseState = 'rejected';
+  }
+
+  function defaultWriterClosedPromiseResolve(writer) {
+    assert(writer._closedPromise_resolve !== undefined, 'writer._closedPromise_resolve !== undefined');
+    assert(writer._closedPromise_reject !== undefined, 'writer._closedPromise_reject !== undefined');
+    assert(writer._closedPromiseState === 'pending', 'writer._closedPromiseState is pending');
+
+    writer._closedPromise_resolve(undefined);
+
+    writer._closedPromise_resolve = undefined;
+    writer._closedPromise_reject = undefined;
+    writer._closedPromiseState = 'resolved';
+  }
+
+  function defaultWriterReadyPromiseInitialize(writer) {
+    writer._readyPromise = new Promise(function (resolve, reject) {
+      writer._readyPromise_resolve = resolve;
+      writer._readyPromise_reject = reject;
+    });
+    writer._readyPromiseState = 'pending';
+  }
+
+  function defaultWriterReadyPromiseInitializeAsRejected(writer, reason) {
+    writer._readyPromise = Promise.reject(reason);
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseInitializeAsResolved(writer) {
+    writer._readyPromise = Promise.resolve(undefined);
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'fulfilled';
+  }
+
+  function defaultWriterReadyPromiseReject(writer, reason) {
+    assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
+    assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
+
+    writer._readyPromise_reject(reason);
+
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseReset(writer) {
+    assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
+    assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
+    writer._readyPromise = new Promise(function (resolve, reject) {
+      writer._readyPromise_resolve = resolve;
+      writer._readyPromise_reject = reject;
+    });
+    writer._readyPromiseState = 'pending';
+  }
+
+  function defaultWriterReadyPromiseResetToRejected(writer, reason) {
+    assert(writer._readyPromise_resolve === undefined, 'writer._readyPromise_resolve === undefined');
+    assert(writer._readyPromise_reject === undefined, 'writer._readyPromise_reject === undefined');
+    writer._readyPromise = Promise.reject(reason);
+    writer._readyPromiseState = 'rejected';
+  }
+
+  function defaultWriterReadyPromiseResolve(writer) {
+    assert(writer._readyPromise_resolve !== undefined, 'writer._readyPromise_resolve !== undefined');
+    assert(writer._readyPromise_reject !== undefined, 'writer._readyPromise_reject !== undefined');
+
+    writer._readyPromise_resolve(undefined);
+
+    writer._readyPromise_resolve = undefined;
+    writer._readyPromise_reject = undefined;
+    writer._readyPromiseState = 'fulfilled';
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _require = __w_pdfjs_require__(0),
+      IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber;
+
+  var _require2 = __w_pdfjs_require__(1),
+      assert = _require2.assert;
+
+  exports.DequeueValue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: DequeueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    assert(container._queue.length > 0, 'Spec-level failure: should never dequeue from an empty queue.');
+
+    var pair = container._queue.shift();
+
+    container._queueTotalSize -= pair.size;
+
+    if (container._queueTotalSize < 0) {
+      container._queueTotalSize = 0;
+    }
+
+    return pair.value;
+  };
+
+  exports.EnqueueValueWithSize = function (container, value, size) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: EnqueueValueWithSize should only be used on containers with [[queue]] and ' + '[[queueTotalSize]].');
+    size = Number(size);
+
+    if (!IsFiniteNonNegativeNumber(size)) {
+      throw new RangeError('Size must be a finite, non-NaN, non-negative number.');
+    }
+
+    container._queue.push({
+      value: value,
+      size: size
+    });
+
+    container._queueTotalSize += size;
+  };
+
+  exports.PeekQueueValue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: PeekQueueValue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    assert(container._queue.length > 0, 'Spec-level failure: should never peek at an empty queue.');
+    var pair = container._queue[0];
+    return pair.value;
+  };
+
+  exports.ResetQueue = function (container) {
+    assert('_queue' in container && '_queueTotalSize' in container, 'Spec-level failure: ResetQueue should only be used on containers with [[queue]] and [[queueTotalSize]].');
+    container._queue = [];
+    container._queueTotalSize = 0;
+  };
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(0),
+      ArrayBufferCopy = _require.ArrayBufferCopy,
+      CreateIterResultObject = _require.CreateIterResultObject,
+      IsFiniteNonNegativeNumber = _require.IsFiniteNonNegativeNumber,
+      InvokeOrNoop = _require.InvokeOrNoop,
+      PromiseInvokeOrNoop = _require.PromiseInvokeOrNoop,
+      TransferArrayBuffer = _require.TransferArrayBuffer,
+      ValidateAndNormalizeQueuingStrategy = _require.ValidateAndNormalizeQueuingStrategy,
+      ValidateAndNormalizeHighWaterMark = _require.ValidateAndNormalizeHighWaterMark;
+
+  var _require2 = __w_pdfjs_require__(0),
+      createArrayFromList = _require2.createArrayFromList,
+      createDataProperty = _require2.createDataProperty,
+      typeIsObject = _require2.typeIsObject;
+
+  var _require3 = __w_pdfjs_require__(1),
+      assert = _require3.assert,
+      rethrowAssertionErrorRejection = _require3.rethrowAssertionErrorRejection;
+
+  var _require4 = __w_pdfjs_require__(3),
+      DequeueValue = _require4.DequeueValue,
+      EnqueueValueWithSize = _require4.EnqueueValueWithSize,
+      ResetQueue = _require4.ResetQueue;
+
+  var _require5 = __w_pdfjs_require__(2),
+      AcquireWritableStreamDefaultWriter = _require5.AcquireWritableStreamDefaultWriter,
+      IsWritableStream = _require5.IsWritableStream,
+      IsWritableStreamLocked = _require5.IsWritableStreamLocked,
+      WritableStreamAbort = _require5.WritableStreamAbort,
+      WritableStreamDefaultWriterCloseWithErrorPropagation = _require5.WritableStreamDefaultWriterCloseWithErrorPropagation,
+      WritableStreamDefaultWriterRelease = _require5.WritableStreamDefaultWriterRelease,
+      WritableStreamDefaultWriterWrite = _require5.WritableStreamDefaultWriterWrite,
+      WritableStreamCloseQueuedOrInFlight = _require5.WritableStreamCloseQueuedOrInFlight;
+
+  var ReadableStream = function () {
+    function ReadableStream() {
+      var underlyingSource = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          size = _ref.size,
+          highWaterMark = _ref.highWaterMark;
+
+      _classCallCheck(this, ReadableStream);
+
+      this._state = 'readable';
+      this._reader = undefined;
+      this._storedError = undefined;
+      this._disturbed = false;
+      this._readableStreamController = undefined;
+      var type = underlyingSource.type;
+      var typeString = String(type);
+
+      if (typeString === 'bytes') {
+        if (highWaterMark === undefined) {
+          highWaterMark = 0;
+        }
+
+        this._readableStreamController = new ReadableByteStreamController(this, underlyingSource, highWaterMark);
+      } else if (type === undefined) {
+        if (highWaterMark === undefined) {
+          highWaterMark = 1;
+        }
+
+        this._readableStreamController = new ReadableStreamDefaultController(this, underlyingSource, size, highWaterMark);
+      } else {
+        throw new RangeError('Invalid type is specified');
+      }
+    }
+
+    _createClass(ReadableStream, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (IsReadableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('cancel'));
+        }
+
+        if (IsReadableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('Cannot cancel a stream that already has a reader'));
+        }
+
+        return ReadableStreamCancel(this, reason);
+      }
+    }, {
+      key: 'getReader',
+      value: function getReader() {
+        var _ref2 = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+            mode = _ref2.mode;
+
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('getReader');
+        }
+
+        if (mode === undefined) {
+          return AcquireReadableStreamDefaultReader(this);
+        }
+
+        mode = String(mode);
+
+        if (mode === 'byob') {
+          return AcquireReadableStreamBYOBReader(this);
+        }
+
+        throw new RangeError('Invalid mode is specified');
+      }
+    }, {
+      key: 'pipeThrough',
+      value: function pipeThrough(_ref3, options) {
+        var writable = _ref3.writable,
+            readable = _ref3.readable;
+        var promise = this.pipeTo(writable, options);
+        ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise);
+        return readable;
+      }
+    }, {
+      key: 'pipeTo',
+      value: function pipeTo(dest) {
+        var _this = this;
+
+        var _ref4 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+            preventClose = _ref4.preventClose,
+            preventAbort = _ref4.preventAbort,
+            preventCancel = _ref4.preventCancel;
+
+        if (IsReadableStream(this) === false) {
+          return Promise.reject(streamBrandCheckException('pipeTo'));
+        }
+
+        if (IsWritableStream(dest) === false) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo\'s first argument must be a WritableStream'));
+        }
+
+        preventClose = Boolean(preventClose);
+        preventAbort = Boolean(preventAbort);
+        preventCancel = Boolean(preventCancel);
+
+        if (IsReadableStreamLocked(this) === true) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked ReadableStream'));
+        }
+
+        if (IsWritableStreamLocked(dest) === true) {
+          return Promise.reject(new TypeError('ReadableStream.prototype.pipeTo cannot be used on a locked WritableStream'));
+        }
+
+        var reader = AcquireReadableStreamDefaultReader(this);
+        var writer = AcquireWritableStreamDefaultWriter(dest);
+        var shuttingDown = false;
+        var currentWrite = Promise.resolve();
+        return new Promise(function (resolve, reject) {
+          function pipeLoop() {
+            currentWrite = Promise.resolve();
+
+            if (shuttingDown === true) {
+              return Promise.resolve();
+            }
+
+            return writer._readyPromise.then(function () {
+              return ReadableStreamDefaultReaderRead(reader).then(function (_ref5) {
+                var value = _ref5.value,
+                    done = _ref5.done;
+
+                if (done === true) {
+                  return;
+                }
+
+                currentWrite = WritableStreamDefaultWriterWrite(writer, value)["catch"](function () {});
+              });
+            }).then(pipeLoop);
+          }
+
+          isOrBecomesErrored(_this, reader._closedPromise, function (storedError) {
+            if (preventAbort === false) {
+              shutdownWithAction(function () {
+                return WritableStreamAbort(dest, storedError);
+              }, true, storedError);
+            } else {
+              shutdown(true, storedError);
+            }
+          });
+          isOrBecomesErrored(dest, writer._closedPromise, function (storedError) {
+            if (preventCancel === false) {
+              shutdownWithAction(function () {
+                return ReadableStreamCancel(_this, storedError);
+              }, true, storedError);
+            } else {
+              shutdown(true, storedError);
+            }
+          });
+          isOrBecomesClosed(_this, reader._closedPromise, function () {
+            if (preventClose === false) {
+              shutdownWithAction(function () {
+                return WritableStreamDefaultWriterCloseWithErrorPropagation(writer);
+              });
+            } else {
+              shutdown();
+            }
+          });
+
+          if (WritableStreamCloseQueuedOrInFlight(dest) === true || dest._state === 'closed') {
+            var destClosed = new TypeError('the destination writable stream closed before all data could be piped to it');
+
+            if (preventCancel === false) {
+              shutdownWithAction(function () {
+                return ReadableStreamCancel(_this, destClosed);
+              }, true, destClosed);
+            } else {
+              shutdown(true, destClosed);
+            }
+          }
+
+          pipeLoop()["catch"](function (err) {
+            currentWrite = Promise.resolve();
+            rethrowAssertionErrorRejection(err);
+          });
+
+          function waitForWritesToFinish() {
+            var oldCurrentWrite = currentWrite;
+            return currentWrite.then(function () {
+              return oldCurrentWrite !== currentWrite ? waitForWritesToFinish() : undefined;
+            });
+          }
+
+          function isOrBecomesErrored(stream, promise, action) {
+            if (stream._state === 'errored') {
+              action(stream._storedError);
+            } else {
+              promise["catch"](action)["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function isOrBecomesClosed(stream, promise, action) {
+            if (stream._state === 'closed') {
+              action();
+            } else {
+              promise.then(action)["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function shutdownWithAction(action, originalIsError, originalError) {
+            if (shuttingDown === true) {
+              return;
+            }
+
+            shuttingDown = true;
+
+            if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
+              waitForWritesToFinish().then(doTheRest);
+            } else {
+              doTheRest();
+            }
+
+            function doTheRest() {
+              action().then(function () {
+                return finalize(originalIsError, originalError);
+              }, function (newError) {
+                return finalize(true, newError);
+              })["catch"](rethrowAssertionErrorRejection);
+            }
+          }
+
+          function shutdown(isError, error) {
+            if (shuttingDown === true) {
+              return;
+            }
+
+            shuttingDown = true;
+
+            if (dest._state === 'writable' && WritableStreamCloseQueuedOrInFlight(dest) === false) {
+              waitForWritesToFinish().then(function () {
+                return finalize(isError, error);
+              })["catch"](rethrowAssertionErrorRejection);
+            } else {
+              finalize(isError, error);
+            }
+          }
+
+          function finalize(isError, error) {
+            WritableStreamDefaultWriterRelease(writer);
+            ReadableStreamReaderGenericRelease(reader);
+
+            if (isError) {
+              reject(error);
+            } else {
+              resolve(undefined);
+            }
+          }
+        });
+      }
+    }, {
+      key: 'tee',
+      value: function tee() {
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('tee');
+        }
+
+        var branches = ReadableStreamTee(this, false);
+        return createArrayFromList(branches);
+      }
+    }, {
+      key: 'locked',
+      get: function get() {
+        if (IsReadableStream(this) === false) {
+          throw streamBrandCheckException('locked');
+        }
+
+        return IsReadableStreamLocked(this);
+      }
+    }]);
+
+    return ReadableStream;
+  }();
+
+  module.exports = {
+    ReadableStream: ReadableStream,
+    IsReadableStreamDisturbed: IsReadableStreamDisturbed,
+    ReadableStreamDefaultControllerClose: ReadableStreamDefaultControllerClose,
+    ReadableStreamDefaultControllerEnqueue: ReadableStreamDefaultControllerEnqueue,
+    ReadableStreamDefaultControllerError: ReadableStreamDefaultControllerError,
+    ReadableStreamDefaultControllerGetDesiredSize: ReadableStreamDefaultControllerGetDesiredSize
+  };
+
+  function AcquireReadableStreamBYOBReader(stream) {
+    return new ReadableStreamBYOBReader(stream);
+  }
+
+  function AcquireReadableStreamDefaultReader(stream) {
+    return new ReadableStreamDefaultReader(stream);
+  }
+
+  function IsReadableStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readableStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamDisturbed(stream) {
+    assert(IsReadableStream(stream) === true, 'IsReadableStreamDisturbed should only be used on known readable streams');
+    return stream._disturbed;
+  }
+
+  function IsReadableStreamLocked(stream) {
+    assert(IsReadableStream(stream) === true, 'IsReadableStreamLocked should only be used on known readable streams');
+
+    if (stream._reader === undefined) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamTee(stream, cloneForBranch2) {
+    assert(IsReadableStream(stream) === true);
+    assert(typeof cloneForBranch2 === 'boolean');
+    var reader = AcquireReadableStreamDefaultReader(stream);
+    var teeState = {
+      closedOrErrored: false,
+      canceled1: false,
+      canceled2: false,
+      reason1: undefined,
+      reason2: undefined
+    };
+    teeState.promise = new Promise(function (resolve) {
+      teeState._resolve = resolve;
+    });
+    var pull = create_ReadableStreamTeePullFunction();
+    pull._reader = reader;
+    pull._teeState = teeState;
+    pull._cloneForBranch2 = cloneForBranch2;
+    var cancel1 = create_ReadableStreamTeeBranch1CancelFunction();
+    cancel1._stream = stream;
+    cancel1._teeState = teeState;
+    var cancel2 = create_ReadableStreamTeeBranch2CancelFunction();
+    cancel2._stream = stream;
+    cancel2._teeState = teeState;
+    var underlyingSource1 = Object.create(Object.prototype);
+    createDataProperty(underlyingSource1, 'pull', pull);
+    createDataProperty(underlyingSource1, 'cancel', cancel1);
+    var branch1Stream = new ReadableStream(underlyingSource1);
+    var underlyingSource2 = Object.create(Object.prototype);
+    createDataProperty(underlyingSource2, 'pull', pull);
+    createDataProperty(underlyingSource2, 'cancel', cancel2);
+    var branch2Stream = new ReadableStream(underlyingSource2);
+    pull._branch1 = branch1Stream._readableStreamController;
+    pull._branch2 = branch2Stream._readableStreamController;
+
+    reader._closedPromise["catch"](function (r) {
+      if (teeState.closedOrErrored === true) {
+        return;
+      }
+
+      ReadableStreamDefaultControllerError(pull._branch1, r);
+      ReadableStreamDefaultControllerError(pull._branch2, r);
+      teeState.closedOrErrored = true;
+    });
+
+    return [branch1Stream, branch2Stream];
+  }
+
+  function create_ReadableStreamTeePullFunction() {
+    function f() {
+      var reader = f._reader,
+          branch1 = f._branch1,
+          branch2 = f._branch2,
+          teeState = f._teeState;
+      return ReadableStreamDefaultReaderRead(reader).then(function (result) {
+        assert(typeIsObject(result));
+        var value = result.value;
+        var done = result.done;
+        assert(typeof done === 'boolean');
+
+        if (done === true && teeState.closedOrErrored === false) {
+          if (teeState.canceled1 === false) {
+            ReadableStreamDefaultControllerClose(branch1);
+          }
+
+          if (teeState.canceled2 === false) {
+            ReadableStreamDefaultControllerClose(branch2);
+          }
+
+          teeState.closedOrErrored = true;
+        }
+
+        if (teeState.closedOrErrored === true) {
+          return;
+        }
+
+        var value1 = value;
+        var value2 = value;
+
+        if (teeState.canceled1 === false) {
+          ReadableStreamDefaultControllerEnqueue(branch1, value1);
+        }
+
+        if (teeState.canceled2 === false) {
+          ReadableStreamDefaultControllerEnqueue(branch2, value2);
+        }
+      });
+    }
+
+    return f;
+  }
+
+  function create_ReadableStreamTeeBranch1CancelFunction() {
+    function f(reason) {
+      var stream = f._stream,
+          teeState = f._teeState;
+      teeState.canceled1 = true;
+      teeState.reason1 = reason;
+
+      if (teeState.canceled2 === true) {
+        var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
+        var cancelResult = ReadableStreamCancel(stream, compositeReason);
+
+        teeState._resolve(cancelResult);
+      }
+
+      return teeState.promise;
+    }
+
+    return f;
+  }
+
+  function create_ReadableStreamTeeBranch2CancelFunction() {
+    function f(reason) {
+      var stream = f._stream,
+          teeState = f._teeState;
+      teeState.canceled2 = true;
+      teeState.reason2 = reason;
+
+      if (teeState.canceled1 === true) {
+        var compositeReason = createArrayFromList([teeState.reason1, teeState.reason2]);
+        var cancelResult = ReadableStreamCancel(stream, compositeReason);
+
+        teeState._resolve(cancelResult);
+      }
+
+      return teeState.promise;
+    }
+
+    return f;
+  }
+
+  function ReadableStreamAddReadIntoRequest(stream) {
+    assert(IsReadableStreamBYOBReader(stream._reader) === true);
+    assert(stream._state === 'readable' || stream._state === 'closed');
+    var promise = new Promise(function (resolve, reject) {
+      var readIntoRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._reader._readIntoRequests.push(readIntoRequest);
+    });
+    return promise;
+  }
+
+  function ReadableStreamAddReadRequest(stream) {
+    assert(IsReadableStreamDefaultReader(stream._reader) === true);
+    assert(stream._state === 'readable');
+    var promise = new Promise(function (resolve, reject) {
+      var readRequest = {
+        _resolve: resolve,
+        _reject: reject
+      };
+
+      stream._reader._readRequests.push(readRequest);
+    });
+    return promise;
+  }
+
+  function ReadableStreamCancel(stream, reason) {
+    stream._disturbed = true;
+
+    if (stream._state === 'closed') {
+      return Promise.resolve(undefined);
+    }
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    ReadableStreamClose(stream);
+
+    var sourceCancelPromise = stream._readableStreamController.__cancelSteps(reason);
+
+    return sourceCancelPromise.then(function () {
+      return undefined;
+    });
+  }
+
+  function ReadableStreamClose(stream) {
+    assert(stream._state === 'readable');
+    stream._state = 'closed';
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return undefined;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === true) {
+      for (var i = 0; i < reader._readRequests.length; i++) {
+        var _resolve = reader._readRequests[i]._resolve;
+
+        _resolve(CreateIterResultObject(undefined, true));
+      }
+
+      reader._readRequests = [];
+    }
+
+    defaultReaderClosedPromiseResolve(reader);
+    return undefined;
+  }
+
+  function ReadableStreamError(stream, e) {
+    assert(IsReadableStream(stream) === true, 'stream must be ReadableStream');
+    assert(stream._state === 'readable', 'state must be readable');
+    stream._state = 'errored';
+    stream._storedError = e;
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return undefined;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === true) {
+      for (var i = 0; i < reader._readRequests.length; i++) {
+        var readRequest = reader._readRequests[i];
+
+        readRequest._reject(e);
+      }
+
+      reader._readRequests = [];
+    } else {
+      assert(IsReadableStreamBYOBReader(reader), 'reader must be ReadableStreamBYOBReader');
+
+      for (var _i = 0; _i < reader._readIntoRequests.length; _i++) {
+        var readIntoRequest = reader._readIntoRequests[_i];
+
+        readIntoRequest._reject(e);
+      }
+
+      reader._readIntoRequests = [];
+    }
+
+    defaultReaderClosedPromiseReject(reader, e);
+
+    reader._closedPromise["catch"](function () {});
+  }
+
+  function ReadableStreamFulfillReadIntoRequest(stream, chunk, done) {
+    var reader = stream._reader;
+    assert(reader._readIntoRequests.length > 0);
+
+    var readIntoRequest = reader._readIntoRequests.shift();
+
+    readIntoRequest._resolve(CreateIterResultObject(chunk, done));
+  }
+
+  function ReadableStreamFulfillReadRequest(stream, chunk, done) {
+    var reader = stream._reader;
+    assert(reader._readRequests.length > 0);
+
+    var readRequest = reader._readRequests.shift();
+
+    readRequest._resolve(CreateIterResultObject(chunk, done));
+  }
+
+  function ReadableStreamGetNumReadIntoRequests(stream) {
+    return stream._reader._readIntoRequests.length;
+  }
+
+  function ReadableStreamGetNumReadRequests(stream) {
+    return stream._reader._readRequests.length;
+  }
+
+  function ReadableStreamHasBYOBReader(stream) {
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return false;
+    }
+
+    if (IsReadableStreamBYOBReader(reader) === false) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamHasDefaultReader(stream) {
+    var reader = stream._reader;
+
+    if (reader === undefined) {
+      return false;
+    }
+
+    if (IsReadableStreamDefaultReader(reader) === false) {
+      return false;
+    }
+
+    return true;
+  }
+
+  var ReadableStreamDefaultReader = function () {
+    function ReadableStreamDefaultReader(stream) {
+      _classCallCheck(this, ReadableStreamDefaultReader);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableStreamDefaultReader can only be constructed with a ReadableStream instance');
+      }
+
+      if (IsReadableStreamLocked(stream) === true) {
+        throw new TypeError('This stream has already been locked for exclusive reading by another reader');
+      }
+
+      ReadableStreamReaderGenericInitialize(this, stream);
+      this._readRequests = [];
+    }
+
+    _createClass(ReadableStreamDefaultReader, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('cancel'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('cancel'));
+        }
+
+        return ReadableStreamReaderGenericCancel(this, reason);
+      }
+    }, {
+      key: 'read',
+      value: function read() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('read'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('read from'));
+        }
+
+        return ReadableStreamDefaultReaderRead(this);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          throw defaultReaderBrandCheckException('releaseLock');
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return;
+        }
+
+        if (this._readRequests.length > 0) {
+          throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
+        }
+
+        ReadableStreamReaderGenericRelease(this);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (IsReadableStreamDefaultReader(this) === false) {
+          return Promise.reject(defaultReaderBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }]);
+
+    return ReadableStreamDefaultReader;
+  }();
+
+  var ReadableStreamBYOBReader = function () {
+    function ReadableStreamBYOBReader(stream) {
+      _classCallCheck(this, ReadableStreamBYOBReader);
+
+      if (!IsReadableStream(stream)) {
+        throw new TypeError('ReadableStreamBYOBReader can only be constructed with a ReadableStream instance given a ' + 'byte source');
+      }
+
+      if (IsReadableByteStreamController(stream._readableStreamController) === false) {
+        throw new TypeError('Cannot construct a ReadableStreamBYOBReader for a stream not constructed with a byte ' + 'source');
+      }
+
+      if (IsReadableStreamLocked(stream)) {
+        throw new TypeError('This stream has already been locked for exclusive reading by another reader');
+      }
+
+      ReadableStreamReaderGenericInitialize(this, stream);
+      this._readIntoRequests = [];
+    }
+
+    _createClass(ReadableStreamBYOBReader, [{
+      key: 'cancel',
+      value: function cancel(reason) {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('cancel'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('cancel'));
+        }
+
+        return ReadableStreamReaderGenericCancel(this, reason);
+      }
+    }, {
+      key: 'read',
+      value: function read(view) {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('read'));
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return Promise.reject(readerLockException('read from'));
+        }
+
+        if (!ArrayBuffer.isView(view)) {
+          return Promise.reject(new TypeError('view must be an array buffer view'));
+        }
+
+        if (view.byteLength === 0) {
+          return Promise.reject(new TypeError('view must have non-zero byteLength'));
+        }
+
+        return ReadableStreamBYOBReaderRead(this, view);
+      }
+    }, {
+      key: 'releaseLock',
+      value: function releaseLock() {
+        if (!IsReadableStreamBYOBReader(this)) {
+          throw byobReaderBrandCheckException('releaseLock');
+        }
+
+        if (this._ownerReadableStream === undefined) {
+          return;
+        }
+
+        if (this._readIntoRequests.length > 0) {
+          throw new TypeError('Tried to release a reader lock when that reader has pending read() calls un-settled');
+        }
+
+        ReadableStreamReaderGenericRelease(this);
+      }
+    }, {
+      key: 'closed',
+      get: function get() {
+        if (!IsReadableStreamBYOBReader(this)) {
+          return Promise.reject(byobReaderBrandCheckException('closed'));
+        }
+
+        return this._closedPromise;
+      }
+    }]);
+
+    return ReadableStreamBYOBReader;
+  }();
+
+  function IsReadableStreamBYOBReader(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readIntoRequests')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamDefaultReader(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_readRequests')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamReaderGenericInitialize(reader, stream) {
+    reader._ownerReadableStream = stream;
+    stream._reader = reader;
+
+    if (stream._state === 'readable') {
+      defaultReaderClosedPromiseInitialize(reader);
+    } else if (stream._state === 'closed') {
+      defaultReaderClosedPromiseInitializeAsResolved(reader);
+    } else {
+      assert(stream._state === 'errored', 'state must be errored');
+      defaultReaderClosedPromiseInitializeAsRejected(reader, stream._storedError);
+
+      reader._closedPromise["catch"](function () {});
+    }
+  }
+
+  function ReadableStreamReaderGenericCancel(reader, reason) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    return ReadableStreamCancel(stream, reason);
+  }
+
+  function ReadableStreamReaderGenericRelease(reader) {
+    assert(reader._ownerReadableStream !== undefined);
+    assert(reader._ownerReadableStream._reader === reader);
+
+    if (reader._ownerReadableStream._state === 'readable') {
+      defaultReaderClosedPromiseReject(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
+    } else {
+      defaultReaderClosedPromiseResetToRejected(reader, new TypeError('Reader was released and can no longer be used to monitor the stream\'s closedness'));
+    }
+
+    reader._closedPromise["catch"](function () {});
+
+    reader._ownerReadableStream._reader = undefined;
+    reader._ownerReadableStream = undefined;
+  }
+
+  function ReadableStreamBYOBReaderRead(reader, view) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    stream._disturbed = true;
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    return ReadableByteStreamControllerPullInto(stream._readableStreamController, view);
+  }
+
+  function ReadableStreamDefaultReaderRead(reader) {
+    var stream = reader._ownerReadableStream;
+    assert(stream !== undefined);
+    stream._disturbed = true;
+
+    if (stream._state === 'closed') {
+      return Promise.resolve(CreateIterResultObject(undefined, true));
+    }
+
+    if (stream._state === 'errored') {
+      return Promise.reject(stream._storedError);
+    }
+
+    assert(stream._state === 'readable');
+    return stream._readableStreamController.__pullSteps();
+  }
+
+  var ReadableStreamDefaultController = function () {
+    function ReadableStreamDefaultController(stream, underlyingSource, size, highWaterMark) {
+      _classCallCheck(this, ReadableStreamDefaultController);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableStreamDefaultController can only be constructed with a ReadableStream instance');
+      }
+
+      if (stream._readableStreamController !== undefined) {
+        throw new TypeError('ReadableStreamDefaultController instances can only be created by the ReadableStream constructor');
+      }
+
+      this._controlledReadableStream = stream;
+      this._underlyingSource = underlyingSource;
+      this._queue = undefined;
+      this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._started = false;
+      this._closeRequested = false;
+      this._pullAgain = false;
+      this._pulling = false;
+      var normalizedStrategy = ValidateAndNormalizeQueuingStrategy(size, highWaterMark);
+      this._strategySize = normalizedStrategy.size;
+      this._strategyHWM = normalizedStrategy.highWaterMark;
+      var controller = this;
+      var startResult = InvokeOrNoop(underlyingSource, 'start', [this]);
+      Promise.resolve(startResult).then(function () {
+        controller._started = true;
+        assert(controller._pulling === false);
+        assert(controller._pullAgain === false);
+        ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+      }, function (r) {
+        ReadableStreamDefaultControllerErrorIfNeeded(controller, r);
+      })["catch"](rethrowAssertionErrorRejection);
+    }
+
+    _createClass(ReadableStreamDefaultController, [{
+      key: 'close',
+      value: function close() {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('close');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('The stream has already been closed; do not close it again!');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
+        }
+
+        ReadableStreamDefaultControllerClose(this);
+      }
+    }, {
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('enqueue');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('stream is closed or draining');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
+        }
+
+        return ReadableStreamDefaultControllerEnqueue(this, chunk);
+      }
+    }, {
+      key: 'error',
+      value: function error(e) {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('error');
+        }
+
+        var stream = this._controlledReadableStream;
+
+        if (stream._state !== 'readable') {
+          throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
+        }
+
+        ReadableStreamDefaultControllerError(this, e);
+      }
+    }, {
+      key: '__cancelSteps',
+      value: function __cancelSteps(reason) {
+        ResetQueue(this);
+        return PromiseInvokeOrNoop(this._underlyingSource, 'cancel', [reason]);
+      }
+    }, {
+      key: '__pullSteps',
+      value: function __pullSteps() {
+        var stream = this._controlledReadableStream;
+
+        if (this._queue.length > 0) {
+          var chunk = DequeueValue(this);
+
+          if (this._closeRequested === true && this._queue.length === 0) {
+            ReadableStreamClose(stream);
+          } else {
+            ReadableStreamDefaultControllerCallPullIfNeeded(this);
+          }
+
+          return Promise.resolve(CreateIterResultObject(chunk, false));
+        }
+
+        var pendingPromise = ReadableStreamAddReadRequest(stream);
+        ReadableStreamDefaultControllerCallPullIfNeeded(this);
+        return pendingPromise;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsReadableStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('desiredSize');
+        }
+
+        return ReadableStreamDefaultControllerGetDesiredSize(this);
+      }
+    }]);
+
+    return ReadableStreamDefaultController;
+  }();
+
+  function IsReadableStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingSource')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableStreamDefaultControllerCallPullIfNeeded(controller) {
+    var shouldPull = ReadableStreamDefaultControllerShouldCallPull(controller);
+
+    if (shouldPull === false) {
+      return undefined;
+    }
+
+    if (controller._pulling === true) {
+      controller._pullAgain = true;
+      return undefined;
+    }
+
+    assert(controller._pullAgain === false);
+    controller._pulling = true;
+    var pullPromise = PromiseInvokeOrNoop(controller._underlyingSource, 'pull', [controller]);
+    pullPromise.then(function () {
+      controller._pulling = false;
+
+      if (controller._pullAgain === true) {
+        controller._pullAgain = false;
+        return ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+      }
+
+      return undefined;
+    }, function (e) {
+      ReadableStreamDefaultControllerErrorIfNeeded(controller, e);
+    })["catch"](rethrowAssertionErrorRejection);
+    return undefined;
+  }
+
+  function ReadableStreamDefaultControllerShouldCallPull(controller) {
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state === 'closed' || stream._state === 'errored') {
+      return false;
+    }
+
+    if (controller._closeRequested === true) {
+      return false;
+    }
+
+    if (controller._started === false) {
+      return false;
+    }
+
+    if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      return true;
+    }
+
+    var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
+
+    if (desiredSize > 0) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function ReadableStreamDefaultControllerClose(controller) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+    controller._closeRequested = true;
+
+    if (controller._queue.length === 0) {
+      ReadableStreamClose(stream);
+    }
+  }
+
+  function ReadableStreamDefaultControllerEnqueue(controller, chunk) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+
+    if (IsReadableStreamLocked(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      ReadableStreamFulfillReadRequest(stream, chunk, false);
+    } else {
+      var chunkSize = 1;
+
+      if (controller._strategySize !== undefined) {
+        var strategySize = controller._strategySize;
+
+        try {
+          chunkSize = strategySize(chunk);
+        } catch (chunkSizeE) {
+          ReadableStreamDefaultControllerErrorIfNeeded(controller, chunkSizeE);
+          throw chunkSizeE;
+        }
+      }
+
+      try {
+        EnqueueValueWithSize(controller, chunk, chunkSize);
+      } catch (enqueueE) {
+        ReadableStreamDefaultControllerErrorIfNeeded(controller, enqueueE);
+        throw enqueueE;
+      }
+    }
+
+    ReadableStreamDefaultControllerCallPullIfNeeded(controller);
+    return undefined;
+  }
+
+  function ReadableStreamDefaultControllerError(controller, e) {
+    var stream = controller._controlledReadableStream;
+    assert(stream._state === 'readable');
+    ResetQueue(controller);
+    ReadableStreamError(stream, e);
+  }
+
+  function ReadableStreamDefaultControllerErrorIfNeeded(controller, e) {
+    if (controller._controlledReadableStream._state === 'readable') {
+      ReadableStreamDefaultControllerError(controller, e);
+    }
+  }
+
+  function ReadableStreamDefaultControllerGetDesiredSize(controller) {
+    var stream = controller._controlledReadableStream;
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  var ReadableStreamBYOBRequest = function () {
+    function ReadableStreamBYOBRequest(controller, view) {
+      _classCallCheck(this, ReadableStreamBYOBRequest);
+
+      this._associatedReadableByteStreamController = controller;
+      this._view = view;
+    }
+
+    _createClass(ReadableStreamBYOBRequest, [{
+      key: 'respond',
+      value: function respond(bytesWritten) {
+        if (IsReadableStreamBYOBRequest(this) === false) {
+          throw byobRequestBrandCheckException('respond');
+        }
+
+        if (this._associatedReadableByteStreamController === undefined) {
+          throw new TypeError('This BYOB request has been invalidated');
+        }
+
+        ReadableByteStreamControllerRespond(this._associatedReadableByteStreamController, bytesWritten);
+      }
+    }, {
+      key: 'respondWithNewView',
+      value: function respondWithNewView(view) {
+        if (IsReadableStreamBYOBRequest(this) === false) {
+          throw byobRequestBrandCheckException('respond');
+        }
+
+        if (this._associatedReadableByteStreamController === undefined) {
+          throw new TypeError('This BYOB request has been invalidated');
+        }
+
+        if (!ArrayBuffer.isView(view)) {
+          throw new TypeError('You can only respond with array buffer views');
+        }
+
+        ReadableByteStreamControllerRespondWithNewView(this._associatedReadableByteStreamController, view);
+      }
+    }, {
+      key: 'view',
+      get: function get() {
+        return this._view;
+      }
+    }]);
+
+    return ReadableStreamBYOBRequest;
+  }();
+
+  var ReadableByteStreamController = function () {
+    function ReadableByteStreamController(stream, underlyingByteSource, highWaterMark) {
+      _classCallCheck(this, ReadableByteStreamController);
+
+      if (IsReadableStream(stream) === false) {
+        throw new TypeError('ReadableByteStreamController can only be constructed with a ReadableStream instance given ' + 'a byte source');
+      }
+
+      if (stream._readableStreamController !== undefined) {
+        throw new TypeError('ReadableByteStreamController instances can only be created by the ReadableStream constructor given a byte ' + 'source');
+      }
+
+      this._controlledReadableStream = stream;
+      this._underlyingByteSource = underlyingByteSource;
+      this._pullAgain = false;
+      this._pulling = false;
+      ReadableByteStreamControllerClearPendingPullIntos(this);
+      this._queue = this._queueTotalSize = undefined;
+      ResetQueue(this);
+      this._closeRequested = false;
+      this._started = false;
+      this._strategyHWM = ValidateAndNormalizeHighWaterMark(highWaterMark);
+      var autoAllocateChunkSize = underlyingByteSource.autoAllocateChunkSize;
+
+      if (autoAllocateChunkSize !== undefined) {
+        if (Number.isInteger(autoAllocateChunkSize) === false || autoAllocateChunkSize <= 0) {
+          throw new RangeError('autoAllocateChunkSize must be a positive integer');
+        }
+      }
+
+      this._autoAllocateChunkSize = autoAllocateChunkSize;
+      this._pendingPullIntos = [];
+      var controller = this;
+      var startResult = InvokeOrNoop(underlyingByteSource, 'start', [this]);
+      Promise.resolve(startResult).then(function () {
+        controller._started = true;
+        assert(controller._pulling === false);
+        assert(controller._pullAgain === false);
+        ReadableByteStreamControllerCallPullIfNeeded(controller);
+      }, function (r) {
+        if (stream._state === 'readable') {
+          ReadableByteStreamControllerError(controller, r);
+        }
+      })["catch"](rethrowAssertionErrorRejection);
+    }
+
+    _createClass(ReadableByteStreamController, [{
+      key: 'close',
+      value: function close() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('close');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('The stream has already been closed; do not close it again!');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be closed');
+        }
+
+        ReadableByteStreamControllerClose(this);
+      }
+    }, {
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('enqueue');
+        }
+
+        if (this._closeRequested === true) {
+          throw new TypeError('stream is closed or draining');
+        }
+
+        var state = this._controlledReadableStream._state;
+
+        if (state !== 'readable') {
+          throw new TypeError('The stream (in ' + state + ' state) is not in the readable state and cannot be enqueued to');
+        }
+
+        if (!ArrayBuffer.isView(chunk)) {
+          throw new TypeError('You can only enqueue array buffer views when using a ReadableByteStreamController');
+        }
+
+        ReadableByteStreamControllerEnqueue(this, chunk);
+      }
+    }, {
+      key: 'error',
+      value: function error(e) {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('error');
+        }
+
+        var stream = this._controlledReadableStream;
+
+        if (stream._state !== 'readable') {
+          throw new TypeError('The stream is ' + stream._state + ' and so cannot be errored');
+        }
+
+        ReadableByteStreamControllerError(this, e);
+      }
+    }, {
+      key: '__cancelSteps',
+      value: function __cancelSteps(reason) {
+        if (this._pendingPullIntos.length > 0) {
+          var firstDescriptor = this._pendingPullIntos[0];
+          firstDescriptor.bytesFilled = 0;
+        }
+
+        ResetQueue(this);
+        return PromiseInvokeOrNoop(this._underlyingByteSource, 'cancel', [reason]);
+      }
+    }, {
+      key: '__pullSteps',
+      value: function __pullSteps() {
+        var stream = this._controlledReadableStream;
+        assert(ReadableStreamHasDefaultReader(stream) === true);
+
+        if (this._queueTotalSize > 0) {
+          assert(ReadableStreamGetNumReadRequests(stream) === 0);
+
+          var entry = this._queue.shift();
+
+          this._queueTotalSize -= entry.byteLength;
+          ReadableByteStreamControllerHandleQueueDrain(this);
+          var view = void 0;
+
+          try {
+            view = new Uint8Array(entry.buffer, entry.byteOffset, entry.byteLength);
+          } catch (viewE) {
+            return Promise.reject(viewE);
+          }
+
+          return Promise.resolve(CreateIterResultObject(view, false));
+        }
+
+        var autoAllocateChunkSize = this._autoAllocateChunkSize;
+
+        if (autoAllocateChunkSize !== undefined) {
+          var buffer = void 0;
+
+          try {
+            buffer = new ArrayBuffer(autoAllocateChunkSize);
+          } catch (bufferE) {
+            return Promise.reject(bufferE);
+          }
+
+          var pullIntoDescriptor = {
+            buffer: buffer,
+            byteOffset: 0,
+            byteLength: autoAllocateChunkSize,
+            bytesFilled: 0,
+            elementSize: 1,
+            ctor: Uint8Array,
+            readerType: 'default'
+          };
+
+          this._pendingPullIntos.push(pullIntoDescriptor);
+        }
+
+        var promise = ReadableStreamAddReadRequest(stream);
+        ReadableByteStreamControllerCallPullIfNeeded(this);
+        return promise;
+      }
+    }, {
+      key: 'byobRequest',
+      get: function get() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('byobRequest');
+        }
+
+        if (this._byobRequest === undefined && this._pendingPullIntos.length > 0) {
+          var firstDescriptor = this._pendingPullIntos[0];
+          var view = new Uint8Array(firstDescriptor.buffer, firstDescriptor.byteOffset + firstDescriptor.bytesFilled, firstDescriptor.byteLength - firstDescriptor.bytesFilled);
+          this._byobRequest = new ReadableStreamBYOBRequest(this, view);
+        }
+
+        return this._byobRequest;
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsReadableByteStreamController(this) === false) {
+          throw byteStreamControllerBrandCheckException('desiredSize');
+        }
+
+        return ReadableByteStreamControllerGetDesiredSize(this);
+      }
+    }]);
+
+    return ReadableByteStreamController;
+  }();
+
+  function IsReadableByteStreamController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_underlyingByteSource')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsReadableStreamBYOBRequest(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_associatedReadableByteStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function ReadableByteStreamControllerCallPullIfNeeded(controller) {
+    var shouldPull = ReadableByteStreamControllerShouldCallPull(controller);
+
+    if (shouldPull === false) {
+      return undefined;
+    }
+
+    if (controller._pulling === true) {
+      controller._pullAgain = true;
+      return undefined;
+    }
+
+    assert(controller._pullAgain === false);
+    controller._pulling = true;
+    var pullPromise = PromiseInvokeOrNoop(controller._underlyingByteSource, 'pull', [controller]);
+    pullPromise.then(function () {
+      controller._pulling = false;
+
+      if (controller._pullAgain === true) {
+        controller._pullAgain = false;
+        ReadableByteStreamControllerCallPullIfNeeded(controller);
+      }
+    }, function (e) {
+      if (controller._controlledReadableStream._state === 'readable') {
+        ReadableByteStreamControllerError(controller, e);
+      }
+    })["catch"](rethrowAssertionErrorRejection);
+    return undefined;
+  }
+
+  function ReadableByteStreamControllerClearPendingPullIntos(controller) {
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    controller._pendingPullIntos = [];
+  }
+
+  function ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor) {
+    assert(stream._state !== 'errored', 'state must not be errored');
+    var done = false;
+
+    if (stream._state === 'closed') {
+      assert(pullIntoDescriptor.bytesFilled === 0);
+      done = true;
+    }
+
+    var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
+
+    if (pullIntoDescriptor.readerType === 'default') {
+      ReadableStreamFulfillReadRequest(stream, filledView, done);
+    } else {
+      assert(pullIntoDescriptor.readerType === 'byob');
+      ReadableStreamFulfillReadIntoRequest(stream, filledView, done);
+    }
+  }
+
+  function ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor) {
+    var bytesFilled = pullIntoDescriptor.bytesFilled;
+    var elementSize = pullIntoDescriptor.elementSize;
+    assert(bytesFilled <= pullIntoDescriptor.byteLength);
+    assert(bytesFilled % elementSize === 0);
+    return new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, bytesFilled / elementSize);
+  }
+
+  function ReadableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength) {
+    controller._queue.push({
+      buffer: buffer,
+      byteOffset: byteOffset,
+      byteLength: byteLength
+    });
+
+    controller._queueTotalSize += byteLength;
+  }
+
+  function ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) {
+    var elementSize = pullIntoDescriptor.elementSize;
+    var currentAlignedBytes = pullIntoDescriptor.bytesFilled - pullIntoDescriptor.bytesFilled % elementSize;
+    var maxBytesToCopy = Math.min(controller._queueTotalSize, pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled);
+    var maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
+    var maxAlignedBytes = maxBytesFilled - maxBytesFilled % elementSize;
+    var totalBytesToCopyRemaining = maxBytesToCopy;
+    var ready = false;
+
+    if (maxAlignedBytes > currentAlignedBytes) {
+      totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
+      ready = true;
+    }
+
+    var queue = controller._queue;
+
+    while (totalBytesToCopyRemaining > 0) {
+      var headOfQueue = queue[0];
+      var bytesToCopy = Math.min(totalBytesToCopyRemaining, headOfQueue.byteLength);
+      var destStart = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+      ArrayBufferCopy(pullIntoDescriptor.buffer, destStart, headOfQueue.buffer, headOfQueue.byteOffset, bytesToCopy);
+
+      if (headOfQueue.byteLength === bytesToCopy) {
+        queue.shift();
+      } else {
+        headOfQueue.byteOffset += bytesToCopy;
+        headOfQueue.byteLength -= bytesToCopy;
+      }
+
+      controller._queueTotalSize -= bytesToCopy;
+      ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesToCopy, pullIntoDescriptor);
+      totalBytesToCopyRemaining -= bytesToCopy;
+    }
+
+    if (ready === false) {
+      assert(controller._queueTotalSize === 0, 'queue must be empty');
+      assert(pullIntoDescriptor.bytesFilled > 0);
+      assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
+    }
+
+    return ready;
+  }
+
+  function ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, size, pullIntoDescriptor) {
+    assert(controller._pendingPullIntos.length === 0 || controller._pendingPullIntos[0] === pullIntoDescriptor);
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    pullIntoDescriptor.bytesFilled += size;
+  }
+
+  function ReadableByteStreamControllerHandleQueueDrain(controller) {
+    assert(controller._controlledReadableStream._state === 'readable');
+
+    if (controller._queueTotalSize === 0 && controller._closeRequested === true) {
+      ReadableStreamClose(controller._controlledReadableStream);
+    } else {
+      ReadableByteStreamControllerCallPullIfNeeded(controller);
+    }
+  }
+
+  function ReadableByteStreamControllerInvalidateBYOBRequest(controller) {
+    if (controller._byobRequest === undefined) {
+      return;
+    }
+
+    controller._byobRequest._associatedReadableByteStreamController = undefined;
+    controller._byobRequest._view = undefined;
+    controller._byobRequest = undefined;
+  }
+
+  function ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller) {
+    assert(controller._closeRequested === false);
+
+    while (controller._pendingPullIntos.length > 0) {
+      if (controller._queueTotalSize === 0) {
+        return;
+      }
+
+      var pullIntoDescriptor = controller._pendingPullIntos[0];
+
+      if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
+        ReadableByteStreamControllerShiftPendingPullInto(controller);
+        ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
+      }
+    }
+  }
+
+  function ReadableByteStreamControllerPullInto(controller, view) {
+    var stream = controller._controlledReadableStream;
+    var elementSize = 1;
+
+    if (view.constructor !== DataView) {
+      elementSize = view.constructor.BYTES_PER_ELEMENT;
+    }
+
+    var ctor = view.constructor;
+    var pullIntoDescriptor = {
+      buffer: view.buffer,
+      byteOffset: view.byteOffset,
+      byteLength: view.byteLength,
+      bytesFilled: 0,
+      elementSize: elementSize,
+      ctor: ctor,
+      readerType: 'byob'
+    };
+
+    if (controller._pendingPullIntos.length > 0) {
+      pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+
+      controller._pendingPullIntos.push(pullIntoDescriptor);
+
+      return ReadableStreamAddReadIntoRequest(stream);
+    }
+
+    if (stream._state === 'closed') {
+      var emptyView = new view.constructor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, 0);
+      return Promise.resolve(CreateIterResultObject(emptyView, true));
+    }
+
+    if (controller._queueTotalSize > 0) {
+      if (ReadableByteStreamControllerFillPullIntoDescriptorFromQueue(controller, pullIntoDescriptor) === true) {
+        var filledView = ReadableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
+        ReadableByteStreamControllerHandleQueueDrain(controller);
+        return Promise.resolve(CreateIterResultObject(filledView, false));
+      }
+
+      if (controller._closeRequested === true) {
+        var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
+        ReadableByteStreamControllerError(controller, e);
+        return Promise.reject(e);
+      }
+    }
+
+    pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+
+    controller._pendingPullIntos.push(pullIntoDescriptor);
+
+    var promise = ReadableStreamAddReadIntoRequest(stream);
+    ReadableByteStreamControllerCallPullIfNeeded(controller);
+    return promise;
+  }
+
+  function ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor) {
+    firstDescriptor.buffer = TransferArrayBuffer(firstDescriptor.buffer);
+    assert(firstDescriptor.bytesFilled === 0, 'bytesFilled must be 0');
+    var stream = controller._controlledReadableStream;
+
+    if (ReadableStreamHasBYOBReader(stream) === true) {
+      while (ReadableStreamGetNumReadIntoRequests(stream) > 0) {
+        var pullIntoDescriptor = ReadableByteStreamControllerShiftPendingPullInto(controller);
+        ReadableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor);
+      }
+    }
+  }
+
+  function ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor) {
+    if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength) {
+      throw new RangeError('bytesWritten out of range');
+    }
+
+    ReadableByteStreamControllerFillHeadPullIntoDescriptor(controller, bytesWritten, pullIntoDescriptor);
+
+    if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize) {
+      return;
+    }
+
+    ReadableByteStreamControllerShiftPendingPullInto(controller);
+    var remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize;
+
+    if (remainderSize > 0) {
+      var end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+      var remainder = pullIntoDescriptor.buffer.slice(end - remainderSize, end);
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, remainder, 0, remainder.byteLength);
+    }
+
+    pullIntoDescriptor.buffer = TransferArrayBuffer(pullIntoDescriptor.buffer);
+    pullIntoDescriptor.bytesFilled -= remainderSize;
+    ReadableByteStreamControllerCommitPullIntoDescriptor(controller._controlledReadableStream, pullIntoDescriptor);
+    ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
+  }
+
+  function ReadableByteStreamControllerRespondInternal(controller, bytesWritten) {
+    var firstDescriptor = controller._pendingPullIntos[0];
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state === 'closed') {
+      if (bytesWritten !== 0) {
+        throw new TypeError('bytesWritten must be 0 when calling respond() on a closed stream');
+      }
+
+      ReadableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
+    } else {
+      assert(stream._state === 'readable');
+      ReadableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
+    }
+  }
+
+  function ReadableByteStreamControllerShiftPendingPullInto(controller) {
+    var descriptor = controller._pendingPullIntos.shift();
+
+    ReadableByteStreamControllerInvalidateBYOBRequest(controller);
+    return descriptor;
+  }
+
+  function ReadableByteStreamControllerShouldCallPull(controller) {
+    var stream = controller._controlledReadableStream;
+
+    if (stream._state !== 'readable') {
+      return false;
+    }
+
+    if (controller._closeRequested === true) {
+      return false;
+    }
+
+    if (controller._started === false) {
+      return false;
+    }
+
+    if (ReadableStreamHasDefaultReader(stream) === true && ReadableStreamGetNumReadRequests(stream) > 0) {
+      return true;
+    }
+
+    if (ReadableStreamHasBYOBReader(stream) === true && ReadableStreamGetNumReadIntoRequests(stream) > 0) {
+      return true;
+    }
+
+    if (ReadableByteStreamControllerGetDesiredSize(controller) > 0) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function ReadableByteStreamControllerClose(controller) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+
+    if (controller._queueTotalSize > 0) {
+      controller._closeRequested = true;
+      return;
+    }
+
+    if (controller._pendingPullIntos.length > 0) {
+      var firstPendingPullInto = controller._pendingPullIntos[0];
+
+      if (firstPendingPullInto.bytesFilled > 0) {
+        var e = new TypeError('Insufficient bytes to fill elements in the given buffer');
+        ReadableByteStreamControllerError(controller, e);
+        throw e;
+      }
+    }
+
+    ReadableStreamClose(stream);
+  }
+
+  function ReadableByteStreamControllerEnqueue(controller, chunk) {
+    var stream = controller._controlledReadableStream;
+    assert(controller._closeRequested === false);
+    assert(stream._state === 'readable');
+    var buffer = chunk.buffer;
+    var byteOffset = chunk.byteOffset;
+    var byteLength = chunk.byteLength;
+    var transferredBuffer = TransferArrayBuffer(buffer);
+
+    if (ReadableStreamHasDefaultReader(stream) === true) {
+      if (ReadableStreamGetNumReadRequests(stream) === 0) {
+        ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+      } else {
+        assert(controller._queue.length === 0);
+        var transferredView = new Uint8Array(transferredBuffer, byteOffset, byteLength);
+        ReadableStreamFulfillReadRequest(stream, transferredView, false);
+      }
+    } else if (ReadableStreamHasBYOBReader(stream) === true) {
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+      ReadableByteStreamControllerProcessPullIntoDescriptorsUsingQueue(controller);
+    } else {
+      assert(IsReadableStreamLocked(stream) === false, 'stream must not be locked');
+      ReadableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+    }
+  }
+
+  function ReadableByteStreamControllerError(controller, e) {
+    var stream = controller._controlledReadableStream;
+    assert(stream._state === 'readable');
+    ReadableByteStreamControllerClearPendingPullIntos(controller);
+    ResetQueue(controller);
+    ReadableStreamError(stream, e);
+  }
+
+  function ReadableByteStreamControllerGetDesiredSize(controller) {
+    var stream = controller._controlledReadableStream;
+    var state = stream._state;
+
+    if (state === 'errored') {
+      return null;
+    }
+
+    if (state === 'closed') {
+      return 0;
+    }
+
+    return controller._strategyHWM - controller._queueTotalSize;
+  }
+
+  function ReadableByteStreamControllerRespond(controller, bytesWritten) {
+    bytesWritten = Number(bytesWritten);
+
+    if (IsFiniteNonNegativeNumber(bytesWritten) === false) {
+      throw new RangeError('bytesWritten must be a finite');
+    }
+
+    assert(controller._pendingPullIntos.length > 0);
+    ReadableByteStreamControllerRespondInternal(controller, bytesWritten);
+  }
+
+  function ReadableByteStreamControllerRespondWithNewView(controller, view) {
+    assert(controller._pendingPullIntos.length > 0);
+    var firstDescriptor = controller._pendingPullIntos[0];
+
+    if (firstDescriptor.byteOffset + firstDescriptor.bytesFilled !== view.byteOffset) {
+      throw new RangeError('The region specified by view does not match byobRequest');
+    }
+
+    if (firstDescriptor.byteLength !== view.byteLength) {
+      throw new RangeError('The buffer of view has different capacity than byobRequest');
+    }
+
+    firstDescriptor.buffer = view.buffer;
+    ReadableByteStreamControllerRespondInternal(controller, view.byteLength);
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('ReadableStream.prototype.' + name + ' can only be used on a ReadableStream');
+  }
+
+  function readerLockException(name) {
+    return new TypeError('Cannot ' + name + ' a stream using a released reader');
+  }
+
+  function defaultReaderBrandCheckException(name) {
+    return new TypeError('ReadableStreamDefaultReader.prototype.' + name + ' can only be used on a ReadableStreamDefaultReader');
+  }
+
+  function defaultReaderClosedPromiseInitialize(reader) {
+    reader._closedPromise = new Promise(function (resolve, reject) {
+      reader._closedPromise_resolve = resolve;
+      reader._closedPromise_reject = reject;
+    });
+  }
+
+  function defaultReaderClosedPromiseInitializeAsRejected(reader, reason) {
+    reader._closedPromise = Promise.reject(reason);
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseInitializeAsResolved(reader) {
+    reader._closedPromise = Promise.resolve(undefined);
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseReject(reader, reason) {
+    assert(reader._closedPromise_resolve !== undefined);
+    assert(reader._closedPromise_reject !== undefined);
+
+    reader._closedPromise_reject(reason);
+
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function defaultReaderClosedPromiseResetToRejected(reader, reason) {
+    assert(reader._closedPromise_resolve === undefined);
+    assert(reader._closedPromise_reject === undefined);
+    reader._closedPromise = Promise.reject(reason);
+  }
+
+  function defaultReaderClosedPromiseResolve(reader) {
+    assert(reader._closedPromise_resolve !== undefined);
+    assert(reader._closedPromise_reject !== undefined);
+
+    reader._closedPromise_resolve(undefined);
+
+    reader._closedPromise_resolve = undefined;
+    reader._closedPromise_reject = undefined;
+  }
+
+  function byobReaderBrandCheckException(name) {
+    return new TypeError('ReadableStreamBYOBReader.prototype.' + name + ' can only be used on a ReadableStreamBYOBReader');
+  }
+
+  function defaultControllerBrandCheckException(name) {
+    return new TypeError('ReadableStreamDefaultController.prototype.' + name + ' can only be used on a ReadableStreamDefaultController');
+  }
+
+  function byobRequestBrandCheckException(name) {
+    return new TypeError('ReadableStreamBYOBRequest.prototype.' + name + ' can only be used on a ReadableStreamBYOBRequest');
+  }
+
+  function byteStreamControllerBrandCheckException(name) {
+    return new TypeError('ReadableByteStreamController.prototype.' + name + ' can only be used on a ReadableByteStreamController');
+  }
+
+  function ifIsObjectAndHasAPromiseIsHandledInternalSlotSetPromiseIsHandledToTrue(promise) {
+    try {
+      Promise.prototype.then.call(promise, undefined, function () {});
+    } catch (e) {}
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var transformStream = __w_pdfjs_require__(6);
+
+  var readableStream = __w_pdfjs_require__(4);
+
+  var writableStream = __w_pdfjs_require__(2);
+
+  exports.TransformStream = transformStream.TransformStream;
+  exports.ReadableStream = readableStream.ReadableStream;
+  exports.IsReadableStreamDisturbed = readableStream.IsReadableStreamDisturbed;
+  exports.ReadableStreamDefaultControllerClose = readableStream.ReadableStreamDefaultControllerClose;
+  exports.ReadableStreamDefaultControllerEnqueue = readableStream.ReadableStreamDefaultControllerEnqueue;
+  exports.ReadableStreamDefaultControllerError = readableStream.ReadableStreamDefaultControllerError;
+  exports.ReadableStreamDefaultControllerGetDesiredSize = readableStream.ReadableStreamDefaultControllerGetDesiredSize;
+  exports.AcquireWritableStreamDefaultWriter = writableStream.AcquireWritableStreamDefaultWriter;
+  exports.IsWritableStream = writableStream.IsWritableStream;
+  exports.IsWritableStreamLocked = writableStream.IsWritableStreamLocked;
+  exports.WritableStream = writableStream.WritableStream;
+  exports.WritableStreamAbort = writableStream.WritableStreamAbort;
+  exports.WritableStreamDefaultControllerError = writableStream.WritableStreamDefaultControllerError;
+  exports.WritableStreamDefaultWriterCloseWithErrorPropagation = writableStream.WritableStreamDefaultWriterCloseWithErrorPropagation;
+  exports.WritableStreamDefaultWriterRelease = writableStream.WritableStreamDefaultWriterRelease;
+  exports.WritableStreamDefaultWriterWrite = writableStream.WritableStreamDefaultWriterWrite;
+}, function (module, exports, __w_pdfjs_require__) {
+  "use strict";
+
+  var _createClass = function () {
+    function defineProperties(target, props) {
+      for (var i = 0; i < props.length; i++) {
+        var descriptor = props[i];
+        descriptor.enumerable = descriptor.enumerable || false;
+        descriptor.configurable = true;
+        if ("value" in descriptor) descriptor.writable = true;
+        Object.defineProperty(target, descriptor.key, descriptor);
+      }
+    }
+
+    return function (Constructor, protoProps, staticProps) {
+      if (protoProps) defineProperties(Constructor.prototype, protoProps);
+      if (staticProps) defineProperties(Constructor, staticProps);
+      return Constructor;
+    };
+  }();
+
+  function _classCallCheck(instance, Constructor) {
+    if (!(instance instanceof Constructor)) {
+      throw new TypeError("Cannot call a class as a function");
+    }
+  }
+
+  var _require = __w_pdfjs_require__(1),
+      assert = _require.assert;
+
+  var _require2 = __w_pdfjs_require__(0),
+      InvokeOrNoop = _require2.InvokeOrNoop,
+      PromiseInvokeOrPerformFallback = _require2.PromiseInvokeOrPerformFallback,
+      PromiseInvokeOrNoop = _require2.PromiseInvokeOrNoop,
+      typeIsObject = _require2.typeIsObject;
+
+  var _require3 = __w_pdfjs_require__(4),
+      ReadableStream = _require3.ReadableStream,
+      ReadableStreamDefaultControllerClose = _require3.ReadableStreamDefaultControllerClose,
+      ReadableStreamDefaultControllerEnqueue = _require3.ReadableStreamDefaultControllerEnqueue,
+      ReadableStreamDefaultControllerError = _require3.ReadableStreamDefaultControllerError,
+      ReadableStreamDefaultControllerGetDesiredSize = _require3.ReadableStreamDefaultControllerGetDesiredSize;
+
+  var _require4 = __w_pdfjs_require__(2),
+      WritableStream = _require4.WritableStream,
+      WritableStreamDefaultControllerError = _require4.WritableStreamDefaultControllerError;
+
+  function TransformStreamCloseReadable(transformStream) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    if (transformStream._readableClosed === true) {
+      throw new TypeError('Readable side is already closed');
+    }
+
+    TransformStreamCloseReadableInternal(transformStream);
+  }
+
+  function TransformStreamEnqueueToReadable(transformStream, chunk) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    if (transformStream._readableClosed === true) {
+      throw new TypeError('Readable side is already closed');
+    }
+
+    var controller = transformStream._readableController;
+
+    try {
+      ReadableStreamDefaultControllerEnqueue(controller, chunk);
+    } catch (e) {
+      transformStream._readableClosed = true;
+      TransformStreamErrorIfNeeded(transformStream, e);
+      throw transformStream._storedError;
+    }
+
+    var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller);
+    var maybeBackpressure = desiredSize <= 0;
+
+    if (maybeBackpressure === true && transformStream._backpressure === false) {
+      TransformStreamSetBackpressure(transformStream, true);
+    }
+  }
+
+  function TransformStreamError(transformStream, e) {
+    if (transformStream._errored === true) {
+      throw new TypeError('TransformStream is already errored');
+    }
+
+    TransformStreamErrorInternal(transformStream, e);
+  }
+
+  function TransformStreamCloseReadableInternal(transformStream) {
+    assert(transformStream._errored === false);
+    assert(transformStream._readableClosed === false);
+
+    try {
+      ReadableStreamDefaultControllerClose(transformStream._readableController);
+    } catch (e) {
+      assert(false);
+    }
+
+    transformStream._readableClosed = true;
+  }
+
+  function TransformStreamErrorIfNeeded(transformStream, e) {
+    if (transformStream._errored === false) {
+      TransformStreamErrorInternal(transformStream, e);
+    }
+  }
+
+  function TransformStreamErrorInternal(transformStream, e) {
+    assert(transformStream._errored === false);
+    transformStream._errored = true;
+    transformStream._storedError = e;
+
+    if (transformStream._writableDone === false) {
+      WritableStreamDefaultControllerError(transformStream._writableController, e);
+    }
+
+    if (transformStream._readableClosed === false) {
+      ReadableStreamDefaultControllerError(transformStream._readableController, e);
+    }
+  }
+
+  function TransformStreamReadableReadyPromise(transformStream) {
+    assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+
+    if (transformStream._backpressure === false) {
+      return Promise.resolve();
+    }
+
+    assert(transformStream._backpressure === true, '_backpressure should have been initialized');
+    return transformStream._backpressureChangePromise;
+  }
+
+  function TransformStreamSetBackpressure(transformStream, backpressure) {
+    assert(transformStream._backpressure !== backpressure, 'TransformStreamSetBackpressure() should be called only when backpressure is changed');
+
+    if (transformStream._backpressureChangePromise !== undefined) {
+      transformStream._backpressureChangePromise_resolve(backpressure);
+    }
+
+    transformStream._backpressureChangePromise = new Promise(function (resolve) {
+      transformStream._backpressureChangePromise_resolve = resolve;
+    });
+
+    transformStream._backpressureChangePromise.then(function (resolution) {
+      assert(resolution !== backpressure, '_backpressureChangePromise should be fulfilled only when backpressure is changed');
+    });
+
+    transformStream._backpressure = backpressure;
+  }
+
+  function TransformStreamDefaultTransform(chunk, transformStreamController) {
+    var transformStream = transformStreamController._controlledTransformStream;
+    TransformStreamEnqueueToReadable(transformStream, chunk);
+    return Promise.resolve();
+  }
+
+  function TransformStreamTransform(transformStream, chunk) {
+    assert(transformStream._errored === false);
+    assert(transformStream._transforming === false);
+    assert(transformStream._backpressure === false);
+    transformStream._transforming = true;
+    var transformer = transformStream._transformer;
+    var controller = transformStream._transformStreamController;
+    var transformPromise = PromiseInvokeOrPerformFallback(transformer, 'transform', [chunk, controller], TransformStreamDefaultTransform, [chunk, controller]);
+    return transformPromise.then(function () {
+      transformStream._transforming = false;
+      return TransformStreamReadableReadyPromise(transformStream);
+    }, function (e) {
+      TransformStreamErrorIfNeeded(transformStream, e);
+      return Promise.reject(e);
+    });
+  }
+
+  function IsTransformStreamDefaultController(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_controlledTransformStream')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  function IsTransformStream(x) {
+    if (!typeIsObject(x)) {
+      return false;
+    }
+
+    if (!Object.prototype.hasOwnProperty.call(x, '_transformStreamController')) {
+      return false;
+    }
+
+    return true;
+  }
+
+  var TransformStreamSink = function () {
+    function TransformStreamSink(transformStream, startPromise) {
+      _classCallCheck(this, TransformStreamSink);
+
+      this._transformStream = transformStream;
+      this._startPromise = startPromise;
+    }
+
+    _createClass(TransformStreamSink, [{
+      key: 'start',
+      value: function start(c) {
+        var transformStream = this._transformStream;
+        transformStream._writableController = c;
+        return this._startPromise.then(function () {
+          return TransformStreamReadableReadyPromise(transformStream);
+        });
+      }
+    }, {
+      key: 'write',
+      value: function write(chunk) {
+        var transformStream = this._transformStream;
+        return TransformStreamTransform(transformStream, chunk);
+      }
+    }, {
+      key: 'abort',
+      value: function abort() {
+        var transformStream = this._transformStream;
+        transformStream._writableDone = true;
+        TransformStreamErrorInternal(transformStream, new TypeError('Writable side aborted'));
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        var transformStream = this._transformStream;
+        assert(transformStream._transforming === false);
+        transformStream._writableDone = true;
+        var flushPromise = PromiseInvokeOrNoop(transformStream._transformer, 'flush', [transformStream._transformStreamController]);
+        return flushPromise.then(function () {
+          if (transformStream._errored === true) {
+            return Promise.reject(transformStream._storedError);
+          }
+
+          if (transformStream._readableClosed === false) {
+            TransformStreamCloseReadableInternal(transformStream);
+          }
+
+          return Promise.resolve();
+        })["catch"](function (r) {
+          TransformStreamErrorIfNeeded(transformStream, r);
+          return Promise.reject(transformStream._storedError);
+        });
+      }
+    }]);
+
+    return TransformStreamSink;
+  }();
+
+  var TransformStreamSource = function () {
+    function TransformStreamSource(transformStream, startPromise) {
+      _classCallCheck(this, TransformStreamSource);
+
+      this._transformStream = transformStream;
+      this._startPromise = startPromise;
+    }
+
+    _createClass(TransformStreamSource, [{
+      key: 'start',
+      value: function start(c) {
+        var transformStream = this._transformStream;
+        transformStream._readableController = c;
+        return this._startPromise.then(function () {
+          assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+
+          if (transformStream._backpressure === true) {
+            return Promise.resolve();
+          }
+
+          assert(transformStream._backpressure === false, '_backpressure should have been initialized');
+          return transformStream._backpressureChangePromise;
+        });
+      }
+    }, {
+      key: 'pull',
+      value: function pull() {
+        var transformStream = this._transformStream;
+        assert(transformStream._backpressure === true, 'pull() should be never called while _backpressure is false');
+        assert(transformStream._backpressureChangePromise !== undefined, '_backpressureChangePromise should have been initialized');
+        TransformStreamSetBackpressure(transformStream, false);
+        return transformStream._backpressureChangePromise;
+      }
+    }, {
+      key: 'cancel',
+      value: function cancel() {
+        var transformStream = this._transformStream;
+        transformStream._readableClosed = true;
+        TransformStreamErrorInternal(transformStream, new TypeError('Readable side canceled'));
+      }
+    }]);
+
+    return TransformStreamSource;
+  }();
+
+  var TransformStreamDefaultController = function () {
+    function TransformStreamDefaultController(transformStream) {
+      _classCallCheck(this, TransformStreamDefaultController);
+
+      if (IsTransformStream(transformStream) === false) {
+        throw new TypeError('TransformStreamDefaultController can only be ' + 'constructed with a TransformStream instance');
+      }
+
+      if (transformStream._transformStreamController !== undefined) {
+        throw new TypeError('TransformStreamDefaultController instances can ' + 'only be created by the TransformStream constructor');
+      }
+
+      this._controlledTransformStream = transformStream;
+    }
+
+    _createClass(TransformStreamDefaultController, [{
+      key: 'enqueue',
+      value: function enqueue(chunk) {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('enqueue');
+        }
+
+        TransformStreamEnqueueToReadable(this._controlledTransformStream, chunk);
+      }
+    }, {
+      key: 'close',
+      value: function close() {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('close');
+        }
+
+        TransformStreamCloseReadable(this._controlledTransformStream);
+      }
+    }, {
+      key: 'error',
+      value: function error(reason) {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('error');
+        }
+
+        TransformStreamError(this._controlledTransformStream, reason);
+      }
+    }, {
+      key: 'desiredSize',
+      get: function get() {
+        if (IsTransformStreamDefaultController(this) === false) {
+          throw defaultControllerBrandCheckException('desiredSize');
+        }
+
+        var transformStream = this._controlledTransformStream;
+        var readableController = transformStream._readableController;
+        return ReadableStreamDefaultControllerGetDesiredSize(readableController);
+      }
+    }]);
+
+    return TransformStreamDefaultController;
+  }();
+
+  var TransformStream = function () {
+    function TransformStream() {
+      var transformer = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
+
+      _classCallCheck(this, TransformStream);
+
+      this._transformer = transformer;
+      var readableStrategy = transformer.readableStrategy,
+          writableStrategy = transformer.writableStrategy;
+      this._transforming = false;
+      this._errored = false;
+      this._storedError = undefined;
+      this._writableController = undefined;
+      this._readableController = undefined;
+      this._transformStreamController = undefined;
+      this._writableDone = false;
+      this._readableClosed = false;
+      this._backpressure = undefined;
+      this._backpressureChangePromise = undefined;
+      this._backpressureChangePromise_resolve = undefined;
+      this._transformStreamController = new TransformStreamDefaultController(this);
+      var startPromise_resolve = void 0;
+      var startPromise = new Promise(function (resolve) {
+        startPromise_resolve = resolve;
+      });
+      var source = new TransformStreamSource(this, startPromise);
+      this._readable = new ReadableStream(source, readableStrategy);
+      var sink = new TransformStreamSink(this, startPromise);
+      this._writable = new WritableStream(sink, writableStrategy);
+      assert(this._writableController !== undefined);
+      assert(this._readableController !== undefined);
+      var desiredSize = ReadableStreamDefaultControllerGetDesiredSize(this._readableController);
+      TransformStreamSetBackpressure(this, desiredSize <= 0);
+      var transformStream = this;
+      var startResult = InvokeOrNoop(transformer, 'start', [transformStream._transformStreamController]);
+      startPromise_resolve(startResult);
+      startPromise["catch"](function (e) {
+        if (transformStream._errored === false) {
+          transformStream._errored = true;
+          transformStream._storedError = e;
+        }
+      });
+    }
+
+    _createClass(TransformStream, [{
+      key: 'readable',
+      get: function get() {
+        if (IsTransformStream(this) === false) {
+          throw streamBrandCheckException('readable');
+        }
+
+        return this._readable;
+      }
+    }, {
+      key: 'writable',
+      get: function get() {
+        if (IsTransformStream(this) === false) {
+          throw streamBrandCheckException('writable');
+        }
+
+        return this._writable;
+      }
+    }]);
+
+    return TransformStream;
+  }();
+
+  module.exports = {
+    TransformStream: TransformStream
+  };
+
+  function defaultControllerBrandCheckException(name) {
+    return new TypeError('TransformStreamDefaultController.prototype.' + name + ' can only be used on a TransformStreamDefaultController');
+  }
+
+  function streamBrandCheckException(name) {
+    return new TypeError('TransformStream.prototype.' + name + ' can only be used on a TransformStream');
+  }
+}, function (module, exports, __w_pdfjs_require__) {
+  module.exports = __w_pdfjs_require__(5);
+}]));
+
+/***/ }),
+/* 149 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+{
+  var isURLSupported = false;
+
+  try {
+    if (typeof URL === 'function' && _typeof(URL.prototype) === 'object' && 'origin' in URL.prototype) {
+      var u = new URL('b', 'http://a');
+      u.pathname = 'c%20d';
+      isURLSupported = u.href === 'http://a/c%20d';
+    }
+  } catch (ex) {}
+
+  if (isURLSupported) {
+    exports.URL = URL;
+  } else {
+    var PolyfillURL = __w_pdfjs_require__(150).URL;
+
+    var OriginalURL = __w_pdfjs_require__(7).URL;
+
+    if (OriginalURL) {
+      PolyfillURL.createObjectURL = function (blob) {
+        return OriginalURL.createObjectURL.apply(OriginalURL, arguments);
+      };
+
+      PolyfillURL.revokeObjectURL = function (url) {
+        OriginalURL.revokeObjectURL(url);
+      };
+    }
+
+    exports.URL = PolyfillURL;
+  }
+}
+
+/***/ }),
+/* 150 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+(function URLConstructorClosure() {
+  'use strict';
+
+  var relative = Object.create(null);
+  relative['ftp'] = 21;
+  relative['file'] = 0;
+  relative['gopher'] = 70;
+  relative['http'] = 80;
+  relative['https'] = 443;
+  relative['ws'] = 80;
+  relative['wss'] = 443;
+  var relativePathDotMapping = Object.create(null);
+  relativePathDotMapping['%2e'] = '.';
+  relativePathDotMapping['.%2e'] = '..';
+  relativePathDotMapping['%2e.'] = '..';
+  relativePathDotMapping['%2e%2e'] = '..';
+
+  function isRelativeScheme(scheme) {
+    return relative[scheme] !== undefined;
+  }
+
+  function invalid() {
+    clear.call(this);
+    this._isInvalid = true;
+  }
+
+  function IDNAToASCII(h) {
+    if (h === '') {
+      invalid.call(this);
+    }
+
+    return h.toLowerCase();
+  }
+
+  function percentEscape(c) {
+    var unicode = c.charCodeAt(0);
+
+    if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x3F, 0x60].indexOf(unicode) === -1) {
+      return c;
+    }
+
+    return encodeURIComponent(c);
+  }
+
+  function percentEscapeQuery(c) {
+    var unicode = c.charCodeAt(0);
+
+    if (unicode > 0x20 && unicode < 0x7F && [0x22, 0x23, 0x3C, 0x3E, 0x60].indexOf(unicode) === -1) {
+      return c;
+    }
+
+    return encodeURIComponent(c);
+  }
+
+  var EOF,
+      ALPHA = /[a-zA-Z]/,
+      ALPHANUMERIC = /[a-zA-Z0-9\+\-\.]/;
+
+  function parse(input, stateOverride, base) {
+    function err(message) {
+      errors.push(message);
+    }
+
+    var state = stateOverride || 'scheme start',
+        cursor = 0,
+        buffer = '',
+        seenAt = false,
+        seenBracket = false,
+        errors = [];
+
+    loop: while ((input[cursor - 1] !== EOF || cursor === 0) && !this._isInvalid) {
+      var c = input[cursor];
+
+      switch (state) {
+        case 'scheme start':
+          if (c && ALPHA.test(c)) {
+            buffer += c.toLowerCase();
+            state = 'scheme';
+          } else if (!stateOverride) {
+            buffer = '';
+            state = 'no scheme';
+            continue;
+          } else {
+            err('Invalid scheme.');
+            break loop;
+          }
+
+          break;
+
+        case 'scheme':
+          if (c && ALPHANUMERIC.test(c)) {
+            buffer += c.toLowerCase();
+          } else if (c === ':') {
+            this._scheme = buffer;
+            buffer = '';
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            if (isRelativeScheme(this._scheme)) {
+              this._isRelative = true;
+            }
+
+            if (this._scheme === 'file') {
+              state = 'relative';
+            } else if (this._isRelative && base && base._scheme === this._scheme) {
+              state = 'relative or authority';
+            } else if (this._isRelative) {
+              state = 'authority first slash';
+            } else {
+              state = 'scheme data';
+            }
+          } else if (!stateOverride) {
+            buffer = '';
+            cursor = 0;
+            state = 'no scheme';
+            continue;
+          } else if (c === EOF) {
+            break loop;
+          } else {
+            err('Code point not allowed in scheme: ' + c);
+            break loop;
+          }
+
+          break;
+
+        case 'scheme data':
+          if (c === '?') {
+            this._query = '?';
+            state = 'query';
+          } else if (c === '#') {
+            this._fragment = '#';
+            state = 'fragment';
+          } else {
+            if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+              this._schemeData += percentEscape(c);
+            }
+          }
+
+          break;
+
+        case 'no scheme':
+          if (!base || !isRelativeScheme(base._scheme)) {
+            err('Missing scheme.');
+            invalid.call(this);
+          } else {
+            state = 'relative';
+            continue;
+          }
+
+          break;
+
+        case 'relative or authority':
+          if (c === '/' && input[cursor + 1] === '/') {
+            state = 'authority ignore slashes';
+          } else {
+            err('Expected /, got: ' + c);
+            state = 'relative';
+            continue;
+          }
+
+          break;
+
+        case 'relative':
+          this._isRelative = true;
+
+          if (this._scheme !== 'file') {
+            this._scheme = base._scheme;
+          }
+
+          if (c === EOF) {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            this._username = base._username;
+            this._password = base._password;
+            break loop;
+          } else if (c === '/' || c === '\\') {
+            if (c === '\\') {
+              err('\\ is an invalid code point.');
+            }
+
+            state = 'relative slash';
+          } else if (c === '?') {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = '?';
+            this._username = base._username;
+            this._password = base._password;
+            state = 'query';
+          } else if (c === '#') {
+            this._host = base._host;
+            this._port = base._port;
+            this._path = base._path.slice();
+            this._query = base._query;
+            this._fragment = '#';
+            this._username = base._username;
+            this._password = base._password;
+            state = 'fragment';
+          } else {
+            var nextC = input[cursor + 1];
+            var nextNextC = input[cursor + 2];
+
+            if (this._scheme !== 'file' || !ALPHA.test(c) || nextC !== ':' && nextC !== '|' || nextNextC !== EOF && nextNextC !== '/' && nextNextC !== '\\' && nextNextC !== '?' && nextNextC !== '#') {
+              this._host = base._host;
+              this._port = base._port;
+              this._username = base._username;
+              this._password = base._password;
+              this._path = base._path.slice();
+
+              this._path.pop();
+            }
+
+            state = 'relative path';
+            continue;
+          }
+
+          break;
+
+        case 'relative slash':
+          if (c === '/' || c === '\\') {
+            if (c === '\\') {
+              err('\\ is an invalid code point.');
+            }
+
+            if (this._scheme === 'file') {
+              state = 'file host';
+            } else {
+              state = 'authority ignore slashes';
+            }
+          } else {
+            if (this._scheme !== 'file') {
+              this._host = base._host;
+              this._port = base._port;
+              this._username = base._username;
+              this._password = base._password;
+            }
+
+            state = 'relative path';
+            continue;
+          }
+
+          break;
+
+        case 'authority first slash':
+          if (c === '/') {
+            state = 'authority second slash';
+          } else {
+            err('Expected \'/\', got: ' + c);
+            state = 'authority ignore slashes';
+            continue;
+          }
+
+          break;
+
+        case 'authority second slash':
+          state = 'authority ignore slashes';
+
+          if (c !== '/') {
+            err('Expected \'/\', got: ' + c);
+            continue;
+          }
+
+          break;
+
+        case 'authority ignore slashes':
+          if (c !== '/' && c !== '\\') {
+            state = 'authority';
+            continue;
+          } else {
+            err('Expected authority, got: ' + c);
+          }
+
+          break;
+
+        case 'authority':
+          if (c === '@') {
+            if (seenAt) {
+              err('@ already seen.');
+              buffer += '%40';
+            }
+
+            seenAt = true;
+
+            for (var i = 0; i < buffer.length; i++) {
+              var cp = buffer[i];
+
+              if (cp === '\t' || cp === '\n' || cp === '\r') {
+                err('Invalid whitespace in authority.');
+                continue;
+              }
+
+              if (cp === ':' && this._password === null) {
+                this._password = '';
+                continue;
+              }
+
+              var tempC = percentEscape(cp);
+
+              if (this._password !== null) {
+                this._password += tempC;
+              } else {
+                this._username += tempC;
+              }
+            }
+
+            buffer = '';
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            cursor -= buffer.length;
+            buffer = '';
+            state = 'host';
+            continue;
+          } else {
+            buffer += c;
+          }
+
+          break;
+
+        case 'file host':
+          if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            if (buffer.length === 2 && ALPHA.test(buffer[0]) && (buffer[1] === ':' || buffer[1] === '|')) {
+              state = 'relative path';
+            } else if (buffer.length === 0) {
+              state = 'relative path start';
+            } else {
+              this._host = IDNAToASCII.call(this, buffer);
+              buffer = '';
+              state = 'relative path start';
+            }
+
+            continue;
+          } else if (c === '\t' || c === '\n' || c === '\r') {
+            err('Invalid whitespace in file host.');
+          } else {
+            buffer += c;
+          }
+
+          break;
+
+        case 'host':
+        case 'hostname':
+          if (c === ':' && !seenBracket) {
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'port';
+
+            if (stateOverride === 'hostname') {
+              break loop;
+            }
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#') {
+            this._host = IDNAToASCII.call(this, buffer);
+            buffer = '';
+            state = 'relative path start';
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            continue;
+          } else if (c !== '\t' && c !== '\n' && c !== '\r') {
+            if (c === '[') {
+              seenBracket = true;
+            } else if (c === ']') {
+              seenBracket = false;
+            }
+
+            buffer += c;
+          } else {
+            err('Invalid code point in host/hostname: ' + c);
+          }
+
+          break;
+
+        case 'port':
+          if (/[0-9]/.test(c)) {
+            buffer += c;
+          } else if (c === EOF || c === '/' || c === '\\' || c === '?' || c === '#' || stateOverride) {
+            if (buffer !== '') {
+              var temp = parseInt(buffer, 10);
+
+              if (temp !== relative[this._scheme]) {
+                this._port = temp + '';
+              }
+
+              buffer = '';
+            }
+
+            if (stateOverride) {
+              break loop;
+            }
+
+            state = 'relative path start';
+            continue;
+          } else if (c === '\t' || c === '\n' || c === '\r') {
+            err('Invalid code point in port: ' + c);
+          } else {
+            invalid.call(this);
+          }
+
+          break;
+
+        case 'relative path start':
+          if (c === '\\') {
+            err('\'\\\' not allowed in path.');
+          }
+
+          state = 'relative path';
+
+          if (c !== '/' && c !== '\\') {
+            continue;
+          }
+
+          break;
+
+        case 'relative path':
+          if (c === EOF || c === '/' || c === '\\' || !stateOverride && (c === '?' || c === '#')) {
+            if (c === '\\') {
+              err('\\ not allowed in relative path.');
+            }
+
+            var tmp;
+
+            if (tmp = relativePathDotMapping[buffer.toLowerCase()]) {
+              buffer = tmp;
+            }
+
+            if (buffer === '..') {
+              this._path.pop();
+
+              if (c !== '/' && c !== '\\') {
+                this._path.push('');
+              }
+            } else if (buffer === '.' && c !== '/' && c !== '\\') {
+              this._path.push('');
+            } else if (buffer !== '.') {
+              if (this._scheme === 'file' && this._path.length === 0 && buffer.length === 2 && ALPHA.test(buffer[0]) && buffer[1] === '|') {
+                buffer = buffer[0] + ':';
+              }
+
+              this._path.push(buffer);
+            }
+
+            buffer = '';
+
+            if (c === '?') {
+              this._query = '?';
+              state = 'query';
+            } else if (c === '#') {
+              this._fragment = '#';
+              state = 'fragment';
+            }
+          } else if (c !== '\t' && c !== '\n' && c !== '\r') {
+            buffer += percentEscape(c);
+          }
+
+          break;
+
+        case 'query':
+          if (!stateOverride && c === '#') {
+            this._fragment = '#';
+            state = 'fragment';
+          } else if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+            this._query += percentEscapeQuery(c);
+          }
+
+          break;
+
+        case 'fragment':
+          if (c !== EOF && c !== '\t' && c !== '\n' && c !== '\r') {
+            this._fragment += c;
+          }
+
+          break;
+      }
+
+      cursor++;
+    }
+  }
+
+  function clear() {
+    this._scheme = '';
+    this._schemeData = '';
+    this._username = '';
+    this._password = null;
+    this._host = '';
+    this._port = '';
+    this._path = [];
+    this._query = '';
+    this._fragment = '';
+    this._isInvalid = false;
+    this._isRelative = false;
+  }
+
+  function JURL(url, base) {
+    if (base !== undefined && !(base instanceof JURL)) {
+      base = new JURL(String(base));
+    }
+
+    this._url = url;
+    clear.call(this);
+    var input = url.replace(/^[ \t\r\n\f]+|[ \t\r\n\f]+$/g, '');
+    parse.call(this, input, null, base);
+  }
+
+  JURL.prototype = {
+    toString: function toString() {
+      return this.href;
+    },
+
+    get href() {
+      if (this._isInvalid) {
+        return this._url;
+      }
+
+      var authority = '';
+
+      if (this._username !== '' || this._password !== null) {
+        authority = this._username + (this._password !== null ? ':' + this._password : '') + '@';
+      }
+
+      return this.protocol + (this._isRelative ? '//' + authority + this.host : '') + this.pathname + this._query + this._fragment;
+    },
+
+    set href(value) {
+      clear.call(this);
+      parse.call(this, value);
+    },
+
+    get protocol() {
+      return this._scheme + ':';
+    },
+
+    set protocol(value) {
+      if (this._isInvalid) {
+        return;
+      }
+
+      parse.call(this, value + ':', 'scheme start');
+    },
+
+    get host() {
+      return this._isInvalid ? '' : this._port ? this._host + ':' + this._port : this._host;
+    },
+
+    set host(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'host');
+    },
+
+    get hostname() {
+      return this._host;
+    },
+
+    set hostname(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'hostname');
+    },
+
+    get port() {
+      return this._port;
+    },
+
+    set port(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      parse.call(this, value, 'port');
+    },
+
+    get pathname() {
+      return this._isInvalid ? '' : this._isRelative ? '/' + this._path.join('/') : this._schemeData;
+    },
+
+    set pathname(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      this._path = [];
+      parse.call(this, value, 'relative path start');
+    },
+
+    get search() {
+      return this._isInvalid || !this._query || this._query === '?' ? '' : this._query;
+    },
+
+    set search(value) {
+      if (this._isInvalid || !this._isRelative) {
+        return;
+      }
+
+      this._query = '?';
+
+      if (value[0] === '?') {
+        value = value.slice(1);
+      }
+
+      parse.call(this, value, 'query');
+    },
+
+    get hash() {
+      return this._isInvalid || !this._fragment || this._fragment === '#' ? '' : this._fragment;
+    },
+
+    set hash(value) {
+      if (this._isInvalid) {
+        return;
+      }
+
+      this._fragment = '#';
+
+      if (value[0] === '#') {
+        value = value.slice(1);
+      }
+
+      parse.call(this, value, 'fragment');
+    },
+
+    get origin() {
+      var host;
+
+      if (this._isInvalid || !this._scheme) {
+        return '';
+      }
+
+      switch (this._scheme) {
+        case 'data':
+        case 'file':
+        case 'javascript':
+        case 'mailto':
+          return 'null';
+
+        case 'blob':
+          try {
+            return new JURL(this._schemeData).origin || 'null';
+          } catch (_) {}
+
+          return 'null';
+      }
+
+      host = this.host;
+
+      if (!host) {
+        return '';
+      }
+
+      return this._scheme + '://' + host;
+    }
+
+  };
+  exports.URL = JURL;
+})();
+
+/***/ }),
+/* 151 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.clearPrimitiveCaches = clearPrimitiveCaches;
+exports.isEOF = isEOF;
+exports.isCmd = isCmd;
+exports.isDict = isDict;
+exports.isName = isName;
+exports.isRef = isRef;
+exports.isRefsEqual = isRefsEqual;
+exports.isStream = isStream;
+exports.RefSetCache = exports.RefSet = exports.Ref = exports.Name = exports.Dict = exports.Cmd = exports.EOF = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var EOF = {};
+exports.EOF = EOF;
+
+var Name = function NameClosure() {
+  var nameCache = Object.create(null);
+
+  function Name(name) {
+    this.name = name;
+  }
+
+  Name.prototype = {};
+
+  Name.get = function Name_get(name) {
+    var nameValue = nameCache[name];
+    return nameValue ? nameValue : nameCache[name] = new Name(name);
+  };
+
+  Name._clearCache = function () {
+    nameCache = Object.create(null);
+  };
+
+  return Name;
+}();
+
+exports.Name = Name;
+
+var Cmd = function CmdClosure() {
+  var cmdCache = Object.create(null);
+
+  function Cmd(cmd) {
+    this.cmd = cmd;
+  }
+
+  Cmd.prototype = {};
+
+  Cmd.get = function Cmd_get(cmd) {
+    var cmdValue = cmdCache[cmd];
+    return cmdValue ? cmdValue : cmdCache[cmd] = new Cmd(cmd);
+  };
+
+  Cmd._clearCache = function () {
+    cmdCache = Object.create(null);
+  };
+
+  return Cmd;
+}();
+
+exports.Cmd = Cmd;
+
+var Dict = function DictClosure() {
+  var nonSerializable = function nonSerializableClosure() {
+    return nonSerializable;
+  };
+
+  function Dict(xref) {
+    this._map = Object.create(null);
+    this.xref = xref;
+    this.objId = null;
+    this.suppressEncryption = false;
+    this.__nonSerializable__ = nonSerializable;
+  }
+
+  Dict.prototype = {
+    assignXref: function Dict_assignXref(newXref) {
+      this.xref = newXref;
+    },
+    get: function Dict_get(key1, key2, key3) {
+      var value;
+      var xref = this.xref,
+          suppressEncryption = this.suppressEncryption;
+
+      if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
+        return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
+      }
+
+      if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
+        return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
+      }
+
+      value = this._map[key3] || null;
+      return xref ? xref.fetchIfRef(value, suppressEncryption) : value;
+    },
+    getAsync: function Dict_getAsync(key1, key2, key3) {
+      var value;
+      var xref = this.xref,
+          suppressEncryption = this.suppressEncryption;
+
+      if (typeof (value = this._map[key1]) !== 'undefined' || key1 in this._map || typeof key2 === 'undefined') {
+        if (xref) {
+          return xref.fetchIfRefAsync(value, suppressEncryption);
+        }
+
+        return Promise.resolve(value);
+      }
+
+      if (typeof (value = this._map[key2]) !== 'undefined' || key2 in this._map || typeof key3 === 'undefined') {
+        if (xref) {
+          return xref.fetchIfRefAsync(value, suppressEncryption);
+        }
+
+        return Promise.resolve(value);
+      }
+
+      value = this._map[key3] || null;
+
+      if (xref) {
+        return xref.fetchIfRefAsync(value, suppressEncryption);
+      }
+
+      return Promise.resolve(value);
+    },
+    getArray: function Dict_getArray(key1, key2, key3) {
+      var value = this.get(key1, key2, key3);
+      var xref = this.xref,
+          suppressEncryption = this.suppressEncryption;
+
+      if (!Array.isArray(value) || !xref) {
+        return value;
+      }
+
+      value = value.slice();
+
+      for (var i = 0, ii = value.length; i < ii; i++) {
+        if (!isRef(value[i])) {
+          continue;
+        }
+
+        value[i] = xref.fetch(value[i], suppressEncryption);
+      }
+
+      return value;
+    },
+    getRaw: function Dict_getRaw(key) {
+      return this._map[key];
+    },
+    getKeys: function Dict_getKeys() {
+      return Object.keys(this._map);
+    },
+    set: function Dict_set(key, value) {
+      this._map[key] = value;
+    },
+    has: function Dict_has(key) {
+      return key in this._map;
+    },
+    forEach: function Dict_forEach(callback) {
+      for (var key in this._map) {
+        callback(key, this.get(key));
+      }
+    }
+  };
+  Dict.empty = new Dict(null);
+
+  Dict.merge = function (xref, dictArray) {
+    var mergedDict = new Dict(xref);
+
+    for (var i = 0, ii = dictArray.length; i < ii; i++) {
+      var dict = dictArray[i];
+
+      if (!isDict(dict)) {
+        continue;
+      }
+
+      for (var keyName in dict._map) {
+        if (mergedDict._map[keyName] !== undefined) {
+          continue;
+        }
+
+        mergedDict._map[keyName] = dict._map[keyName];
+      }
+    }
+
+    return mergedDict;
+  };
+
+  return Dict;
+}();
+
+exports.Dict = Dict;
+
+var Ref = function RefClosure() {
+  var refCache = Object.create(null);
+
+  function Ref(num, gen) {
+    this.num = num;
+    this.gen = gen;
+  }
+
+  Ref.prototype = {
+    toString: function Ref_toString() {
+      if (this.gen === 0) {
+        return "".concat(this.num, "R");
+      }
+
+      return "".concat(this.num, "R").concat(this.gen);
+    }
+  };
+
+  Ref.get = function (num, gen) {
+    var key = gen === 0 ? "".concat(num, "R") : "".concat(num, "R").concat(gen);
+    var refValue = refCache[key];
+    return refValue ? refValue : refCache[key] = new Ref(num, gen);
+  };
+
+  Ref._clearCache = function () {
+    refCache = Object.create(null);
+  };
+
+  return Ref;
+}();
+
+exports.Ref = Ref;
+
+var RefSet = function RefSetClosure() {
+  function RefSet() {
+    this.dict = Object.create(null);
+  }
+
+  RefSet.prototype = {
+    has: function RefSet_has(ref) {
+      return ref.toString() in this.dict;
+    },
+    put: function RefSet_put(ref) {
+      this.dict[ref.toString()] = true;
+    },
+    remove: function RefSet_remove(ref) {
+      delete this.dict[ref.toString()];
+    }
+  };
+  return RefSet;
+}();
+
+exports.RefSet = RefSet;
+
+var RefSetCache = function RefSetCacheClosure() {
+  function RefSetCache() {
+    this.dict = Object.create(null);
+  }
+
+  RefSetCache.prototype = {
+    get: function RefSetCache_get(ref) {
+      return this.dict[ref.toString()];
+    },
+    has: function RefSetCache_has(ref) {
+      return ref.toString() in this.dict;
+    },
+    put: function RefSetCache_put(ref, obj) {
+      this.dict[ref.toString()] = obj;
+    },
+    putAlias: function RefSetCache_putAlias(ref, aliasRef) {
+      this.dict[ref.toString()] = this.get(aliasRef);
+    },
+    forEach: function RefSetCache_forEach(fn, thisArg) {
+      for (var i in this.dict) {
+        fn.call(thisArg, this.dict[i]);
+      }
+    },
+    clear: function RefSetCache_clear() {
+      this.dict = Object.create(null);
+    }
+  };
+  return RefSetCache;
+}();
+
+exports.RefSetCache = RefSetCache;
+
+function isEOF(v) {
+  return v === EOF;
+}
+
+function isName(v, name) {
+  return v instanceof Name && (name === undefined || v.name === name);
+}
+
+function isCmd(v, cmd) {
+  return v instanceof Cmd && (cmd === undefined || v.cmd === cmd);
+}
+
+function isDict(v, type) {
+  return v instanceof Dict && (type === undefined || isName(v.get('Type'), type));
+}
+
+function isRef(v) {
+  return v instanceof Ref;
+}
+
+function isRefsEqual(v1, v2) {
+  return v1.num === v2.num && v1.gen === v2.gen;
+}
+
+function isStream(v) {
+  return _typeof(v) === 'object' && v !== null && v.getBytes !== undefined;
+}
+
+function clearPrimitiveCaches() {
+  Cmd._clearCache();
+
+  Name._clearCache();
+
+  Ref._clearCache();
+}
+
+/***/ }),
+/* 152 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.NetworkPdfManager = exports.LocalPdfManager = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+var _chunked_stream = __w_pdfjs_require__(153);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _document = __w_pdfjs_require__(155);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var BasePdfManager =
+/*#__PURE__*/
+function () {
+  function BasePdfManager() {
+    _classCallCheck(this, BasePdfManager);
+
+    if (this.constructor === BasePdfManager) {
+      (0, _util.unreachable)('Cannot initialize BasePdfManager.');
+    }
+  }
+
+  _createClass(BasePdfManager, [{
+    key: "onLoadedStream",
+    value: function onLoadedStream() {
+      (0, _util.unreachable)('Abstract method `onLoadedStream` called');
+    }
+  }, {
+    key: "ensureDoc",
+    value: function ensureDoc(prop, args) {
+      return this.ensure(this.pdfDocument, prop, args);
+    }
+  }, {
+    key: "ensureXRef",
+    value: function ensureXRef(prop, args) {
+      return this.ensure(this.pdfDocument.xref, prop, args);
+    }
+  }, {
+    key: "ensureCatalog",
+    value: function ensureCatalog(prop, args) {
+      return this.ensure(this.pdfDocument.catalog, prop, args);
+    }
+  }, {
+    key: "getPage",
+    value: function getPage(pageIndex) {
+      return this.pdfDocument.getPage(pageIndex);
+    }
+  }, {
+    key: "fontFallback",
+    value: function fontFallback(id, handler) {
+      return this.pdfDocument.fontFallback(id, handler);
+    }
+  }, {
+    key: "cleanup",
+    value: function cleanup() {
+      return this.pdfDocument.cleanup();
+    }
+  }, {
+    key: "ensure",
+    value: function () {
+      var _ensure = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee(obj, prop, args) {
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                (0, _util.unreachable)('Abstract method `ensure` called');
+
+              case 1:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee);
+      }));
+
+      function ensure(_x, _x2, _x3) {
+        return _ensure.apply(this, arguments);
+      }
+
+      return ensure;
+    }()
+  }, {
+    key: "requestRange",
+    value: function requestRange(begin, end) {
+      (0, _util.unreachable)('Abstract method `requestRange` called');
+    }
+  }, {
+    key: "requestLoadedStream",
+    value: function requestLoadedStream() {
+      (0, _util.unreachable)('Abstract method `requestLoadedStream` called');
+    }
+  }, {
+    key: "sendProgressiveData",
+    value: function sendProgressiveData(chunk) {
+      (0, _util.unreachable)('Abstract method `sendProgressiveData` called');
+    }
+  }, {
+    key: "updatePassword",
+    value: function updatePassword(password) {
+      this._password = password;
+    }
+  }, {
+    key: "terminate",
+    value: function terminate() {
+      (0, _util.unreachable)('Abstract method `terminate` called');
+    }
+  }, {
+    key: "docId",
+    get: function get() {
+      return this._docId;
+    }
+  }, {
+    key: "password",
+    get: function get() {
+      return this._password;
+    }
+  }, {
+    key: "docBaseUrl",
+    get: function get() {
+      var docBaseUrl = null;
+
+      if (this._docBaseUrl) {
+        var absoluteUrl = (0, _util.createValidAbsoluteUrl)(this._docBaseUrl);
+
+        if (absoluteUrl) {
+          docBaseUrl = absoluteUrl.href;
+        } else {
+          (0, _util.warn)("Invalid absolute docBaseUrl: \"".concat(this._docBaseUrl, "\"."));
+        }
+      }
+
+      return (0, _util.shadow)(this, 'docBaseUrl', docBaseUrl);
+    }
+  }]);
+
+  return BasePdfManager;
+}();
+
+var LocalPdfManager =
+/*#__PURE__*/
+function (_BasePdfManager) {
+  _inherits(LocalPdfManager, _BasePdfManager);
+
+  function LocalPdfManager(docId, data, password, evaluatorOptions, docBaseUrl) {
+    var _this;
+
+    _classCallCheck(this, LocalPdfManager);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(LocalPdfManager).call(this));
+    _this._docId = docId;
+    _this._password = password;
+    _this._docBaseUrl = docBaseUrl;
+    _this.evaluatorOptions = evaluatorOptions;
+    var stream = new _stream.Stream(data);
+    _this.pdfDocument = new _document.PDFDocument(_assertThisInitialized(_this), stream);
+    _this._loadedStreamPromise = Promise.resolve(stream);
+    return _this;
+  }
+
+  _createClass(LocalPdfManager, [{
+    key: "ensure",
+    value: function () {
+      var _ensure2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2(obj, prop, args) {
+        var value;
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                value = obj[prop];
+
+                if (!(typeof value === 'function')) {
+                  _context2.next = 3;
+                  break;
+                }
+
+                return _context2.abrupt("return", value.apply(obj, args));
+
+              case 3:
+                return _context2.abrupt("return", value);
+
+              case 4:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2);
+      }));
+
+      function ensure(_x4, _x5, _x6) {
+        return _ensure2.apply(this, arguments);
+      }
+
+      return ensure;
+    }()
+  }, {
+    key: "requestRange",
+    value: function requestRange(begin, end) {
+      return Promise.resolve();
+    }
+  }, {
+    key: "requestLoadedStream",
+    value: function requestLoadedStream() {}
+  }, {
+    key: "onLoadedStream",
+    value: function onLoadedStream() {
+      return this._loadedStreamPromise;
+    }
+  }, {
+    key: "terminate",
+    value: function terminate() {}
+  }]);
+
+  return LocalPdfManager;
+}(BasePdfManager);
+
+exports.LocalPdfManager = LocalPdfManager;
+
+var NetworkPdfManager =
+/*#__PURE__*/
+function (_BasePdfManager2) {
+  _inherits(NetworkPdfManager, _BasePdfManager2);
+
+  function NetworkPdfManager(docId, pdfNetworkStream, args, evaluatorOptions, docBaseUrl) {
+    var _this2;
+
+    _classCallCheck(this, NetworkPdfManager);
+
+    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(NetworkPdfManager).call(this));
+    _this2._docId = docId;
+    _this2._password = args.password;
+    _this2._docBaseUrl = docBaseUrl;
+    _this2.msgHandler = args.msgHandler;
+    _this2.evaluatorOptions = evaluatorOptions;
+    _this2.streamManager = new _chunked_stream.ChunkedStreamManager(pdfNetworkStream, {
+      msgHandler: args.msgHandler,
+      length: args.length,
+      disableAutoFetch: args.disableAutoFetch,
+      rangeChunkSize: args.rangeChunkSize
+    });
+    _this2.pdfDocument = new _document.PDFDocument(_assertThisInitialized(_this2), _this2.streamManager.getStream());
+    return _this2;
+  }
+
+  _createClass(NetworkPdfManager, [{
+    key: "ensure",
+    value: function () {
+      var _ensure3 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee3(obj, prop, args) {
+        var value;
+        return _regenerator["default"].wrap(function _callee3$(_context3) {
+          while (1) {
+            switch (_context3.prev = _context3.next) {
+              case 0:
+                _context3.prev = 0;
+                value = obj[prop];
+
+                if (!(typeof value === 'function')) {
+                  _context3.next = 4;
+                  break;
+                }
+
+                return _context3.abrupt("return", value.apply(obj, args));
+
+              case 4:
+                return _context3.abrupt("return", value);
+
+              case 7:
+                _context3.prev = 7;
+                _context3.t0 = _context3["catch"](0);
+
+                if (_context3.t0 instanceof _core_utils.MissingDataException) {
+                  _context3.next = 11;
+                  break;
+                }
+
+                throw _context3.t0;
+
+              case 11:
+                _context3.next = 13;
+                return this.requestRange(_context3.t0.begin, _context3.t0.end);
+
+              case 13:
+                return _context3.abrupt("return", this.ensure(obj, prop, args));
+
+              case 14:
+              case "end":
+                return _context3.stop();
+            }
+          }
+        }, _callee3, this, [[0, 7]]);
+      }));
+
+      function ensure(_x7, _x8, _x9) {
+        return _ensure3.apply(this, arguments);
+      }
+
+      return ensure;
+    }()
+  }, {
+    key: "requestRange",
+    value: function requestRange(begin, end) {
+      return this.streamManager.requestRange(begin, end);
+    }
+  }, {
+    key: "requestLoadedStream",
+    value: function requestLoadedStream() {
+      this.streamManager.requestAllChunks();
+    }
+  }, {
+    key: "sendProgressiveData",
+    value: function sendProgressiveData(chunk) {
+      this.streamManager.onReceiveData({
+        chunk: chunk
+      });
+    }
+  }, {
+    key: "onLoadedStream",
+    value: function onLoadedStream() {
+      return this.streamManager.onLoadedStream();
+    }
+  }, {
+    key: "terminate",
+    value: function terminate() {
+      this.streamManager.abort();
+    }
+  }]);
+
+  return NetworkPdfManager;
+}(BasePdfManager);
+
+exports.NetworkPdfManager = NetworkPdfManager;
+
+/***/ }),
+/* 153 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ChunkedStreamManager = exports.ChunkedStream = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var ChunkedStream =
+/*#__PURE__*/
+function () {
+  function ChunkedStream(length, chunkSize, manager) {
+    _classCallCheck(this, ChunkedStream);
+
+    this.bytes = new Uint8Array(length);
+    this.start = 0;
+    this.pos = 0;
+    this.end = length;
+    this.chunkSize = chunkSize;
+    this.loadedChunks = [];
+    this.numChunksLoaded = 0;
+    this.numChunks = Math.ceil(length / chunkSize);
+    this.manager = manager;
+    this.progressiveDataLength = 0;
+    this.lastSuccessfulEnsureByteChunk = -1;
+  }
+
+  _createClass(ChunkedStream, [{
+    key: "getMissingChunks",
+    value: function getMissingChunks() {
+      var chunks = [];
+
+      for (var chunk = 0, n = this.numChunks; chunk < n; ++chunk) {
+        if (!this.loadedChunks[chunk]) {
+          chunks.push(chunk);
+        }
+      }
+
+      return chunks;
+    }
+  }, {
+    key: "getBaseStreams",
+    value: function getBaseStreams() {
+      return [this];
+    }
+  }, {
+    key: "allChunksLoaded",
+    value: function allChunksLoaded() {
+      return this.numChunksLoaded === this.numChunks;
+    }
+  }, {
+    key: "onReceiveData",
+    value: function onReceiveData(begin, chunk) {
+      var chunkSize = this.chunkSize;
+
+      if (begin % chunkSize !== 0) {
+        throw new Error("Bad begin offset: ".concat(begin));
+      }
+
+      var end = begin + chunk.byteLength;
+
+      if (end % chunkSize !== 0 && end !== this.bytes.length) {
+        throw new Error("Bad end offset: ".concat(end));
+      }
+
+      this.bytes.set(new Uint8Array(chunk), begin);
+      var beginChunk = Math.floor(begin / chunkSize);
+      var endChunk = Math.floor((end - 1) / chunkSize) + 1;
+
+      for (var curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+        if (!this.loadedChunks[curChunk]) {
+          this.loadedChunks[curChunk] = true;
+          ++this.numChunksLoaded;
+        }
+      }
+    }
+  }, {
+    key: "onReceiveProgressiveData",
+    value: function onReceiveProgressiveData(data) {
+      var position = this.progressiveDataLength;
+      var beginChunk = Math.floor(position / this.chunkSize);
+      this.bytes.set(new Uint8Array(data), position);
+      position += data.byteLength;
+      this.progressiveDataLength = position;
+      var endChunk = position >= this.end ? this.numChunks : Math.floor(position / this.chunkSize);
+
+      for (var curChunk = beginChunk; curChunk < endChunk; ++curChunk) {
+        if (!this.loadedChunks[curChunk]) {
+          this.loadedChunks[curChunk] = true;
+          ++this.numChunksLoaded;
+        }
+      }
+    }
+  }, {
+    key: "ensureByte",
+    value: function ensureByte(pos) {
+      if (pos < this.progressiveDataLength) {
+        return;
+      }
+
+      var chunk = Math.floor(pos / this.chunkSize);
+
+      if (chunk === this.lastSuccessfulEnsureByteChunk) {
+        return;
+      }
+
+      if (!this.loadedChunks[chunk]) {
+        throw new _core_utils.MissingDataException(pos, pos + 1);
+      }
+
+      this.lastSuccessfulEnsureByteChunk = chunk;
+    }
+  }, {
+    key: "ensureRange",
+    value: function ensureRange(begin, end) {
+      if (begin >= end) {
+        return;
+      }
+
+      if (end <= this.progressiveDataLength) {
+        return;
+      }
+
+      var chunkSize = this.chunkSize;
+      var beginChunk = Math.floor(begin / chunkSize);
+      var endChunk = Math.floor((end - 1) / chunkSize) + 1;
+
+      for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
+        if (!this.loadedChunks[chunk]) {
+          throw new _core_utils.MissingDataException(begin, end);
+        }
+      }
+    }
+  }, {
+    key: "nextEmptyChunk",
+    value: function nextEmptyChunk(beginChunk) {
+      var numChunks = this.numChunks;
+
+      for (var i = 0; i < numChunks; ++i) {
+        var chunk = (beginChunk + i) % numChunks;
+
+        if (!this.loadedChunks[chunk]) {
+          return chunk;
+        }
+      }
+
+      return null;
+    }
+  }, {
+    key: "hasChunk",
+    value: function hasChunk(chunk) {
+      return !!this.loadedChunks[chunk];
+    }
+  }, {
+    key: "getByte",
+    value: function getByte() {
+      var pos = this.pos;
+
+      if (pos >= this.end) {
+        return -1;
+      }
+
+      this.ensureByte(pos);
+      return this.bytes[this.pos++];
+    }
+  }, {
+    key: "getUint16",
+    value: function getUint16() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+
+      if (b0 === -1 || b1 === -1) {
+        return -1;
+      }
+
+      return (b0 << 8) + b1;
+    }
+  }, {
+    key: "getInt32",
+    value: function getInt32() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+      var b2 = this.getByte();
+      var b3 = this.getByte();
+      return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+    }
+  }, {
+    key: "getBytes",
+    value: function getBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var bytes = this.bytes;
+      var pos = this.pos;
+      var strEnd = this.end;
+
+      if (!length) {
+        this.ensureRange(pos, strEnd);
+
+        var _subarray = bytes.subarray(pos, strEnd);
+
+        return forceClamped ? new Uint8ClampedArray(_subarray) : _subarray;
+      }
+
+      var end = pos + length;
+
+      if (end > strEnd) {
+        end = strEnd;
+      }
+
+      this.ensureRange(pos, end);
+      this.pos = end;
+      var subarray = bytes.subarray(pos, end);
+      return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
+    }
+  }, {
+    key: "peekByte",
+    value: function peekByte() {
+      var peekedByte = this.getByte();
+      this.pos--;
+      return peekedByte;
+    }
+  }, {
+    key: "peekBytes",
+    value: function peekBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var bytes = this.getBytes(length, forceClamped);
+      this.pos -= bytes.length;
+      return bytes;
+    }
+  }, {
+    key: "getByteRange",
+    value: function getByteRange(begin, end) {
+      this.ensureRange(begin, end);
+      return this.bytes.subarray(begin, end);
+    }
+  }, {
+    key: "skip",
+    value: function skip(n) {
+      if (!n) {
+        n = 1;
+      }
+
+      this.pos += n;
+    }
+  }, {
+    key: "reset",
+    value: function reset() {
+      this.pos = this.start;
+    }
+  }, {
+    key: "moveStart",
+    value: function moveStart() {
+      this.start = this.pos;
+    }
+  }, {
+    key: "makeSubStream",
+    value: function makeSubStream(start, length, dict) {
+      if (length) {
+        this.ensureRange(start, start + length);
+      } else {
+        this.ensureByte(start);
+      }
+
+      function ChunkedStreamSubstream() {}
+
+      ChunkedStreamSubstream.prototype = Object.create(this);
+
+      ChunkedStreamSubstream.prototype.getMissingChunks = function () {
+        var chunkSize = this.chunkSize;
+        var beginChunk = Math.floor(this.start / chunkSize);
+        var endChunk = Math.floor((this.end - 1) / chunkSize) + 1;
+        var missingChunks = [];
+
+        for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
+          if (!this.loadedChunks[chunk]) {
+            missingChunks.push(chunk);
+          }
+        }
+
+        return missingChunks;
+      };
+
+      var subStream = new ChunkedStreamSubstream();
+      subStream.pos = subStream.start = start;
+      subStream.end = start + length || this.end;
+      subStream.dict = dict;
+      return subStream;
+    }
+  }, {
+    key: "length",
+    get: function get() {
+      return this.end - this.start;
+    }
+  }, {
+    key: "isEmpty",
+    get: function get() {
+      return this.length === 0;
+    }
+  }]);
+
+  return ChunkedStream;
+}();
+
+exports.ChunkedStream = ChunkedStream;
+
+var ChunkedStreamManager =
+/*#__PURE__*/
+function () {
+  function ChunkedStreamManager(pdfNetworkStream, args) {
+    _classCallCheck(this, ChunkedStreamManager);
+
+    this.length = args.length;
+    this.chunkSize = args.rangeChunkSize;
+    this.stream = new ChunkedStream(this.length, this.chunkSize, this);
+    this.pdfNetworkStream = pdfNetworkStream;
+    this.disableAutoFetch = args.disableAutoFetch;
+    this.msgHandler = args.msgHandler;
+    this.currRequestId = 0;
+    this.chunksNeededByRequest = Object.create(null);
+    this.requestsByChunk = Object.create(null);
+    this.promisesByRequest = Object.create(null);
+    this.progressiveDataLength = 0;
+    this.aborted = false;
+    this._loadedStreamCapability = (0, _util.createPromiseCapability)();
+  }
+
+  _createClass(ChunkedStreamManager, [{
+    key: "onLoadedStream",
+    value: function onLoadedStream() {
+      return this._loadedStreamCapability.promise;
+    }
+  }, {
+    key: "sendRequest",
+    value: function sendRequest(begin, end) {
+      var _this = this;
+
+      var rangeReader = this.pdfNetworkStream.getRangeReader(begin, end);
+
+      if (!rangeReader.isStreamingSupported) {
+        rangeReader.onProgress = this.onProgress.bind(this);
+      }
+
+      var chunks = [],
+          loaded = 0;
+      var promise = new Promise(function (resolve, reject) {
+        var readChunk = function readChunk(chunk) {
+          try {
+            if (!chunk.done) {
+              var data = chunk.value;
+              chunks.push(data);
+              loaded += (0, _util.arrayByteLength)(data);
+
+              if (rangeReader.isStreamingSupported) {
+                _this.onProgress({
+                  loaded: loaded
+                });
+              }
+
+              rangeReader.read().then(readChunk, reject);
+              return;
+            }
+
+            var chunkData = (0, _util.arraysToBytes)(chunks);
+            chunks = null;
+            resolve(chunkData);
+          } catch (e) {
+            reject(e);
+          }
+        };
+
+        rangeReader.read().then(readChunk, reject);
+      });
+      promise.then(function (data) {
+        if (_this.aborted) {
+          return;
+        }
+
+        _this.onReceiveData({
+          chunk: data,
+          begin: begin
+        });
+      });
+    }
+  }, {
+    key: "requestAllChunks",
+    value: function requestAllChunks() {
+      var missingChunks = this.stream.getMissingChunks();
+
+      this._requestChunks(missingChunks);
+
+      return this._loadedStreamCapability.promise;
+    }
+  }, {
+    key: "_requestChunks",
+    value: function _requestChunks(chunks) {
+      var requestId = this.currRequestId++;
+      var chunksNeeded = Object.create(null);
+      this.chunksNeededByRequest[requestId] = chunksNeeded;
+      var _iteratorNormalCompletion = true;
+      var _didIteratorError = false;
+      var _iteratorError = undefined;
+
+      try {
+        for (var _iterator = chunks[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+          var _chunk = _step.value;
+
+          if (!this.stream.hasChunk(_chunk)) {
+            chunksNeeded[_chunk] = true;
+          }
+        }
+      } catch (err) {
+        _didIteratorError = true;
+        _iteratorError = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+            _iterator["return"]();
+          }
+        } finally {
+          if (_didIteratorError) {
+            throw _iteratorError;
+          }
+        }
+      }
+
+      if ((0, _util.isEmptyObj)(chunksNeeded)) {
+        return Promise.resolve();
+      }
+
+      var capability = (0, _util.createPromiseCapability)();
+      this.promisesByRequest[requestId] = capability;
+      var chunksToRequest = [];
+
+      for (var chunk in chunksNeeded) {
+        chunk = chunk | 0;
+
+        if (!(chunk in this.requestsByChunk)) {
+          this.requestsByChunk[chunk] = [];
+          chunksToRequest.push(chunk);
+        }
+
+        this.requestsByChunk[chunk].push(requestId);
+      }
+
+      if (!chunksToRequest.length) {
+        return capability.promise;
+      }
+
+      var groupedChunksToRequest = this.groupChunks(chunksToRequest);
+      var _iteratorNormalCompletion2 = true;
+      var _didIteratorError2 = false;
+      var _iteratorError2 = undefined;
+
+      try {
+        for (var _iterator2 = groupedChunksToRequest[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+          var groupedChunk = _step2.value;
+          var begin = groupedChunk.beginChunk * this.chunkSize;
+          var end = Math.min(groupedChunk.endChunk * this.chunkSize, this.length);
+          this.sendRequest(begin, end);
+        }
+      } catch (err) {
+        _didIteratorError2 = true;
+        _iteratorError2 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
+            _iterator2["return"]();
+          }
+        } finally {
+          if (_didIteratorError2) {
+            throw _iteratorError2;
+          }
+        }
+      }
+
+      return capability.promise;
+    }
+  }, {
+    key: "getStream",
+    value: function getStream() {
+      return this.stream;
+    }
+  }, {
+    key: "requestRange",
+    value: function requestRange(begin, end) {
+      end = Math.min(end, this.length);
+      var beginChunk = this.getBeginChunk(begin);
+      var endChunk = this.getEndChunk(end);
+      var chunks = [];
+
+      for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
+        chunks.push(chunk);
+      }
+
+      return this._requestChunks(chunks);
+    }
+  }, {
+    key: "requestRanges",
+    value: function requestRanges() {
+      var ranges = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+      var chunksToRequest = [];
+      var _iteratorNormalCompletion3 = true;
+      var _didIteratorError3 = false;
+      var _iteratorError3 = undefined;
+
+      try {
+        for (var _iterator3 = ranges[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+          var range = _step3.value;
+          var beginChunk = this.getBeginChunk(range.begin);
+          var endChunk = this.getEndChunk(range.end);
+
+          for (var chunk = beginChunk; chunk < endChunk; ++chunk) {
+            if (!chunksToRequest.includes(chunk)) {
+              chunksToRequest.push(chunk);
+            }
+          }
+        }
+      } catch (err) {
+        _didIteratorError3 = true;
+        _iteratorError3 = err;
+      } finally {
+        try {
+          if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
+            _iterator3["return"]();
+          }
+        } finally {
+          if (_didIteratorError3) {
+            throw _iteratorError3;
+          }
+        }
+      }
+
+      chunksToRequest.sort(function (a, b) {
+        return a - b;
+      });
+      return this._requestChunks(chunksToRequest);
+    }
+  }, {
+    key: "groupChunks",
+    value: function groupChunks(chunks) {
+      var groupedChunks = [];
+      var beginChunk = -1;
+      var prevChunk = -1;
+
+      for (var i = 0, ii = chunks.length; i < ii; ++i) {
+        var chunk = chunks[i];
+
+        if (beginChunk < 0) {
+          beginChunk = chunk;
+        }
+
+        if (prevChunk >= 0 && prevChunk + 1 !== chunk) {
+          groupedChunks.push({
+            beginChunk: beginChunk,
+            endChunk: prevChunk + 1
+          });
+          beginChunk = chunk;
+        }
+
+        if (i + 1 === chunks.length) {
+          groupedChunks.push({
+            beginChunk: beginChunk,
+            endChunk: chunk + 1
+          });
+        }
+
+        prevChunk = chunk;
+      }
+
+      return groupedChunks;
+    }
+  }, {
+    key: "onProgress",
+    value: function onProgress(args) {
+      this.msgHandler.send('DocProgress', {
+        loaded: this.stream.numChunksLoaded * this.chunkSize + args.loaded,
+        total: this.length
+      });
+    }
+  }, {
+    key: "onReceiveData",
+    value: function onReceiveData(args) {
+      var chunk = args.chunk;
+      var isProgressive = args.begin === undefined;
+      var begin = isProgressive ? this.progressiveDataLength : args.begin;
+      var end = begin + chunk.byteLength;
+      var beginChunk = Math.floor(begin / this.chunkSize);
+      var endChunk = end < this.length ? Math.floor(end / this.chunkSize) : Math.ceil(end / this.chunkSize);
+
+      if (isProgressive) {
+        this.stream.onReceiveProgressiveData(chunk);
+        this.progressiveDataLength = end;
+      } else {
+        this.stream.onReceiveData(begin, chunk);
+      }
+
+      if (this.stream.allChunksLoaded()) {
+        this._loadedStreamCapability.resolve(this.stream);
+      }
+
+      var loadedRequests = [];
+
+      for (var _chunk2 = beginChunk; _chunk2 < endChunk; ++_chunk2) {
+        var requestIds = this.requestsByChunk[_chunk2] || [];
+        delete this.requestsByChunk[_chunk2];
+        var _iteratorNormalCompletion4 = true;
+        var _didIteratorError4 = false;
+        var _iteratorError4 = undefined;
+
+        try {
+          for (var _iterator4 = requestIds[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+            var requestId = _step4.value;
+            var chunksNeeded = this.chunksNeededByRequest[requestId];
+
+            if (_chunk2 in chunksNeeded) {
+              delete chunksNeeded[_chunk2];
+            }
+
+            if (!(0, _util.isEmptyObj)(chunksNeeded)) {
+              continue;
+            }
+
+            loadedRequests.push(requestId);
+          }
+        } catch (err) {
+          _didIteratorError4 = true;
+          _iteratorError4 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
+              _iterator4["return"]();
+            }
+          } finally {
+            if (_didIteratorError4) {
+              throw _iteratorError4;
+            }
+          }
+        }
+      }
+
+      if (!this.disableAutoFetch && (0, _util.isEmptyObj)(this.requestsByChunk)) {
+        var nextEmptyChunk;
+
+        if (this.stream.numChunksLoaded === 1) {
+          var lastChunk = this.stream.numChunks - 1;
+
+          if (!this.stream.hasChunk(lastChunk)) {
+            nextEmptyChunk = lastChunk;
+          }
+        } else {
+          nextEmptyChunk = this.stream.nextEmptyChunk(endChunk);
+        }
+
+        if (Number.isInteger(nextEmptyChunk)) {
+          this._requestChunks([nextEmptyChunk]);
+        }
+      }
+
+      for (var _i = 0, _loadedRequests = loadedRequests; _i < _loadedRequests.length; _i++) {
+        var _requestId = _loadedRequests[_i];
+        var capability = this.promisesByRequest[_requestId];
+        delete this.promisesByRequest[_requestId];
+        capability.resolve();
+      }
+
+      this.msgHandler.send('DocProgress', {
+        loaded: this.stream.numChunksLoaded * this.chunkSize,
+        total: this.length
+      });
+    }
+  }, {
+    key: "onError",
+    value: function onError(err) {
+      this._loadedStreamCapability.reject(err);
+    }
+  }, {
+    key: "getBeginChunk",
+    value: function getBeginChunk(begin) {
+      return Math.floor(begin / this.chunkSize);
+    }
+  }, {
+    key: "getEndChunk",
+    value: function getEndChunk(end) {
+      return Math.floor((end - 1) / this.chunkSize) + 1;
+    }
+  }, {
+    key: "abort",
+    value: function abort() {
+      this.aborted = true;
+
+      if (this.pdfNetworkStream) {
+        this.pdfNetworkStream.cancelAllRequests('abort');
+      }
+
+      for (var requestId in this.promisesByRequest) {
+        this.promisesByRequest[requestId].reject(new Error('Request was aborted'));
+      }
+    }
+  }]);
+
+  return ChunkedStreamManager;
+}();
+
+exports.ChunkedStreamManager = ChunkedStreamManager;
+
+/***/ }),
+/* 154 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getLookupTableFactory = getLookupTableFactory;
+exports.getInheritableProperty = getInheritableProperty;
+exports.toRomanNumerals = toRomanNumerals;
+exports.XRefParseException = exports.XRefEntryException = exports.MissingDataException = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+function getLookupTableFactory(initializer) {
+  var lookup;
+  return function () {
+    if (initializer) {
+      lookup = Object.create(null);
+      initializer(lookup);
+      initializer = null;
+    }
+
+    return lookup;
+  };
+}
+
+var MissingDataException = function MissingDataExceptionClosure() {
+  function MissingDataException(begin, end) {
+    this.begin = begin;
+    this.end = end;
+    this.message = "Missing data [".concat(begin, ", ").concat(end, ")");
+  }
+
+  MissingDataException.prototype = new Error();
+  MissingDataException.prototype.name = 'MissingDataException';
+  MissingDataException.constructor = MissingDataException;
+  return MissingDataException;
+}();
+
+exports.MissingDataException = MissingDataException;
+
+var XRefEntryException = function XRefEntryExceptionClosure() {
+  function XRefEntryException(msg) {
+    this.message = msg;
+  }
+
+  XRefEntryException.prototype = new Error();
+  XRefEntryException.prototype.name = 'XRefEntryException';
+  XRefEntryException.constructor = XRefEntryException;
+  return XRefEntryException;
+}();
+
+exports.XRefEntryException = XRefEntryException;
+
+var XRefParseException = function XRefParseExceptionClosure() {
+  function XRefParseException(msg) {
+    this.message = msg;
+  }
+
+  XRefParseException.prototype = new Error();
+  XRefParseException.prototype.name = 'XRefParseException';
+  XRefParseException.constructor = XRefParseException;
+  return XRefParseException;
+}();
+
+exports.XRefParseException = XRefParseException;
+
+function getInheritableProperty(_ref) {
+  var dict = _ref.dict,
+      key = _ref.key,
+      _ref$getArray = _ref.getArray,
+      getArray = _ref$getArray === void 0 ? false : _ref$getArray,
+      _ref$stopWhenFound = _ref.stopWhenFound,
+      stopWhenFound = _ref$stopWhenFound === void 0 ? true : _ref$stopWhenFound;
+  var LOOP_LIMIT = 100;
+  var loopCount = 0;
+  var values;
+
+  while (dict) {
+    var value = getArray ? dict.getArray(key) : dict.get(key);
+
+    if (value !== undefined) {
+      if (stopWhenFound) {
+        return value;
+      }
+
+      if (!values) {
+        values = [];
+      }
+
+      values.push(value);
+    }
+
+    if (++loopCount > LOOP_LIMIT) {
+      (0, _util.warn)("getInheritableProperty: maximum loop count exceeded for \"".concat(key, "\""));
+      break;
+    }
+
+    dict = dict.get('Parent');
+  }
+
+  return values;
+}
+
+var ROMAN_NUMBER_MAP = ['', 'C', 'CC', 'CCC', 'CD', 'D', 'DC', 'DCC', 'DCCC', 'CM', '', 'X', 'XX', 'XXX', 'XL', 'L', 'LX', 'LXX', 'LXXX', 'XC', '', 'I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII', 'IX'];
+
+function toRomanNumerals(number) {
+  var lowerCase = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+  (0, _util.assert)(Number.isInteger(number) && number > 0, 'The number should be a positive integer.');
+  var pos,
+      romanBuf = [];
+
+  while (number >= 1000) {
+    number -= 1000;
+    romanBuf.push('M');
+  }
+
+  pos = number / 100 | 0;
+  number %= 100;
+  romanBuf.push(ROMAN_NUMBER_MAP[pos]);
+  pos = number / 10 | 0;
+  number %= 10;
+  romanBuf.push(ROMAN_NUMBER_MAP[10 + pos]);
+  romanBuf.push(ROMAN_NUMBER_MAP[20 + number]);
+  var romanStr = romanBuf.join('');
+  return lowerCase ? romanStr.toLowerCase() : romanStr;
+}
+
+/***/ }),
+/* 155 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFDocument = exports.Page = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _obj = __w_pdfjs_require__(156);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _stream2 = __w_pdfjs_require__(158);
+
+var _annotation = __w_pdfjs_require__(170);
+
+var _crypto = __w_pdfjs_require__(168);
+
+var _parser = __w_pdfjs_require__(157);
+
+var _operator_list = __w_pdfjs_require__(171);
+
+var _evaluator = __w_pdfjs_require__(172);
+
+var _function = __w_pdfjs_require__(186);
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var DEFAULT_USER_UNIT = 1.0;
+var LETTER_SIZE_MEDIABOX = [0, 0, 612, 792];
+
+function isAnnotationRenderable(annotation, intent) {
+  return intent === 'display' && annotation.viewable || intent === 'print' && annotation.printable;
+}
+
+var Page =
+/*#__PURE__*/
+function () {
+  function Page(_ref) {
+    var pdfManager = _ref.pdfManager,
+        xref = _ref.xref,
+        pageIndex = _ref.pageIndex,
+        pageDict = _ref.pageDict,
+        ref = _ref.ref,
+        fontCache = _ref.fontCache,
+        builtInCMapCache = _ref.builtInCMapCache,
+        pdfFunctionFactory = _ref.pdfFunctionFactory;
+
+    _classCallCheck(this, Page);
+
+    this.pdfManager = pdfManager;
+    this.pageIndex = pageIndex;
+    this.pageDict = pageDict;
+    this.xref = xref;
+    this.ref = ref;
+    this.fontCache = fontCache;
+    this.builtInCMapCache = builtInCMapCache;
+    this.pdfFunctionFactory = pdfFunctionFactory;
+    this.evaluatorOptions = pdfManager.evaluatorOptions;
+    this.resourcesPromise = null;
+    var idCounters = {
+      obj: 0
+    };
+    this.idFactory = {
+      createObjId: function createObjId() {
+        return "p".concat(pageIndex, "_").concat(++idCounters.obj);
+      },
+      getDocId: function getDocId() {
+        return "g_".concat(pdfManager.docId);
+      }
+    };
+  }
+
+  _createClass(Page, [{
+    key: "_getInheritableProperty",
+    value: function _getInheritableProperty(key) {
+      var getArray = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var value = (0, _core_utils.getInheritableProperty)({
+        dict: this.pageDict,
+        key: key,
+        getArray: getArray,
+        stopWhenFound: false
+      });
+
+      if (!Array.isArray(value)) {
+        return value;
+      }
+
+      if (value.length === 1 || !(0, _primitives.isDict)(value[0])) {
+        return value[0];
+      }
+
+      return _primitives.Dict.merge(this.xref, value);
+    }
+  }, {
+    key: "getContentStream",
+    value: function getContentStream() {
+      var content = this.content;
+      var stream;
+
+      if (Array.isArray(content)) {
+        var xref = this.xref;
+        var streams = [];
+        var _iteratorNormalCompletion = true;
+        var _didIteratorError = false;
+        var _iteratorError = undefined;
+
+        try {
+          for (var _iterator = content[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+            var _stream = _step.value;
+            streams.push(xref.fetchIfRef(_stream));
+          }
+        } catch (err) {
+          _didIteratorError = true;
+          _iteratorError = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+              _iterator["return"]();
+            }
+          } finally {
+            if (_didIteratorError) {
+              throw _iteratorError;
+            }
+          }
+        }
+
+        stream = new _stream2.StreamsSequenceStream(streams);
+      } else if ((0, _primitives.isStream)(content)) {
+        stream = content;
+      } else {
+        stream = new _stream2.NullStream();
+      }
+
+      return stream;
+    }
+  }, {
+    key: "loadResources",
+    value: function loadResources(keys) {
+      var _this = this;
+
+      if (!this.resourcesPromise) {
+        this.resourcesPromise = this.pdfManager.ensure(this, 'resources');
+      }
+
+      return this.resourcesPromise.then(function () {
+        var objectLoader = new _obj.ObjectLoader(_this.resources, keys, _this.xref);
+        return objectLoader.load();
+      });
+    }
+  }, {
+    key: "getOperatorList",
+    value: function getOperatorList(_ref2) {
+      var _this2 = this;
+
+      var handler = _ref2.handler,
+          task = _ref2.task,
+          intent = _ref2.intent,
+          renderInteractiveForms = _ref2.renderInteractiveForms;
+      var contentStreamPromise = this.pdfManager.ensure(this, 'getContentStream');
+      var resourcesPromise = this.loadResources(['ExtGState', 'ColorSpace', 'Pattern', 'Shading', 'XObject', 'Font']);
+      var partialEvaluator = new _evaluator.PartialEvaluator({
+        xref: this.xref,
+        handler: handler,
+        pageIndex: this.pageIndex,
+        idFactory: this.idFactory,
+        fontCache: this.fontCache,
+        builtInCMapCache: this.builtInCMapCache,
+        options: this.evaluatorOptions,
+        pdfFunctionFactory: this.pdfFunctionFactory
+      });
+      var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
+      var pageListPromise = dataPromises.then(function (_ref3) {
+        var _ref4 = _slicedToArray(_ref3, 1),
+            contentStream = _ref4[0];
+
+        var opList = new _operator_list.OperatorList(intent, handler, _this2.pageIndex);
+        handler.send('StartRenderPage', {
+          transparency: partialEvaluator.hasBlendModes(_this2.resources),
+          pageIndex: _this2.pageIndex,
+          intent: intent
+        });
+        return partialEvaluator.getOperatorList({
+          stream: contentStream,
+          task: task,
+          resources: _this2.resources,
+          operatorList: opList
+        }).then(function () {
+          return opList;
+        });
+      });
+      return Promise.all([pageListPromise, this._parsedAnnotations]).then(function (_ref5) {
+        var _ref6 = _slicedToArray(_ref5, 2),
+            pageOpList = _ref6[0],
+            annotations = _ref6[1];
+
+        if (annotations.length === 0) {
+          pageOpList.flush(true);
+          return pageOpList;
+        }
+
+        var opListPromises = [];
+        var _iteratorNormalCompletion2 = true;
+        var _didIteratorError2 = false;
+        var _iteratorError2 = undefined;
+
+        try {
+          for (var _iterator2 = annotations[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {
+            var annotation = _step2.value;
+
+            if (isAnnotationRenderable(annotation, intent)) {
+              opListPromises.push(annotation.getOperatorList(partialEvaluator, task, renderInteractiveForms));
+            }
+          }
+        } catch (err) {
+          _didIteratorError2 = true;
+          _iteratorError2 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion2 && _iterator2["return"] != null) {
+              _iterator2["return"]();
+            }
+          } finally {
+            if (_didIteratorError2) {
+              throw _iteratorError2;
+            }
+          }
+        }
+
+        return Promise.all(opListPromises).then(function (opLists) {
+          pageOpList.addOp(_util.OPS.beginAnnotations, []);
+          var _iteratorNormalCompletion3 = true;
+          var _didIteratorError3 = false;
+          var _iteratorError3 = undefined;
+
+          try {
+            for (var _iterator3 = opLists[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {
+              var opList = _step3.value;
+              pageOpList.addOpList(opList);
+            }
+          } catch (err) {
+            _didIteratorError3 = true;
+            _iteratorError3 = err;
+          } finally {
+            try {
+              if (!_iteratorNormalCompletion3 && _iterator3["return"] != null) {
+                _iterator3["return"]();
+              }
+            } finally {
+              if (_didIteratorError3) {
+                throw _iteratorError3;
+              }
+            }
+          }
+
+          pageOpList.addOp(_util.OPS.endAnnotations, []);
+          pageOpList.flush(true);
+          return pageOpList;
+        });
+      });
+    }
+  }, {
+    key: "extractTextContent",
+    value: function extractTextContent(_ref7) {
+      var _this3 = this;
+
+      var handler = _ref7.handler,
+          task = _ref7.task,
+          normalizeWhitespace = _ref7.normalizeWhitespace,
+          sink = _ref7.sink,
+          combineTextItems = _ref7.combineTextItems;
+      var contentStreamPromise = this.pdfManager.ensure(this, 'getContentStream');
+      var resourcesPromise = this.loadResources(['ExtGState', 'XObject', 'Font']);
+      var dataPromises = Promise.all([contentStreamPromise, resourcesPromise]);
+      return dataPromises.then(function (_ref8) {
+        var _ref9 = _slicedToArray(_ref8, 1),
+            contentStream = _ref9[0];
+
+        var partialEvaluator = new _evaluator.PartialEvaluator({
+          xref: _this3.xref,
+          handler: handler,
+          pageIndex: _this3.pageIndex,
+          idFactory: _this3.idFactory,
+          fontCache: _this3.fontCache,
+          builtInCMapCache: _this3.builtInCMapCache,
+          options: _this3.evaluatorOptions,
+          pdfFunctionFactory: _this3.pdfFunctionFactory
+        });
+        return partialEvaluator.getTextContent({
+          stream: contentStream,
+          task: task,
+          resources: _this3.resources,
+          normalizeWhitespace: normalizeWhitespace,
+          combineTextItems: combineTextItems,
+          sink: sink
+        });
+      });
+    }
+  }, {
+    key: "getAnnotationsData",
+    value: function getAnnotationsData(intent) {
+      return this._parsedAnnotations.then(function (annotations) {
+        var annotationsData = [];
+
+        for (var i = 0, ii = annotations.length; i < ii; i++) {
+          if (!intent || isAnnotationRenderable(annotations[i], intent)) {
+            annotationsData.push(annotations[i].data);
+          }
+        }
+
+        return annotationsData;
+      });
+    }
+  }, {
+    key: "content",
+    get: function get() {
+      return this.pageDict.get('Contents');
+    }
+  }, {
+    key: "resources",
+    get: function get() {
+      return (0, _util.shadow)(this, 'resources', this._getInheritableProperty('Resources') || _primitives.Dict.empty);
+    }
+  }, {
+    key: "mediaBox",
+    get: function get() {
+      var mediaBox = this._getInheritableProperty('MediaBox', true);
+
+      if (!Array.isArray(mediaBox) || mediaBox.length !== 4) {
+        return (0, _util.shadow)(this, 'mediaBox', LETTER_SIZE_MEDIABOX);
+      }
+
+      return (0, _util.shadow)(this, 'mediaBox', mediaBox);
+    }
+  }, {
+    key: "cropBox",
+    get: function get() {
+      var cropBox = this._getInheritableProperty('CropBox', true);
+
+      if (!Array.isArray(cropBox) || cropBox.length !== 4) {
+        return (0, _util.shadow)(this, 'cropBox', this.mediaBox);
+      }
+
+      return (0, _util.shadow)(this, 'cropBox', cropBox);
+    }
+  }, {
+    key: "userUnit",
+    get: function get() {
+      var obj = this.pageDict.get('UserUnit');
+
+      if (!(0, _util.isNum)(obj) || obj <= 0) {
+        obj = DEFAULT_USER_UNIT;
+      }
+
+      return (0, _util.shadow)(this, 'userUnit', obj);
+    }
+  }, {
+    key: "view",
+    get: function get() {
+      var mediaBox = this.mediaBox,
+          cropBox = this.cropBox;
+
+      if (mediaBox === cropBox) {
+        return (0, _util.shadow)(this, 'view', mediaBox);
+      }
+
+      var intersection = _util.Util.intersect(cropBox, mediaBox);
+
+      return (0, _util.shadow)(this, 'view', intersection || mediaBox);
+    }
+  }, {
+    key: "rotate",
+    get: function get() {
+      var rotate = this._getInheritableProperty('Rotate') || 0;
+
+      if (rotate % 90 !== 0) {
+        rotate = 0;
+      } else if (rotate >= 360) {
+        rotate = rotate % 360;
+      } else if (rotate < 0) {
+        rotate = (rotate % 360 + 360) % 360;
+      }
+
+      return (0, _util.shadow)(this, 'rotate', rotate);
+    }
+  }, {
+    key: "annotations",
+    get: function get() {
+      return (0, _util.shadow)(this, 'annotations', this._getInheritableProperty('Annots') || []);
+    }
+  }, {
+    key: "_parsedAnnotations",
+    get: function get() {
+      var _this4 = this;
+
+      var parsedAnnotations = this.pdfManager.ensure(this, 'annotations').then(function () {
+        var annotationRefs = _this4.annotations;
+        var annotationPromises = [];
+
+        for (var i = 0, ii = annotationRefs.length; i < ii; i++) {
+          annotationPromises.push(_annotation.AnnotationFactory.create(_this4.xref, annotationRefs[i], _this4.pdfManager, _this4.idFactory));
+        }
+
+        return Promise.all(annotationPromises).then(function (annotations) {
+          return annotations.filter(function isDefined(annotation) {
+            return !!annotation;
+          });
+        }, function (reason) {
+          (0, _util.warn)("_parsedAnnotations: \"".concat(reason, "\"."));
+          return [];
+        });
+      });
+      return (0, _util.shadow)(this, '_parsedAnnotations', parsedAnnotations);
+    }
+  }]);
+
+  return Page;
+}();
+
+exports.Page = Page;
+var FINGERPRINT_FIRST_BYTES = 1024;
+var EMPTY_FINGERPRINT = '\x00\x00\x00\x00\x00\x00\x00' + '\x00\x00\x00\x00\x00\x00\x00\x00\x00';
+
+function find(stream, needle, limit) {
+  var backwards = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+  (0, _util.assert)(limit > 0, 'The "limit" must be a positive integer.');
+  var str = (0, _util.bytesToString)(stream.peekBytes(limit));
+  var index = backwards ? str.lastIndexOf(needle) : str.indexOf(needle);
+
+  if (index === -1) {
+    return false;
+  }
+
+  stream.pos += index;
+  return true;
+}
+
+var PDFDocument =
+/*#__PURE__*/
+function () {
+  function PDFDocument(pdfManager, arg) {
+    _classCallCheck(this, PDFDocument);
+
+    var stream;
+
+    if ((0, _primitives.isStream)(arg)) {
+      stream = arg;
+    } else if ((0, _util.isArrayBuffer)(arg)) {
+      stream = new _stream2.Stream(arg);
+    } else {
+      throw new Error('PDFDocument: Unknown argument type');
+    }
+
+    if (stream.length <= 0) {
+      throw new Error('PDFDocument: Stream must have data');
+    }
+
+    this.pdfManager = pdfManager;
+    this.stream = stream;
+    this.xref = new _obj.XRef(stream, pdfManager);
+    this.pdfFunctionFactory = new _function.PDFFunctionFactory({
+      xref: this.xref,
+      isEvalSupported: pdfManager.evaluatorOptions.isEvalSupported
+    });
+    this._pagePromises = [];
+  }
+
+  _createClass(PDFDocument, [{
+    key: "parse",
+    value: function parse(recoveryMode) {
+      this.setup(recoveryMode);
+      var version = this.catalog.catDict.get('Version');
+
+      if ((0, _primitives.isName)(version)) {
+        this.pdfFormatVersion = version.name;
+      }
+
+      try {
+        this.acroForm = this.catalog.catDict.get('AcroForm');
+
+        if (this.acroForm) {
+          this.xfa = this.acroForm.get('XFA');
+          var fields = this.acroForm.get('Fields');
+
+          if ((!Array.isArray(fields) || fields.length === 0) && !this.xfa) {
+            this.acroForm = null;
+          }
+        }
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.info)('Cannot fetch AcroForm entry; assuming no AcroForms are present');
+        this.acroForm = null;
+      }
+
+      try {
+        var collection = this.catalog.catDict.get('Collection');
+
+        if ((0, _primitives.isDict)(collection) && collection.getKeys().length > 0) {
+          this.collection = collection;
+        }
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.info)('Cannot fetch Collection dictionary.');
+      }
+    }
+  }, {
+    key: "checkHeader",
+    value: function checkHeader() {
+      var stream = this.stream;
+      stream.reset();
+
+      if (!find(stream, '%PDF-', 1024)) {
+        return;
+      }
+
+      stream.moveStart();
+      var MAX_PDF_VERSION_LENGTH = 12;
+      var version = '',
+          ch;
+
+      while ((ch = stream.getByte()) > 0x20) {
+        if (version.length >= MAX_PDF_VERSION_LENGTH) {
+          break;
+        }
+
+        version += String.fromCharCode(ch);
+      }
+
+      if (!this.pdfFormatVersion) {
+        this.pdfFormatVersion = version.substring(5);
+      }
+    }
+  }, {
+    key: "parseStartXRef",
+    value: function parseStartXRef() {
+      this.xref.setStartXRef(this.startXRef);
+    }
+  }, {
+    key: "setup",
+    value: function setup(recoveryMode) {
+      this.xref.parse(recoveryMode);
+      this.catalog = new _obj.Catalog(this.pdfManager, this.xref);
+    }
+  }, {
+    key: "_getLinearizationPage",
+    value: function _getLinearizationPage(pageIndex) {
+      var catalog = this.catalog,
+          linearization = this.linearization;
+      (0, _util.assert)(linearization && linearization.pageFirst === pageIndex);
+
+      var ref = _primitives.Ref.get(linearization.objectNumberFirst, 0);
+
+      return this.xref.fetchAsync(ref).then(function (obj) {
+        if ((0, _primitives.isDict)(obj, 'Page') || (0, _primitives.isDict)(obj) && !obj.has('Type') && obj.has('Contents')) {
+          if (ref && !catalog.pageKidsCountCache.has(ref)) {
+            catalog.pageKidsCountCache.put(ref, 1);
+          }
+
+          return [obj, ref];
+        }
+
+        throw new _util.FormatError('The Linearization dictionary doesn\'t point ' + 'to a valid Page dictionary.');
+      })["catch"](function (reason) {
+        (0, _util.info)(reason);
+        return catalog.getPageDict(pageIndex);
+      });
+    }
+  }, {
+    key: "getPage",
+    value: function getPage(pageIndex) {
+      var _this5 = this;
+
+      if (this._pagePromises[pageIndex] !== undefined) {
+        return this._pagePromises[pageIndex];
+      }
+
+      var catalog = this.catalog,
+          linearization = this.linearization;
+      var promise = linearization && linearization.pageFirst === pageIndex ? this._getLinearizationPage(pageIndex) : catalog.getPageDict(pageIndex);
+      return this._pagePromises[pageIndex] = promise.then(function (_ref10) {
+        var _ref11 = _slicedToArray(_ref10, 2),
+            pageDict = _ref11[0],
+            ref = _ref11[1];
+
+        return new Page({
+          pdfManager: _this5.pdfManager,
+          xref: _this5.xref,
+          pageIndex: pageIndex,
+          pageDict: pageDict,
+          ref: ref,
+          fontCache: catalog.fontCache,
+          builtInCMapCache: catalog.builtInCMapCache,
+          pdfFunctionFactory: _this5.pdfFunctionFactory
+        });
+      });
+    }
+  }, {
+    key: "checkFirstPage",
+    value: function checkFirstPage() {
+      var _this6 = this;
+
+      return this.getPage(0)["catch"](function (reason) {
+        if (reason instanceof _core_utils.XRefEntryException) {
+          _this6._pagePromises.length = 0;
+
+          _this6.cleanup();
+
+          throw new _core_utils.XRefParseException();
+        }
+      });
+    }
+  }, {
+    key: "fontFallback",
+    value: function fontFallback(id, handler) {
+      return this.catalog.fontFallback(id, handler);
+    }
+  }, {
+    key: "cleanup",
+    value: function cleanup() {
+      return this.catalog.cleanup();
+    }
+  }, {
+    key: "linearization",
+    get: function get() {
+      var linearization = null;
+
+      try {
+        linearization = _parser.Linearization.create(this.stream);
+      } catch (err) {
+        if (err instanceof _core_utils.MissingDataException) {
+          throw err;
+        }
+
+        (0, _util.info)(err);
+      }
+
+      return (0, _util.shadow)(this, 'linearization', linearization);
+    }
+  }, {
+    key: "startXRef",
+    get: function get() {
+      var stream = this.stream;
+      var startXRef = 0;
+
+      if (this.linearization) {
+        stream.reset();
+
+        if (find(stream, 'endobj', 1024)) {
+          startXRef = stream.pos + 6;
+        }
+      } else {
+        var step = 1024;
+        var startXRefLength = 'startxref'.length;
+        var found = false,
+            pos = stream.end;
+
+        while (!found && pos > 0) {
+          pos -= step - startXRefLength;
+
+          if (pos < 0) {
+            pos = 0;
+          }
+
+          stream.pos = pos;
+          found = find(stream, 'startxref', step, true);
+        }
+
+        if (found) {
+          stream.skip(9);
+          var ch;
+
+          do {
+            ch = stream.getByte();
+          } while ((0, _util.isSpace)(ch));
+
+          var str = '';
+
+          while (ch >= 0x20 && ch <= 0x39) {
+            str += String.fromCharCode(ch);
+            ch = stream.getByte();
+          }
+
+          startXRef = parseInt(str, 10);
+
+          if (isNaN(startXRef)) {
+            startXRef = 0;
+          }
+        }
+      }
+
+      return (0, _util.shadow)(this, 'startXRef', startXRef);
+    }
+  }, {
+    key: "numPages",
+    get: function get() {
+      var linearization = this.linearization;
+      var num = linearization ? linearization.numPages : this.catalog.numPages;
+      return (0, _util.shadow)(this, 'numPages', num);
+    }
+  }, {
+    key: "documentInfo",
+    get: function get() {
+      var DocumentInfoValidators = {
+        Title: _util.isString,
+        Author: _util.isString,
+        Subject: _util.isString,
+        Keywords: _util.isString,
+        Creator: _util.isString,
+        Producer: _util.isString,
+        CreationDate: _util.isString,
+        ModDate: _util.isString,
+        Trapped: _primitives.isName
+      };
+      var docInfo = {
+        PDFFormatVersion: this.pdfFormatVersion,
+        IsLinearized: !!this.linearization,
+        IsAcroFormPresent: !!this.acroForm,
+        IsXFAPresent: !!this.xfa,
+        IsCollectionPresent: !!this.collection
+      };
+      var infoDict;
+
+      try {
+        infoDict = this.xref.trailer.get('Info');
+      } catch (err) {
+        if (err instanceof _core_utils.MissingDataException) {
+          throw err;
+        }
+
+        (0, _util.info)('The document information dictionary is invalid.');
+      }
+
+      if ((0, _primitives.isDict)(infoDict)) {
+        var _iteratorNormalCompletion4 = true;
+        var _didIteratorError4 = false;
+        var _iteratorError4 = undefined;
+
+        try {
+          for (var _iterator4 = infoDict.getKeys()[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {
+            var key = _step4.value;
+            var value = infoDict.get(key);
+
+            if (DocumentInfoValidators[key]) {
+              if (DocumentInfoValidators[key](value)) {
+                docInfo[key] = typeof value !== 'string' ? value : (0, _util.stringToPDFString)(value);
+              } else {
+                (0, _util.info)("Bad value in document info for \"".concat(key, "\"."));
+              }
+            } else if (typeof key === 'string') {
+              var customValue = void 0;
+
+              if ((0, _util.isString)(value)) {
+                customValue = (0, _util.stringToPDFString)(value);
+              } else if ((0, _primitives.isName)(value) || (0, _util.isNum)(value) || (0, _util.isBool)(value)) {
+                customValue = value;
+              } else {
+                (0, _util.info)("Unsupported value in document info for (custom) \"".concat(key, "\"."));
+                continue;
+              }
+
+              if (!docInfo['Custom']) {
+                docInfo['Custom'] = Object.create(null);
+              }
+
+              docInfo['Custom'][key] = customValue;
+            }
+          }
+        } catch (err) {
+          _didIteratorError4 = true;
+          _iteratorError4 = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion4 && _iterator4["return"] != null) {
+              _iterator4["return"]();
+            }
+          } finally {
+            if (_didIteratorError4) {
+              throw _iteratorError4;
+            }
+          }
+        }
+      }
+
+      return (0, _util.shadow)(this, 'documentInfo', docInfo);
+    }
+  }, {
+    key: "fingerprint",
+    get: function get() {
+      var hash;
+      var idArray = this.xref.trailer.get('ID');
+
+      if (Array.isArray(idArray) && idArray[0] && (0, _util.isString)(idArray[0]) && idArray[0] !== EMPTY_FINGERPRINT) {
+        hash = (0, _util.stringToBytes)(idArray[0]);
+      } else {
+        if (this.stream.ensureRange) {
+          this.stream.ensureRange(0, Math.min(FINGERPRINT_FIRST_BYTES, this.stream.end));
+        }
+
+        hash = (0, _crypto.calculateMD5)(this.stream.bytes.subarray(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
+      }
+
+      var fingerprint = '';
+
+      for (var i = 0, ii = hash.length; i < ii; i++) {
+        var hex = hash[i].toString(16);
+        fingerprint += hex.length === 1 ? '0' + hex : hex;
+      }
+
+      return (0, _util.shadow)(this, 'fingerprint', fingerprint);
+    }
+  }]);
+
+  return PDFDocument;
+}();
+
+exports.PDFDocument = PDFDocument;
+
+/***/ }),
+/* 156 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.FileSpec = exports.XRef = exports.ObjectLoader = exports.Catalog = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _parser = __w_pdfjs_require__(157);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _chunked_stream = __w_pdfjs_require__(153);
+
+var _crypto = __w_pdfjs_require__(168);
+
+var _colorspace = __w_pdfjs_require__(169);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function fetchDestination(dest) {
+  return (0, _primitives.isDict)(dest) ? dest.get('D') : dest;
+}
+
+var Catalog =
+/*#__PURE__*/
+function () {
+  function Catalog(pdfManager, xref) {
+    _classCallCheck(this, Catalog);
+
+    this.pdfManager = pdfManager;
+    this.xref = xref;
+    this.catDict = xref.getCatalogObj();
+
+    if (!(0, _primitives.isDict)(this.catDict)) {
+      throw new _util.FormatError('Catalog object is not a dictionary.');
+    }
+
+    this.fontCache = new _primitives.RefSetCache();
+    this.builtInCMapCache = new Map();
+    this.pageKidsCountCache = new _primitives.RefSetCache();
+  }
+
+  _createClass(Catalog, [{
+    key: "_readDocumentOutline",
+    value: function _readDocumentOutline() {
+      var obj = this.catDict.get('Outlines');
+
+      if (!(0, _primitives.isDict)(obj)) {
+        return null;
+      }
+
+      obj = obj.getRaw('First');
+
+      if (!(0, _primitives.isRef)(obj)) {
+        return null;
+      }
+
+      var root = {
+        items: []
+      };
+      var queue = [{
+        obj: obj,
+        parent: root
+      }];
+      var processed = new _primitives.RefSet();
+      processed.put(obj);
+      var xref = this.xref,
+          blackColor = new Uint8ClampedArray(3);
+
+      while (queue.length > 0) {
+        var i = queue.shift();
+        var outlineDict = xref.fetchIfRef(i.obj);
+
+        if (outlineDict === null) {
+          continue;
+        }
+
+        if (!outlineDict.has('Title')) {
+          throw new _util.FormatError('Invalid outline item encountered.');
+        }
+
+        var data = {
+          url: null,
+          dest: null
+        };
+        Catalog.parseDestDictionary({
+          destDict: outlineDict,
+          resultObj: data,
+          docBaseUrl: this.pdfManager.docBaseUrl
+        });
+        var title = outlineDict.get('Title');
+        var flags = outlineDict.get('F') || 0;
+        var color = outlineDict.getArray('C');
+        var count = outlineDict.get('Count');
+        var rgbColor = blackColor;
+
+        if (Array.isArray(color) && color.length === 3 && (color[0] !== 0 || color[1] !== 0 || color[2] !== 0)) {
+          rgbColor = _colorspace.ColorSpace.singletons.rgb.getRgb(color, 0);
+        }
+
+        var outlineItem = {
+          dest: data.dest,
+          url: data.url,
+          unsafeUrl: data.unsafeUrl,
+          newWindow: data.newWindow,
+          title: (0, _util.stringToPDFString)(title),
+          color: rgbColor,
+          count: Number.isInteger(count) ? count : undefined,
+          bold: !!(flags & 2),
+          italic: !!(flags & 1),
+          items: []
+        };
+        i.parent.items.push(outlineItem);
+        obj = outlineDict.getRaw('First');
+
+        if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
+          queue.push({
+            obj: obj,
+            parent: outlineItem
+          });
+          processed.put(obj);
+        }
+
+        obj = outlineDict.getRaw('Next');
+
+        if ((0, _primitives.isRef)(obj) && !processed.has(obj)) {
+          queue.push({
+            obj: obj,
+            parent: i.parent
+          });
+          processed.put(obj);
+        }
+      }
+
+      return root.items.length > 0 ? root.items : null;
+    }
+  }, {
+    key: "_readPermissions",
+    value: function _readPermissions() {
+      var encrypt = this.xref.trailer.get('Encrypt');
+
+      if (!(0, _primitives.isDict)(encrypt)) {
+        return null;
+      }
+
+      var flags = encrypt.get('P');
+
+      if (!(0, _util.isNum)(flags)) {
+        return null;
+      }
+
+      flags += Math.pow(2, 32);
+      var permissions = [];
+
+      for (var key in _util.PermissionFlag) {
+        var value = _util.PermissionFlag[key];
+
+        if (flags & value) {
+          permissions.push(value);
+        }
+      }
+
+      return permissions;
+    }
+  }, {
+    key: "getDestination",
+    value: function getDestination(destinationId) {
+      var obj = this._readDests();
+
+      if (obj instanceof NameTree || obj instanceof _primitives.Dict) {
+        return fetchDestination(obj.get(destinationId) || null);
+      }
+
+      return null;
+    }
+  }, {
+    key: "_readDests",
+    value: function _readDests() {
+      var obj = this.catDict.get('Names');
+
+      if (obj && obj.has('Dests')) {
+        return new NameTree(obj.getRaw('Dests'), this.xref);
+      } else if (this.catDict.has('Dests')) {
+        return this.catDict.get('Dests');
+      }
+
+      return undefined;
+    }
+  }, {
+    key: "_readPageLabels",
+    value: function _readPageLabels() {
+      var obj = this.catDict.getRaw('PageLabels');
+
+      if (!obj) {
+        return null;
+      }
+
+      var pageLabels = new Array(this.numPages);
+      var style = null,
+          prefix = '';
+      var numberTree = new NumberTree(obj, this.xref);
+      var nums = numberTree.getAll();
+      var currentLabel = '',
+          currentIndex = 1;
+
+      for (var i = 0, ii = this.numPages; i < ii; i++) {
+        if (i in nums) {
+          var labelDict = nums[i];
+
+          if (!(0, _primitives.isDict)(labelDict)) {
+            throw new _util.FormatError('PageLabel is not a dictionary.');
+          }
+
+          if (labelDict.has('Type') && !(0, _primitives.isName)(labelDict.get('Type'), 'PageLabel')) {
+            throw new _util.FormatError('Invalid type in PageLabel dictionary.');
+          }
+
+          if (labelDict.has('S')) {
+            var s = labelDict.get('S');
+
+            if (!(0, _primitives.isName)(s)) {
+              throw new _util.FormatError('Invalid style in PageLabel dictionary.');
+            }
+
+            style = s.name;
+          } else {
+            style = null;
+          }
+
+          if (labelDict.has('P')) {
+            var p = labelDict.get('P');
+
+            if (!(0, _util.isString)(p)) {
+              throw new _util.FormatError('Invalid prefix in PageLabel dictionary.');
+            }
+
+            prefix = (0, _util.stringToPDFString)(p);
+          } else {
+            prefix = '';
+          }
+
+          if (labelDict.has('St')) {
+            var st = labelDict.get('St');
+
+            if (!(Number.isInteger(st) && st >= 1)) {
+              throw new _util.FormatError('Invalid start in PageLabel dictionary.');
+            }
+
+            currentIndex = st;
+          } else {
+            currentIndex = 1;
+          }
+        }
+
+        switch (style) {
+          case 'D':
+            currentLabel = currentIndex;
+            break;
+
+          case 'R':
+          case 'r':
+            currentLabel = (0, _core_utils.toRomanNumerals)(currentIndex, style === 'r');
+            break;
+
+          case 'A':
+          case 'a':
+            var LIMIT = 26;
+            var A_UPPER_CASE = 0x41,
+                A_LOWER_CASE = 0x61;
+            var baseCharCode = style === 'a' ? A_LOWER_CASE : A_UPPER_CASE;
+            var letterIndex = currentIndex - 1;
+            var character = String.fromCharCode(baseCharCode + letterIndex % LIMIT);
+            var charBuf = [];
+
+            for (var j = 0, jj = letterIndex / LIMIT | 0; j <= jj; j++) {
+              charBuf.push(character);
+            }
+
+            currentLabel = charBuf.join('');
+            break;
+
+          default:
+            if (style) {
+              throw new _util.FormatError("Invalid style \"".concat(style, "\" in PageLabel dictionary."));
+            }
+
+            currentLabel = '';
+        }
+
+        pageLabels[i] = prefix + currentLabel;
+        currentIndex++;
+      }
+
+      return pageLabels;
+    }
+  }, {
+    key: "fontFallback",
+    value: function fontFallback(id, handler) {
+      var promises = [];
+      this.fontCache.forEach(function (promise) {
+        promises.push(promise);
+      });
+      return Promise.all(promises).then(function (translatedFonts) {
+        var _iteratorNormalCompletion = true;
+        var _didIteratorError = false;
+        var _iteratorError = undefined;
+
+        try {
+          for (var _iterator = translatedFonts[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+            var translatedFont = _step.value;
+
+            if (translatedFont.loadedName === id) {
+              translatedFont.fallback(handler);
+              return;
+            }
+          }
+        } catch (err) {
+          _didIteratorError = true;
+          _iteratorError = err;
+        } finally {
+          try {
+            if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+              _iterator["return"]();
+            }
+          } finally {
+            if (_didIteratorError) {
+              throw _iteratorError;
+            }
+          }
+        }
+      });
+    }
+  }, {
+    key: "cleanup",
+    value: function cleanup() {
+      var _this = this;
+
+      (0, _primitives.clearPrimitiveCaches)();
+      this.pageKidsCountCache.clear();
+      var promises = [];
+      this.fontCache.forEach(function (promise) {
+        promises.push(promise);
+      });
+      return Promise.all(promises).then(function (translatedFonts) {
+        for (var i = 0, ii = translatedFonts.length; i < ii; i++) {
+          var font = translatedFonts[i].dict;
+          delete font.translated;
+        }
+
+        _this.fontCache.clear();
+
+        _this.builtInCMapCache.clear();
+      });
+    }
+  }, {
+    key: "getPageDict",
+    value: function getPageDict(pageIndex) {
+      var capability = (0, _util.createPromiseCapability)();
+      var nodesToVisit = [this.catDict.getRaw('Pages')];
+      var xref = this.xref,
+          pageKidsCountCache = this.pageKidsCountCache;
+      var count,
+          currentPageIndex = 0;
+
+      function next() {
+        var _loop = function _loop() {
+          var currentNode = nodesToVisit.pop();
+
+          if ((0, _primitives.isRef)(currentNode)) {
+            count = pageKidsCountCache.get(currentNode);
+
+            if (count > 0 && currentPageIndex + count < pageIndex) {
+              currentPageIndex += count;
+              return "continue";
+            }
+
+            xref.fetchAsync(currentNode).then(function (obj) {
+              if ((0, _primitives.isDict)(obj, 'Page') || (0, _primitives.isDict)(obj) && !obj.has('Kids')) {
+                if (pageIndex === currentPageIndex) {
+                  if (currentNode && !pageKidsCountCache.has(currentNode)) {
+                    pageKidsCountCache.put(currentNode, 1);
+                  }
+
+                  capability.resolve([obj, currentNode]);
+                } else {
+                  currentPageIndex++;
+                  next();
+                }
+
+                return;
+              }
+
+              nodesToVisit.push(obj);
+              next();
+            }, capability.reject);
+            return {
+              v: void 0
+            };
+          }
+
+          if (!(0, _primitives.isDict)(currentNode)) {
+            capability.reject(new _util.FormatError('Page dictionary kid reference points to wrong type of object.'));
+            return {
+              v: void 0
+            };
+          }
+
+          count = currentNode.get('Count');
+
+          if (Number.isInteger(count) && count >= 0) {
+            var objId = currentNode.objId;
+
+            if (objId && !pageKidsCountCache.has(objId)) {
+              pageKidsCountCache.put(objId, count);
+            }
+
+            if (currentPageIndex + count <= pageIndex) {
+              currentPageIndex += count;
+              return "continue";
+            }
+          }
+
+          var kids = currentNode.get('Kids');
+
+          if (!Array.isArray(kids)) {
+            if ((0, _primitives.isName)(currentNode.get('Type'), 'Page') || !currentNode.has('Type') && currentNode.has('Contents')) {
+              if (currentPageIndex === pageIndex) {
+                capability.resolve([currentNode, null]);
+                return {
+                  v: void 0
+                };
+              }
+
+              currentPageIndex++;
+              return "continue";
+            }
+
+            capability.reject(new _util.FormatError('Page dictionary kids object is not an array.'));
+            return {
+              v: void 0
+            };
+          }
+
+          for (var last = kids.length - 1; last >= 0; last--) {
+            nodesToVisit.push(kids[last]);
+          }
+        };
+
+        while (nodesToVisit.length) {
+          var _ret = _loop();
+
+          switch (_ret) {
+            case "continue":
+              continue;
+
+            default:
+              if (_typeof(_ret) === "object") return _ret.v;
+          }
+        }
+
+        capability.reject(new Error("Page index ".concat(pageIndex, " not found.")));
+      }
+
+      next();
+      return capability.promise;
+    }
+  }, {
+    key: "getPageIndex",
+    value: function getPageIndex(pageRef) {
+      var xref = this.xref;
+
+      function pagesBeforeRef(kidRef) {
+        var total = 0,
+            parentRef;
+        return xref.fetchAsync(kidRef).then(function (node) {
+          if ((0, _primitives.isRefsEqual)(kidRef, pageRef) && !(0, _primitives.isDict)(node, 'Page') && !((0, _primitives.isDict)(node) && !node.has('Type') && node.has('Contents'))) {
+            throw new _util.FormatError('The reference does not point to a /Page dictionary.');
+          }
+
+          if (!node) {
+            return null;
+          }
+
+          if (!(0, _primitives.isDict)(node)) {
+            throw new _util.FormatError('Node must be a dictionary.');
+          }
+
+          parentRef = node.getRaw('Parent');
+          return node.getAsync('Parent');
+        }).then(function (parent) {
+          if (!parent) {
+            return null;
+          }
+
+          if (!(0, _primitives.isDict)(parent)) {
+            throw new _util.FormatError('Parent must be a dictionary.');
+          }
+
+          return parent.getAsync('Kids');
+        }).then(function (kids) {
+          if (!kids) {
+            return null;
+          }
+
+          var kidPromises = [];
+          var found = false;
+
+          for (var i = 0, ii = kids.length; i < ii; i++) {
+            var kid = kids[i];
+
+            if (!(0, _primitives.isRef)(kid)) {
+              throw new _util.FormatError('Kid must be a reference.');
+            }
+
+            if ((0, _primitives.isRefsEqual)(kid, kidRef)) {
+              found = true;
+              break;
+            }
+
+            kidPromises.push(xref.fetchAsync(kid).then(function (kid) {
+              if (!(0, _primitives.isDict)(kid)) {
+                throw new _util.FormatError('Kid node must be a dictionary.');
+              }
+
+              if (kid.has('Count')) {
+                total += kid.get('Count');
+              } else {
+                total++;
+              }
+            }));
+          }
+
+          if (!found) {
+            throw new _util.FormatError('Kid reference not found in parent\'s kids.');
+          }
+
+          return Promise.all(kidPromises).then(function () {
+            return [total, parentRef];
+          });
+        });
+      }
+
+      var total = 0;
+
+      function next(ref) {
+        return pagesBeforeRef(ref).then(function (args) {
+          if (!args) {
+            return total;
+          }
+
+          var _args = _slicedToArray(args, 2),
+              count = _args[0],
+              parentRef = _args[1];
+
+          total += count;
+          return next(parentRef);
+        });
+      }
+
+      return next(pageRef);
+    }
+  }, {
+    key: "metadata",
+    get: function get() {
+      var streamRef = this.catDict.getRaw('Metadata');
+
+      if (!(0, _primitives.isRef)(streamRef)) {
+        return (0, _util.shadow)(this, 'metadata', null);
+      }
+
+      var suppressEncryption = !(this.xref.encrypt && this.xref.encrypt.encryptMetadata);
+      var stream = this.xref.fetch(streamRef, suppressEncryption);
+      var metadata;
+
+      if (stream && (0, _primitives.isDict)(stream.dict)) {
+        var type = stream.dict.get('Type');
+        var subtype = stream.dict.get('Subtype');
+
+        if ((0, _primitives.isName)(type, 'Metadata') && (0, _primitives.isName)(subtype, 'XML')) {
+          try {
+            metadata = (0, _util.stringToUTF8String)((0, _util.bytesToString)(stream.getBytes()));
+          } catch (e) {
+            if (e instanceof _core_utils.MissingDataException) {
+              throw e;
+            }
+
+            (0, _util.info)('Skipping invalid metadata.');
+          }
+        }
+      }
+
+      return (0, _util.shadow)(this, 'metadata', metadata);
+    }
+  }, {
+    key: "toplevelPagesDict",
+    get: function get() {
+      var pagesObj = this.catDict.get('Pages');
+
+      if (!(0, _primitives.isDict)(pagesObj)) {
+        throw new _util.FormatError('Invalid top-level pages dictionary.');
+      }
+
+      return (0, _util.shadow)(this, 'toplevelPagesDict', pagesObj);
+    }
+  }, {
+    key: "documentOutline",
+    get: function get() {
+      var obj = null;
+
+      try {
+        obj = this._readDocumentOutline();
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)('Unable to read document outline.');
+      }
+
+      return (0, _util.shadow)(this, 'documentOutline', obj);
+    }
+  }, {
+    key: "permissions",
+    get: function get() {
+      var permissions = null;
+
+      try {
+        permissions = this._readPermissions();
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)('Unable to read permissions.');
+      }
+
+      return (0, _util.shadow)(this, 'permissions', permissions);
+    }
+  }, {
+    key: "numPages",
+    get: function get() {
+      var obj = this.toplevelPagesDict.get('Count');
+
+      if (!Number.isInteger(obj)) {
+        throw new _util.FormatError('Page count in top-level pages dictionary is not an integer.');
+      }
+
+      return (0, _util.shadow)(this, 'numPages', obj);
+    }
+  }, {
+    key: "destinations",
+    get: function get() {
+      var obj = this._readDests(),
+          dests = Object.create(null);
+
+      if (obj instanceof NameTree) {
+        var names = obj.getAll();
+
+        for (var name in names) {
+          dests[name] = fetchDestination(names[name]);
+        }
+      } else if (obj instanceof _primitives.Dict) {
+        obj.forEach(function (key, value) {
+          if (value) {
+            dests[key] = fetchDestination(value);
+          }
+        });
+      }
+
+      return (0, _util.shadow)(this, 'destinations', dests);
+    }
+  }, {
+    key: "pageLabels",
+    get: function get() {
+      var obj = null;
+
+      try {
+        obj = this._readPageLabels();
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)('Unable to read page labels.');
+      }
+
+      return (0, _util.shadow)(this, 'pageLabels', obj);
+    }
+  }, {
+    key: "pageLayout",
+    get: function get() {
+      var obj = this.catDict.get('PageLayout');
+      var pageLayout = '';
+
+      if ((0, _primitives.isName)(obj)) {
+        switch (obj.name) {
+          case 'SinglePage':
+          case 'OneColumn':
+          case 'TwoColumnLeft':
+          case 'TwoColumnRight':
+          case 'TwoPageLeft':
+          case 'TwoPageRight':
+            pageLayout = obj.name;
+        }
+      }
+
+      return (0, _util.shadow)(this, 'pageLayout', pageLayout);
+    }
+  }, {
+    key: "pageMode",
+    get: function get() {
+      var obj = this.catDict.get('PageMode');
+      var pageMode = 'UseNone';
+
+      if ((0, _primitives.isName)(obj)) {
+        switch (obj.name) {
+          case 'UseNone':
+          case 'UseOutlines':
+          case 'UseThumbs':
+          case 'FullScreen':
+          case 'UseOC':
+          case 'UseAttachments':
+            pageMode = obj.name;
+        }
+      }
+
+      return (0, _util.shadow)(this, 'pageMode', pageMode);
+    }
+  }, {
+    key: "viewerPreferences",
+    get: function get() {
+      var _this2 = this;
+
+      var ViewerPreferencesValidators = {
+        HideToolbar: _util.isBool,
+        HideMenubar: _util.isBool,
+        HideWindowUI: _util.isBool,
+        FitWindow: _util.isBool,
+        CenterWindow: _util.isBool,
+        DisplayDocTitle: _util.isBool,
+        NonFullScreenPageMode: _primitives.isName,
+        Direction: _primitives.isName,
+        ViewArea: _primitives.isName,
+        ViewClip: _primitives.isName,
+        PrintArea: _primitives.isName,
+        PrintClip: _primitives.isName,
+        PrintScaling: _primitives.isName,
+        Duplex: _primitives.isName,
+        PickTrayByPDFSize: _util.isBool,
+        PrintPageRange: Array.isArray,
+        NumCopies: Number.isInteger
+      };
+      var obj = this.catDict.get('ViewerPreferences');
+      var prefs = Object.create(null);
+
+      if ((0, _primitives.isDict)(obj)) {
+        for (var key in ViewerPreferencesValidators) {
+          if (!obj.has(key)) {
+            continue;
+          }
+
+          var value = obj.get(key);
+
+          if (!ViewerPreferencesValidators[key](value)) {
+            (0, _util.info)("Bad value in ViewerPreferences for \"".concat(key, "\"."));
+            continue;
+          }
+
+          var prefValue = void 0;
+
+          switch (key) {
+            case 'NonFullScreenPageMode':
+              switch (value.name) {
+                case 'UseNone':
+                case 'UseOutlines':
+                case 'UseThumbs':
+                case 'UseOC':
+                  prefValue = value.name;
+                  break;
+
+                default:
+                  prefValue = 'UseNone';
+              }
+
+              break;
+
+            case 'Direction':
+              switch (value.name) {
+                case 'L2R':
+                case 'R2L':
+                  prefValue = value.name;
+                  break;
+
+                default:
+                  prefValue = 'L2R';
+              }
+
+              break;
+
+            case 'ViewArea':
+            case 'ViewClip':
+            case 'PrintArea':
+            case 'PrintClip':
+              switch (value.name) {
+                case 'MediaBox':
+                case 'CropBox':
+                case 'BleedBox':
+                case 'TrimBox':
+                case 'ArtBox':
+                  prefValue = value.name;
+                  break;
+
+                default:
+                  prefValue = 'CropBox';
+              }
+
+              break;
+
+            case 'PrintScaling':
+              switch (value.name) {
+                case 'None':
+                case 'AppDefault':
+                  prefValue = value.name;
+                  break;
+
+                default:
+                  prefValue = 'AppDefault';
+              }
+
+              break;
+
+            case 'Duplex':
+              switch (value.name) {
+                case 'Simplex':
+                case 'DuplexFlipShortEdge':
+                case 'DuplexFlipLongEdge':
+                  prefValue = value.name;
+                  break;
+
+                default:
+                  prefValue = 'None';
+              }
+
+              break;
+
+            case 'PrintPageRange':
+              var length = value.length;
+
+              if (length % 2 !== 0) {
+                break;
+              }
+
+              var isValid = value.every(function (page, i, arr) {
+                return Number.isInteger(page) && page > 0 && (i === 0 || page >= arr[i - 1]) && page <= _this2.numPages;
+              });
+
+              if (isValid) {
+                prefValue = value;
+              }
+
+              break;
+
+            case 'NumCopies':
+              if (value > 0) {
+                prefValue = value;
+              }
+
+              break;
+
+            default:
+              (0, _util.assert)(typeof value === 'boolean');
+              prefValue = value;
+          }
+
+          if (prefValue !== undefined) {
+            prefs[key] = prefValue;
+          } else {
+            (0, _util.info)("Bad value in ViewerPreferences for \"".concat(key, "\"."));
+          }
+        }
+      }
+
+      return (0, _util.shadow)(this, 'viewerPreferences', prefs);
+    }
+  }, {
+    key: "openActionDestination",
+    get: function get() {
+      var obj = this.catDict.get('OpenAction');
+      var openActionDest = null;
+
+      if ((0, _primitives.isDict)(obj)) {
+        var destDict = new _primitives.Dict(this.xref);
+        destDict.set('A', obj);
+        var resultObj = {
+          url: null,
+          dest: null
+        };
+        Catalog.parseDestDictionary({
+          destDict: destDict,
+          resultObj: resultObj
+        });
+
+        if (Array.isArray(resultObj.dest)) {
+          openActionDest = resultObj.dest;
+        }
+      } else if (Array.isArray(obj)) {
+        openActionDest = obj;
+      }
+
+      return (0, _util.shadow)(this, 'openActionDestination', openActionDest);
+    }
+  }, {
+    key: "attachments",
+    get: function get() {
+      var obj = this.catDict.get('Names');
+      var attachments = null;
+
+      if (obj && obj.has('EmbeddedFiles')) {
+        var nameTree = new NameTree(obj.getRaw('EmbeddedFiles'), this.xref);
+        var names = nameTree.getAll();
+
+        for (var name in names) {
+          var fs = new FileSpec(names[name], this.xref);
+
+          if (!attachments) {
+            attachments = Object.create(null);
+          }
+
+          attachments[(0, _util.stringToPDFString)(name)] = fs.serializable;
+        }
+      }
+
+      return (0, _util.shadow)(this, 'attachments', attachments);
+    }
+  }, {
+    key: "javaScript",
+    get: function get() {
+      var obj = this.catDict.get('Names');
+      var javaScript = null;
+
+      function appendIfJavaScriptDict(jsDict) {
+        var type = jsDict.get('S');
+
+        if (!(0, _primitives.isName)(type, 'JavaScript')) {
+          return;
+        }
+
+        var js = jsDict.get('JS');
+
+        if ((0, _primitives.isStream)(js)) {
+          js = (0, _util.bytesToString)(js.getBytes());
+        } else if (!(0, _util.isString)(js)) {
+          return;
+        }
+
+        if (!javaScript) {
+          javaScript = [];
+        }
+
+        javaScript.push((0, _util.stringToPDFString)(js));
+      }
+
+      if (obj && obj.has('JavaScript')) {
+        var nameTree = new NameTree(obj.getRaw('JavaScript'), this.xref);
+        var names = nameTree.getAll();
+
+        for (var name in names) {
+          var jsDict = names[name];
+
+          if ((0, _primitives.isDict)(jsDict)) {
+            appendIfJavaScriptDict(jsDict);
+          }
+        }
+      }
+
+      var openActionDict = this.catDict.get('OpenAction');
+
+      if ((0, _primitives.isDict)(openActionDict, 'Action')) {
+        var actionType = openActionDict.get('S');
+
+        if ((0, _primitives.isName)(actionType, 'Named')) {
+          var action = openActionDict.get('N');
+
+          if ((0, _primitives.isName)(action, 'Print')) {
+            if (!javaScript) {
+              javaScript = [];
+            }
+
+            javaScript.push('print({});');
+          }
+        } else {
+          appendIfJavaScriptDict(openActionDict);
+        }
+      }
+
+      return (0, _util.shadow)(this, 'javaScript', javaScript);
+    }
+  }], [{
+    key: "parseDestDictionary",
+    value: function parseDestDictionary(params) {
+      function addDefaultProtocolToUrl(url) {
+        return url.startsWith('www.') ? "http://".concat(url) : url;
+      }
+
+      function tryConvertUrlEncoding(url) {
+        try {
+          return (0, _util.stringToUTF8String)(url);
+        } catch (e) {
+          return url;
+        }
+      }
+
+      var destDict = params.destDict;
+
+      if (!(0, _primitives.isDict)(destDict)) {
+        (0, _util.warn)('parseDestDictionary: `destDict` must be a dictionary.');
+        return;
+      }
+
+      var resultObj = params.resultObj;
+
+      if (_typeof(resultObj) !== 'object') {
+        (0, _util.warn)('parseDestDictionary: `resultObj` must be an object.');
+        return;
+      }
+
+      var docBaseUrl = params.docBaseUrl || null;
+      var action = destDict.get('A'),
+          url,
+          dest;
+
+      if (!(0, _primitives.isDict)(action) && destDict.has('Dest')) {
+        action = destDict.get('Dest');
+      }
+
+      if ((0, _primitives.isDict)(action)) {
+        var actionType = action.get('S');
+
+        if (!(0, _primitives.isName)(actionType)) {
+          (0, _util.warn)('parseDestDictionary: Invalid type in Action dictionary.');
+          return;
+        }
+
+        var actionName = actionType.name;
+
+        switch (actionName) {
+          case 'URI':
+            url = action.get('URI');
+
+            if ((0, _primitives.isName)(url)) {
+              url = '/' + url.name;
+            } else if ((0, _util.isString)(url)) {
+              url = addDefaultProtocolToUrl(url);
+            }
+
+            break;
+
+          case 'GoTo':
+            dest = action.get('D');
+            break;
+
+          case 'Launch':
+          case 'GoToR':
+            var urlDict = action.get('F');
+
+            if ((0, _primitives.isDict)(urlDict)) {
+              url = urlDict.get('F') || null;
+            } else if ((0, _util.isString)(urlDict)) {
+              url = urlDict;
+            }
+
+            var remoteDest = action.get('D');
+
+            if (remoteDest) {
+              if ((0, _primitives.isName)(remoteDest)) {
+                remoteDest = remoteDest.name;
+              }
+
+              if ((0, _util.isString)(url)) {
+                var baseUrl = url.split('#')[0];
+
+                if ((0, _util.isString)(remoteDest)) {
+                  url = baseUrl + '#' + remoteDest;
+                } else if (Array.isArray(remoteDest)) {
+                  url = baseUrl + '#' + JSON.stringify(remoteDest);
+                }
+              }
+            }
+
+            var newWindow = action.get('NewWindow');
+
+            if ((0, _util.isBool)(newWindow)) {
+              resultObj.newWindow = newWindow;
+            }
+
+            break;
+
+          case 'Named':
+            var namedAction = action.get('N');
+
+            if ((0, _primitives.isName)(namedAction)) {
+              resultObj.action = namedAction.name;
+            }
+
+            break;
+
+          case 'JavaScript':
+            var jsAction = action.get('JS');
+            var js;
+
+            if ((0, _primitives.isStream)(jsAction)) {
+              js = (0, _util.bytesToString)(jsAction.getBytes());
+            } else if ((0, _util.isString)(jsAction)) {
+              js = jsAction;
+            }
+
+            if (js) {
+              var URL_OPEN_METHODS = ['app.launchURL', 'window.open'];
+              var regex = new RegExp('^\\s*(' + URL_OPEN_METHODS.join('|').split('.').join('\\.') + ')\\((?:\'|\")([^\'\"]*)(?:\'|\")(?:,\\s*(\\w+)\\)|\\))', 'i');
+              var jsUrl = regex.exec((0, _util.stringToPDFString)(js));
+
+              if (jsUrl && jsUrl[2]) {
+                url = jsUrl[2];
+
+                if (jsUrl[3] === 'true' && jsUrl[1] === 'app.launchURL') {
+                  resultObj.newWindow = true;
+                }
+
+                break;
+              }
+            }
+
+          default:
+            (0, _util.warn)("parseDestDictionary: unsupported action type \"".concat(actionName, "\"."));
+            break;
+        }
+      } else if (destDict.has('Dest')) {
+        dest = destDict.get('Dest');
+      }
+
+      if ((0, _util.isString)(url)) {
+        url = tryConvertUrlEncoding(url);
+        var absoluteUrl = (0, _util.createValidAbsoluteUrl)(url, docBaseUrl);
+
+        if (absoluteUrl) {
+          resultObj.url = absoluteUrl.href;
+        }
+
+        resultObj.unsafeUrl = url;
+      }
+
+      if (dest) {
+        if ((0, _primitives.isName)(dest)) {
+          dest = dest.name;
+        }
+
+        if ((0, _util.isString)(dest) || Array.isArray(dest)) {
+          resultObj.dest = dest;
+        }
+      }
+    }
+  }]);
+
+  return Catalog;
+}();
+
+exports.Catalog = Catalog;
+
+var XRef = function XRefClosure() {
+  function XRef(stream, pdfManager) {
+    this.stream = stream;
+    this.pdfManager = pdfManager;
+    this.entries = [];
+    this.xrefstms = Object.create(null);
+    this.cache = [];
+    this.stats = {
+      streamTypes: [],
+      fontTypes: []
+    };
+  }
+
+  XRef.prototype = {
+    setStartXRef: function XRef_setStartXRef(startXRef) {
+      this.startXRefQueue = [startXRef];
+    },
+    parse: function XRef_parse(recoveryMode) {
+      var trailerDict;
+
+      if (!recoveryMode) {
+        trailerDict = this.readXRef();
+      } else {
+        (0, _util.warn)('Indexing all PDF objects');
+        trailerDict = this.indexObjects();
+      }
+
+      trailerDict.assignXref(this);
+      this.trailer = trailerDict;
+      var encrypt;
+
+      try {
+        encrypt = trailerDict.get('Encrypt');
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)("XRef.parse - Invalid \"Encrypt\" reference: \"".concat(ex, "\"."));
+      }
+
+      if ((0, _primitives.isDict)(encrypt)) {
+        var ids = trailerDict.get('ID');
+        var fileId = ids && ids.length ? ids[0] : '';
+        encrypt.suppressEncryption = true;
+        this.encrypt = new _crypto.CipherTransformFactory(encrypt, fileId, this.pdfManager.password);
+      }
+
+      var root;
+
+      try {
+        root = trailerDict.get('Root');
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)("XRef.parse - Invalid \"Root\" reference: \"".concat(ex, "\"."));
+      }
+
+      if ((0, _primitives.isDict)(root) && root.has('Pages')) {
+        this.root = root;
+      } else {
+        if (!recoveryMode) {
+          throw new _core_utils.XRefParseException();
+        }
+
+        throw new _util.FormatError('Invalid root reference');
+      }
+    },
+    processXRefTable: function XRef_processXRefTable(parser) {
+      if (!('tableState' in this)) {
+        this.tableState = {
+          entryNum: 0,
+          streamPos: parser.lexer.stream.pos,
+          parserBuf1: parser.buf1,
+          parserBuf2: parser.buf2
+        };
+      }
+
+      var obj = this.readXRefTable(parser);
+
+      if (!(0, _primitives.isCmd)(obj, 'trailer')) {
+        throw new _util.FormatError('Invalid XRef table: could not find trailer dictionary');
+      }
+
+      var dict = parser.getObj();
+
+      if (!(0, _primitives.isDict)(dict) && dict.dict) {
+        dict = dict.dict;
+      }
+
+      if (!(0, _primitives.isDict)(dict)) {
+        throw new _util.FormatError('Invalid XRef table: could not parse trailer dictionary');
+      }
+
+      delete this.tableState;
+      return dict;
+    },
+    readXRefTable: function XRef_readXRefTable(parser) {
+      var stream = parser.lexer.stream;
+      var tableState = this.tableState;
+      stream.pos = tableState.streamPos;
+      parser.buf1 = tableState.parserBuf1;
+      parser.buf2 = tableState.parserBuf2;
+      var obj;
+
+      while (true) {
+        if (!('firstEntryNum' in tableState) || !('entryCount' in tableState)) {
+          if ((0, _primitives.isCmd)(obj = parser.getObj(), 'trailer')) {
+            break;
+          }
+
+          tableState.firstEntryNum = obj;
+          tableState.entryCount = parser.getObj();
+        }
+
+        var first = tableState.firstEntryNum;
+        var count = tableState.entryCount;
+
+        if (!Number.isInteger(first) || !Number.isInteger(count)) {
+          throw new _util.FormatError('Invalid XRef table: wrong types in subsection header');
+        }
+
+        for (var i = tableState.entryNum; i < count; i++) {
+          tableState.streamPos = stream.pos;
+          tableState.entryNum = i;
+          tableState.parserBuf1 = parser.buf1;
+          tableState.parserBuf2 = parser.buf2;
+          var entry = {};
+          entry.offset = parser.getObj();
+          entry.gen = parser.getObj();
+          var type = parser.getObj();
+
+          if (type instanceof _primitives.Cmd) {
+            switch (type.cmd) {
+              case 'f':
+                entry.free = true;
+                break;
+
+              case 'n':
+                entry.uncompressed = true;
+                break;
+            }
+          }
+
+          if (!Number.isInteger(entry.offset) || !Number.isInteger(entry.gen) || !(entry.free || entry.uncompressed)) {
+            throw new _util.FormatError("Invalid entry in XRef subsection: ".concat(first, ", ").concat(count));
+          }
+
+          if (i === 0 && entry.free && first === 1) {
+            first = 0;
+          }
+
+          if (!this.entries[i + first]) {
+            this.entries[i + first] = entry;
+          }
+        }
+
+        tableState.entryNum = 0;
+        tableState.streamPos = stream.pos;
+        tableState.parserBuf1 = parser.buf1;
+        tableState.parserBuf2 = parser.buf2;
+        delete tableState.firstEntryNum;
+        delete tableState.entryCount;
+      }
+
+      if (this.entries[0] && !this.entries[0].free) {
+        throw new _util.FormatError('Invalid XRef table: unexpected first object');
+      }
+
+      return obj;
+    },
+    processXRefStream: function XRef_processXRefStream(stream) {
+      if (!('streamState' in this)) {
+        var streamParameters = stream.dict;
+        var byteWidths = streamParameters.get('W');
+        var range = streamParameters.get('Index');
+
+        if (!range) {
+          range = [0, streamParameters.get('Size')];
+        }
+
+        this.streamState = {
+          entryRanges: range,
+          byteWidths: byteWidths,
+          entryNum: 0,
+          streamPos: stream.pos
+        };
+      }
+
+      this.readXRefStream(stream);
+      delete this.streamState;
+      return stream.dict;
+    },
+    readXRefStream: function XRef_readXRefStream(stream) {
+      var i, j;
+      var streamState = this.streamState;
+      stream.pos = streamState.streamPos;
+      var byteWidths = streamState.byteWidths;
+      var typeFieldWidth = byteWidths[0];
+      var offsetFieldWidth = byteWidths[1];
+      var generationFieldWidth = byteWidths[2];
+      var entryRanges = streamState.entryRanges;
+
+      while (entryRanges.length > 0) {
+        var first = entryRanges[0];
+        var n = entryRanges[1];
+
+        if (!Number.isInteger(first) || !Number.isInteger(n)) {
+          throw new _util.FormatError("Invalid XRef range fields: ".concat(first, ", ").concat(n));
+        }
+
+        if (!Number.isInteger(typeFieldWidth) || !Number.isInteger(offsetFieldWidth) || !Number.isInteger(generationFieldWidth)) {
+          throw new _util.FormatError("Invalid XRef entry fields length: ".concat(first, ", ").concat(n));
+        }
+
+        for (i = streamState.entryNum; i < n; ++i) {
+          streamState.entryNum = i;
+          streamState.streamPos = stream.pos;
+          var type = 0,
+              offset = 0,
+              generation = 0;
+
+          for (j = 0; j < typeFieldWidth; ++j) {
+            type = type << 8 | stream.getByte();
+          }
+
+          if (typeFieldWidth === 0) {
+            type = 1;
+          }
+
+          for (j = 0; j < offsetFieldWidth; ++j) {
+            offset = offset << 8 | stream.getByte();
+          }
+
+          for (j = 0; j < generationFieldWidth; ++j) {
+            generation = generation << 8 | stream.getByte();
+          }
+
+          var entry = {};
+          entry.offset = offset;
+          entry.gen = generation;
+
+          switch (type) {
+            case 0:
+              entry.free = true;
+              break;
+
+            case 1:
+              entry.uncompressed = true;
+              break;
+
+            case 2:
+              break;
+
+            default:
+              throw new _util.FormatError("Invalid XRef entry type: ".concat(type));
+          }
+
+          if (!this.entries[first + i]) {
+            this.entries[first + i] = entry;
+          }
+        }
+
+        streamState.entryNum = 0;
+        streamState.streamPos = stream.pos;
+        entryRanges.splice(0, 2);
+      }
+    },
+    indexObjects: function XRef_indexObjects() {
+      var TAB = 0x9,
+          LF = 0xA,
+          CR = 0xD,
+          SPACE = 0x20;
+      var PERCENT = 0x25,
+          LT = 0x3C;
+
+      function readToken(data, offset) {
+        var token = '',
+            ch = data[offset];
+
+        while (ch !== LF && ch !== CR && ch !== LT) {
+          if (++offset >= data.length) {
+            break;
+          }
+
+          token += String.fromCharCode(ch);
+          ch = data[offset];
+        }
+
+        return token;
+      }
+
+      function skipUntil(data, offset, what) {
+        var length = what.length,
+            dataLength = data.length;
+        var skipped = 0;
+
+        while (offset < dataLength) {
+          var i = 0;
+
+          while (i < length && data[offset + i] === what[i]) {
+            ++i;
+          }
+
+          if (i >= length) {
+            break;
+          }
+
+          offset++;
+          skipped++;
+        }
+
+        return skipped;
+      }
+
+      var objRegExp = /^(\d+)\s+(\d+)\s+obj\b/;
+      var endobjRegExp = /\bendobj[\b\s]$/;
+      var nestedObjRegExp = /\s+(\d+\s+\d+\s+obj[\b\s<])$/;
+      var CHECK_CONTENT_LENGTH = 25;
+      var trailerBytes = new Uint8Array([116, 114, 97, 105, 108, 101, 114]);
+      var startxrefBytes = new Uint8Array([115, 116, 97, 114, 116, 120, 114, 101, 102]);
+      var objBytes = new Uint8Array([111, 98, 106]);
+      var xrefBytes = new Uint8Array([47, 88, 82, 101, 102]);
+      this.entries.length = 0;
+      var stream = this.stream;
+      stream.pos = 0;
+      var buffer = stream.getBytes();
+      var position = stream.start,
+          length = buffer.length;
+      var trailers = [],
+          xrefStms = [];
+
+      while (position < length) {
+        var ch = buffer[position];
+
+        if (ch === TAB || ch === LF || ch === CR || ch === SPACE) {
+          ++position;
+          continue;
+        }
+
+        if (ch === PERCENT) {
+          do {
+            ++position;
+
+            if (position >= length) {
+              break;
+            }
+
+            ch = buffer[position];
+          } while (ch !== LF && ch !== CR);
+
+          continue;
+        }
+
+        var token = readToken(buffer, position);
+        var m;
+
+        if (token.startsWith('xref') && (token.length === 4 || /\s/.test(token[4]))) {
+          position += skipUntil(buffer, position, trailerBytes);
+          trailers.push(position);
+          position += skipUntil(buffer, position, startxrefBytes);
+        } else if (m = objRegExp.exec(token)) {
+          var num = m[1] | 0,
+              gen = m[2] | 0;
+
+          if (typeof this.entries[num] === 'undefined') {
+            this.entries[num] = {
+              offset: position - stream.start,
+              gen: gen,
+              uncompressed: true
+            };
+          }
+
+          var contentLength = void 0,
+              startPos = position + token.length;
+
+          while (startPos < buffer.length) {
+            var endPos = startPos + skipUntil(buffer, startPos, objBytes) + 4;
+            contentLength = endPos - position;
+            var checkPos = Math.max(endPos - CHECK_CONTENT_LENGTH, startPos);
+            var tokenStr = (0, _util.bytesToString)(buffer.subarray(checkPos, endPos));
+
+            if (endobjRegExp.test(tokenStr)) {
+              break;
+            } else {
+              var objToken = nestedObjRegExp.exec(tokenStr);
+
+              if (objToken && objToken[1]) {
+                (0, _util.warn)('indexObjects: Found new "obj" inside of another "obj", ' + 'caused by missing "endobj" -- trying to recover.');
+                contentLength -= objToken[1].length;
+                break;
+              }
+            }
+
+            startPos = endPos;
+          }
+
+          var content = buffer.subarray(position, position + contentLength);
+          var xrefTagOffset = skipUntil(content, 0, xrefBytes);
+
+          if (xrefTagOffset < contentLength && content[xrefTagOffset + 5] < 64) {
+            xrefStms.push(position - stream.start);
+            this.xrefstms[position - stream.start] = 1;
+          }
+
+          position += contentLength;
+        } else if (token.startsWith('trailer') && (token.length === 7 || /\s/.test(token[7]))) {
+          trailers.push(position);
+          position += skipUntil(buffer, position, startxrefBytes);
+        } else {
+          position += token.length + 1;
+        }
+      }
+
+      var i, ii;
+
+      for (i = 0, ii = xrefStms.length; i < ii; ++i) {
+        this.startXRefQueue.push(xrefStms[i]);
+        this.readXRef(true);
+      }
+
+      var trailerDict;
+
+      for (i = 0, ii = trailers.length; i < ii; ++i) {
+        stream.pos = trailers[i];
+        var parser = new _parser.Parser({
+          lexer: new _parser.Lexer(stream),
+          xref: this,
+          allowStreams: true,
+          recoveryMode: true
+        });
+        var obj = parser.getObj();
+
+        if (!(0, _primitives.isCmd)(obj, 'trailer')) {
+          continue;
+        }
+
+        var dict = parser.getObj();
+
+        if (!(0, _primitives.isDict)(dict)) {
+          continue;
+        }
+
+        var rootDict = void 0;
+
+        try {
+          rootDict = dict.get('Root');
+        } catch (ex) {
+          if (ex instanceof _core_utils.MissingDataException) {
+            throw ex;
+          }
+
+          continue;
+        }
+
+        if (!(0, _primitives.isDict)(rootDict) || !rootDict.has('Pages')) {
+          continue;
+        }
+
+        if (dict.has('ID')) {
+          return dict;
+        }
+
+        trailerDict = dict;
+      }
+
+      if (trailerDict) {
+        return trailerDict;
+      }
+
+      throw new _util.InvalidPDFException('Invalid PDF structure');
+    },
+    readXRef: function XRef_readXRef(recoveryMode) {
+      var stream = this.stream;
+      var startXRefParsedCache = Object.create(null);
+
+      try {
+        while (this.startXRefQueue.length) {
+          var startXRef = this.startXRefQueue[0];
+
+          if (startXRefParsedCache[startXRef]) {
+            (0, _util.warn)('readXRef - skipping XRef table since it was already parsed.');
+            this.startXRefQueue.shift();
+            continue;
+          }
+
+          startXRefParsedCache[startXRef] = true;
+          stream.pos = startXRef + stream.start;
+          var parser = new _parser.Parser({
+            lexer: new _parser.Lexer(stream),
+            xref: this,
+            allowStreams: true
+          });
+          var obj = parser.getObj();
+          var dict;
+
+          if ((0, _primitives.isCmd)(obj, 'xref')) {
+            dict = this.processXRefTable(parser);
+
+            if (!this.topDict) {
+              this.topDict = dict;
+            }
+
+            obj = dict.get('XRefStm');
+
+            if (Number.isInteger(obj)) {
+              var pos = obj;
+
+              if (!(pos in this.xrefstms)) {
+                this.xrefstms[pos] = 1;
+                this.startXRefQueue.push(pos);
+              }
+            }
+          } else if (Number.isInteger(obj)) {
+            if (!Number.isInteger(parser.getObj()) || !(0, _primitives.isCmd)(parser.getObj(), 'obj') || !(0, _primitives.isStream)(obj = parser.getObj())) {
+              throw new _util.FormatError('Invalid XRef stream');
+            }
+
+            dict = this.processXRefStream(obj);
+
+            if (!this.topDict) {
+              this.topDict = dict;
+            }
+
+            if (!dict) {
+              throw new _util.FormatError('Failed to read XRef stream');
+            }
+          } else {
+            throw new _util.FormatError('Invalid XRef stream header');
+          }
+
+          obj = dict.get('Prev');
+
+          if (Number.isInteger(obj)) {
+            this.startXRefQueue.push(obj);
+          } else if ((0, _primitives.isRef)(obj)) {
+            this.startXRefQueue.push(obj.num);
+          }
+
+          this.startXRefQueue.shift();
+        }
+
+        return this.topDict;
+      } catch (e) {
+        if (e instanceof _core_utils.MissingDataException) {
+          throw e;
+        }
+
+        (0, _util.info)('(while reading XRef): ' + e);
+      }
+
+      if (recoveryMode) {
+        return undefined;
+      }
+
+      throw new _core_utils.XRefParseException();
+    },
+    getEntry: function XRef_getEntry(i) {
+      var xrefEntry = this.entries[i];
+
+      if (xrefEntry && !xrefEntry.free && xrefEntry.offset) {
+        return xrefEntry;
+      }
+
+      return null;
+    },
+    fetchIfRef: function XRef_fetchIfRef(obj, suppressEncryption) {
+      if (!(0, _primitives.isRef)(obj)) {
+        return obj;
+      }
+
+      return this.fetch(obj, suppressEncryption);
+    },
+    fetch: function XRef_fetch(ref, suppressEncryption) {
+      if (!(0, _primitives.isRef)(ref)) {
+        throw new Error('ref object is not a reference');
+      }
+
+      var num = ref.num;
+
+      if (num in this.cache) {
+        var cacheEntry = this.cache[num];
+
+        if (cacheEntry instanceof _primitives.Dict && !cacheEntry.objId) {
+          cacheEntry.objId = ref.toString();
+        }
+
+        return cacheEntry;
+      }
+
+      var xrefEntry = this.getEntry(num);
+
+      if (xrefEntry === null) {
+        return this.cache[num] = null;
+      }
+
+      if (xrefEntry.uncompressed) {
+        xrefEntry = this.fetchUncompressed(ref, xrefEntry, suppressEncryption);
+      } else {
+        xrefEntry = this.fetchCompressed(ref, xrefEntry, suppressEncryption);
+      }
+
+      if ((0, _primitives.isDict)(xrefEntry)) {
+        xrefEntry.objId = ref.toString();
+      } else if ((0, _primitives.isStream)(xrefEntry)) {
+        xrefEntry.dict.objId = ref.toString();
+      }
+
+      return xrefEntry;
+    },
+    fetchUncompressed: function fetchUncompressed(ref, xrefEntry) {
+      var suppressEncryption = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+      var gen = ref.gen;
+      var num = ref.num;
+
+      if (xrefEntry.gen !== gen) {
+        throw new _core_utils.XRefEntryException("Inconsistent generation in XRef: ".concat(ref));
+      }
+
+      var stream = this.stream.makeSubStream(xrefEntry.offset + this.stream.start);
+      var parser = new _parser.Parser({
+        lexer: new _parser.Lexer(stream),
+        xref: this,
+        allowStreams: true
+      });
+      var obj1 = parser.getObj();
+      var obj2 = parser.getObj();
+      var obj3 = parser.getObj();
+
+      if (!Number.isInteger(obj1)) {
+        obj1 = parseInt(obj1, 10);
+      }
+
+      if (!Number.isInteger(obj2)) {
+        obj2 = parseInt(obj2, 10);
+      }
+
+      if (obj1 !== num || obj2 !== gen || !(obj3 instanceof _primitives.Cmd)) {
+        throw new _core_utils.XRefEntryException("Bad (uncompressed) XRef entry: ".concat(ref));
+      }
+
+      if (obj3.cmd !== 'obj') {
+        if (obj3.cmd.startsWith('obj')) {
+          num = parseInt(obj3.cmd.substring(3), 10);
+
+          if (!Number.isNaN(num)) {
+            return num;
+          }
+        }
+
+        throw new _core_utils.XRefEntryException("Bad (uncompressed) XRef entry: ".concat(ref));
+      }
+
+      if (this.encrypt && !suppressEncryption) {
+        xrefEntry = parser.getObj(this.encrypt.createCipherTransform(num, gen));
+      } else {
+        xrefEntry = parser.getObj();
+      }
+
+      if (!(0, _primitives.isStream)(xrefEntry)) {
+        this.cache[num] = xrefEntry;
+      }
+
+      return xrefEntry;
+    },
+    fetchCompressed: function fetchCompressed(ref, xrefEntry) {
+      var suppressEncryption = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+      var tableOffset = xrefEntry.offset;
+      var stream = this.fetch(_primitives.Ref.get(tableOffset, 0));
+
+      if (!(0, _primitives.isStream)(stream)) {
+        throw new _util.FormatError('bad ObjStm stream');
+      }
+
+      var first = stream.dict.get('First');
+      var n = stream.dict.get('N');
+
+      if (!Number.isInteger(first) || !Number.isInteger(n)) {
+        throw new _util.FormatError('invalid first and n parameters for ObjStm stream');
+      }
+
+      var parser = new _parser.Parser({
+        lexer: new _parser.Lexer(stream),
+        xref: this,
+        allowStreams: true
+      });
+      var i,
+          entries = [],
+          num,
+          nums = [];
+
+      for (i = 0; i < n; ++i) {
+        num = parser.getObj();
+
+        if (!Number.isInteger(num)) {
+          throw new _util.FormatError("invalid object number in the ObjStm stream: ".concat(num));
+        }
+
+        nums.push(num);
+        var offset = parser.getObj();
+
+        if (!Number.isInteger(offset)) {
+          throw new _util.FormatError("invalid object offset in the ObjStm stream: ".concat(offset));
+        }
+      }
+
+      for (i = 0; i < n; ++i) {
+        entries.push(parser.getObj());
+
+        if ((0, _primitives.isCmd)(parser.buf1, 'endobj')) {
+          parser.shift();
+        }
+
+        num = nums[i];
+        var entry = this.entries[num];
+
+        if (entry && entry.offset === tableOffset && entry.gen === i) {
+          this.cache[num] = entries[i];
+        }
+      }
+
+      xrefEntry = entries[xrefEntry.gen];
+
+      if (xrefEntry === undefined) {
+        throw new _core_utils.XRefEntryException("Bad (compressed) XRef entry: ".concat(ref));
+      }
+
+      return xrefEntry;
+    },
+    fetchIfRefAsync: function () {
+      var _fetchIfRefAsync = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee(obj, suppressEncryption) {
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                if ((0, _primitives.isRef)(obj)) {
+                  _context.next = 2;
+                  break;
+                }
+
+                return _context.abrupt("return", obj);
+
+              case 2:
+                return _context.abrupt("return", this.fetchAsync(obj, suppressEncryption));
+
+              case 3:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function fetchIfRefAsync(_x, _x2) {
+        return _fetchIfRefAsync.apply(this, arguments);
+      }
+
+      return fetchIfRefAsync;
+    }(),
+    fetchAsync: function () {
+      var _fetchAsync = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2(ref, suppressEncryption) {
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                _context2.prev = 0;
+                return _context2.abrupt("return", this.fetch(ref, suppressEncryption));
+
+              case 4:
+                _context2.prev = 4;
+                _context2.t0 = _context2["catch"](0);
+
+                if (_context2.t0 instanceof _core_utils.MissingDataException) {
+                  _context2.next = 8;
+                  break;
+                }
+
+                throw _context2.t0;
+
+              case 8:
+                _context2.next = 10;
+                return this.pdfManager.requestRange(_context2.t0.begin, _context2.t0.end);
+
+              case 10:
+                return _context2.abrupt("return", this.fetchAsync(ref, suppressEncryption));
+
+              case 11:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this, [[0, 4]]);
+      }));
+
+      function fetchAsync(_x3, _x4) {
+        return _fetchAsync.apply(this, arguments);
+      }
+
+      return fetchAsync;
+    }(),
+    getCatalogObj: function XRef_getCatalogObj() {
+      return this.root;
+    }
+  };
+  return XRef;
+}();
+
+exports.XRef = XRef;
+
+var NameOrNumberTree =
+/*#__PURE__*/
+function () {
+  function NameOrNumberTree(root, xref, type) {
+    _classCallCheck(this, NameOrNumberTree);
+
+    if (this.constructor === NameOrNumberTree) {
+      (0, _util.unreachable)('Cannot initialize NameOrNumberTree.');
+    }
+
+    this.root = root;
+    this.xref = xref;
+    this._type = type;
+  }
+
+  _createClass(NameOrNumberTree, [{
+    key: "getAll",
+    value: function getAll() {
+      var dict = Object.create(null);
+
+      if (!this.root) {
+        return dict;
+      }
+
+      var xref = this.xref;
+      var processed = new _primitives.RefSet();
+      processed.put(this.root);
+      var queue = [this.root];
+
+      while (queue.length > 0) {
+        var obj = xref.fetchIfRef(queue.shift());
+
+        if (!(0, _primitives.isDict)(obj)) {
+          continue;
+        }
+
+        if (obj.has('Kids')) {
+          var kids = obj.get('Kids');
+
+          for (var i = 0, ii = kids.length; i < ii; i++) {
+            var kid = kids[i];
+
+            if (processed.has(kid)) {
+              throw new _util.FormatError("Duplicate entry in \"".concat(this._type, "\" tree."));
+            }
+
+            queue.push(kid);
+            processed.put(kid);
+          }
+
+          continue;
+        }
+
+        var entries = obj.get(this._type);
+
+        if (Array.isArray(entries)) {
+          for (var _i2 = 0, _ii = entries.length; _i2 < _ii; _i2 += 2) {
+            dict[xref.fetchIfRef(entries[_i2])] = xref.fetchIfRef(entries[_i2 + 1]);
+          }
+        }
+      }
+
+      return dict;
+    }
+  }, {
+    key: "get",
+    value: function get(key) {
+      if (!this.root) {
+        return null;
+      }
+
+      var xref = this.xref;
+      var kidsOrEntries = xref.fetchIfRef(this.root);
+      var loopCount = 0;
+      var MAX_LEVELS = 10;
+
+      while (kidsOrEntries.has('Kids')) {
+        if (++loopCount > MAX_LEVELS) {
+          (0, _util.warn)("Search depth limit reached for \"".concat(this._type, "\" tree."));
+          return null;
+        }
+
+        var kids = kidsOrEntries.get('Kids');
+
+        if (!Array.isArray(kids)) {
+          return null;
+        }
+
+        var l = 0,
+            r = kids.length - 1;
+
+        while (l <= r) {
+          var m = l + r >> 1;
+          var kid = xref.fetchIfRef(kids[m]);
+          var limits = kid.get('Limits');
+
+          if (key < xref.fetchIfRef(limits[0])) {
+            r = m - 1;
+          } else if (key > xref.fetchIfRef(limits[1])) {
+            l = m + 1;
+          } else {
+            kidsOrEntries = xref.fetchIfRef(kids[m]);
+            break;
+          }
+        }
+
+        if (l > r) {
+          return null;
+        }
+      }
+
+      var entries = kidsOrEntries.get(this._type);
+
+      if (Array.isArray(entries)) {
+        var _l = 0,
+            _r = entries.length - 2;
+
+        while (_l <= _r) {
+          var tmp = _l + _r >> 1,
+              _m = tmp + (tmp & 1);
+
+          var currentKey = xref.fetchIfRef(entries[_m]);
+
+          if (key < currentKey) {
+            _r = _m - 2;
+          } else if (key > currentKey) {
+            _l = _m + 2;
+          } else {
+            return xref.fetchIfRef(entries[_m + 1]);
+          }
+        }
+
+        (0, _util.info)("Falling back to an exhaustive search, for key \"".concat(key, "\", ") + "in \"".concat(this._type, "\" tree."));
+
+        for (var _m2 = 0, mm = entries.length; _m2 < mm; _m2 += 2) {
+          var _currentKey = xref.fetchIfRef(entries[_m2]);
+
+          if (_currentKey === key) {
+            (0, _util.warn)("The \"".concat(key, "\" key was found at an incorrect, ") + "i.e. out-of-order, position in \"".concat(this._type, "\" tree."));
+            return xref.fetchIfRef(entries[_m2 + 1]);
+          }
+        }
+      }
+
+      return null;
+    }
+  }]);
+
+  return NameOrNumberTree;
+}();
+
+var NameTree =
+/*#__PURE__*/
+function (_NameOrNumberTree) {
+  _inherits(NameTree, _NameOrNumberTree);
+
+  function NameTree(root, xref) {
+    _classCallCheck(this, NameTree);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(NameTree).call(this, root, xref, 'Names'));
+  }
+
+  return NameTree;
+}(NameOrNumberTree);
+
+var NumberTree =
+/*#__PURE__*/
+function (_NameOrNumberTree2) {
+  _inherits(NumberTree, _NameOrNumberTree2);
+
+  function NumberTree(root, xref) {
+    _classCallCheck(this, NumberTree);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(NumberTree).call(this, root, xref, 'Nums'));
+  }
+
+  return NumberTree;
+}(NameOrNumberTree);
+
+var FileSpec = function FileSpecClosure() {
+  function FileSpec(root, xref) {
+    if (!root || !(0, _primitives.isDict)(root)) {
+      return;
+    }
+
+    this.xref = xref;
+    this.root = root;
+
+    if (root.has('FS')) {
+      this.fs = root.get('FS');
+    }
+
+    this.description = root.has('Desc') ? (0, _util.stringToPDFString)(root.get('Desc')) : '';
+
+    if (root.has('RF')) {
+      (0, _util.warn)('Related file specifications are not supported');
+    }
+
+    this.contentAvailable = true;
+
+    if (!root.has('EF')) {
+      this.contentAvailable = false;
+      (0, _util.warn)('Non-embedded file specifications are not supported');
+    }
+  }
+
+  function pickPlatformItem(dict) {
+    if (dict.has('UF')) {
+      return dict.get('UF');
+    } else if (dict.has('F')) {
+      return dict.get('F');
+    } else if (dict.has('Unix')) {
+      return dict.get('Unix');
+    } else if (dict.has('Mac')) {
+      return dict.get('Mac');
+    } else if (dict.has('DOS')) {
+      return dict.get('DOS');
+    }
+
+    return null;
+  }
+
+  FileSpec.prototype = {
+    get filename() {
+      if (!this._filename && this.root) {
+        var filename = pickPlatformItem(this.root) || 'unnamed';
+        this._filename = (0, _util.stringToPDFString)(filename).replace(/\\\\/g, '\\').replace(/\\\//g, '/').replace(/\\/g, '/');
+      }
+
+      return this._filename;
+    },
+
+    get content() {
+      if (!this.contentAvailable) {
+        return null;
+      }
+
+      if (!this.contentRef && this.root) {
+        this.contentRef = pickPlatformItem(this.root.get('EF'));
+      }
+
+      var content = null;
+
+      if (this.contentRef) {
+        var xref = this.xref;
+        var fileObj = xref.fetchIfRef(this.contentRef);
+
+        if (fileObj && (0, _primitives.isStream)(fileObj)) {
+          content = fileObj.getBytes();
+        } else {
+          (0, _util.warn)('Embedded file specification points to non-existing/invalid ' + 'content');
+        }
+      } else {
+        (0, _util.warn)('Embedded file specification does not have a content');
+      }
+
+      return content;
+    },
+
+    get serializable() {
+      return {
+        filename: this.filename,
+        content: this.content
+      };
+    }
+
+  };
+  return FileSpec;
+}();
+
+exports.FileSpec = FileSpec;
+
+var ObjectLoader = function () {
+  function mayHaveChildren(value) {
+    return (0, _primitives.isRef)(value) || (0, _primitives.isDict)(value) || Array.isArray(value) || (0, _primitives.isStream)(value);
+  }
+
+  function addChildren(node, nodesToVisit) {
+    if ((0, _primitives.isDict)(node) || (0, _primitives.isStream)(node)) {
+      var dict = (0, _primitives.isDict)(node) ? node : node.dict;
+      var dictKeys = dict.getKeys();
+
+      for (var i = 0, ii = dictKeys.length; i < ii; i++) {
+        var rawValue = dict.getRaw(dictKeys[i]);
+
+        if (mayHaveChildren(rawValue)) {
+          nodesToVisit.push(rawValue);
+        }
+      }
+    } else if (Array.isArray(node)) {
+      for (var _i3 = 0, _ii2 = node.length; _i3 < _ii2; _i3++) {
+        var value = node[_i3];
+
+        if (mayHaveChildren(value)) {
+          nodesToVisit.push(value);
+        }
+      }
+    }
+  }
+
+  function ObjectLoader(dict, keys, xref) {
+    this.dict = dict;
+    this.keys = keys;
+    this.xref = xref;
+    this.refSet = null;
+    this.capability = null;
+  }
+
+  ObjectLoader.prototype = {
+    load: function load() {
+      this.capability = (0, _util.createPromiseCapability)();
+
+      if (!(this.xref.stream instanceof _chunked_stream.ChunkedStream) || this.xref.stream.getMissingChunks().length === 0) {
+        this.capability.resolve();
+        return this.capability.promise;
+      }
+
+      var keys = this.keys,
+          dict = this.dict;
+      this.refSet = new _primitives.RefSet();
+      var nodesToVisit = [];
+
+      for (var i = 0, ii = keys.length; i < ii; i++) {
+        var rawValue = dict.getRaw(keys[i]);
+
+        if (rawValue !== undefined) {
+          nodesToVisit.push(rawValue);
+        }
+      }
+
+      this._walk(nodesToVisit);
+
+      return this.capability.promise;
+    },
+    _walk: function _walk(nodesToVisit) {
+      var _this3 = this;
+
+      var nodesToRevisit = [];
+      var pendingRequests = [];
+
+      while (nodesToVisit.length) {
+        var currentNode = nodesToVisit.pop();
+
+        if ((0, _primitives.isRef)(currentNode)) {
+          if (this.refSet.has(currentNode)) {
+            continue;
+          }
+
+          try {
+            this.refSet.put(currentNode);
+            currentNode = this.xref.fetch(currentNode);
+          } catch (ex) {
+            if (!(ex instanceof _core_utils.MissingDataException)) {
+              throw ex;
+            }
+
+            nodesToRevisit.push(currentNode);
+            pendingRequests.push({
+              begin: ex.begin,
+              end: ex.end
+            });
+          }
+        }
+
+        if (currentNode && currentNode.getBaseStreams) {
+          var baseStreams = currentNode.getBaseStreams();
+          var foundMissingData = false;
+
+          for (var i = 0, ii = baseStreams.length; i < ii; i++) {
+            var stream = baseStreams[i];
+
+            if (stream.getMissingChunks && stream.getMissingChunks().length) {
+              foundMissingData = true;
+              pendingRequests.push({
+                begin: stream.start,
+                end: stream.end
+              });
+            }
+          }
+
+          if (foundMissingData) {
+            nodesToRevisit.push(currentNode);
+          }
+        }
+
+        addChildren(currentNode, nodesToVisit);
+      }
+
+      if (pendingRequests.length) {
+        this.xref.stream.manager.requestRanges(pendingRequests).then(function () {
+          for (var _i4 = 0, _ii3 = nodesToRevisit.length; _i4 < _ii3; _i4++) {
+            var node = nodesToRevisit[_i4];
+
+            if ((0, _primitives.isRef)(node)) {
+              _this3.refSet.remove(node);
+            }
+          }
+
+          _this3._walk(nodesToRevisit);
+        }, this.capability.reject);
+        return;
+      }
+
+      this.refSet = null;
+      this.capability.resolve();
+    }
+  };
+  return ObjectLoader;
+}();
+
+exports.ObjectLoader = ObjectLoader;
+
+/***/ }),
+/* 157 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Parser = exports.Linearization = exports.Lexer = void 0;
+
+var _stream = __w_pdfjs_require__(158);
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _ccitt_stream = __w_pdfjs_require__(159);
+
+var _jbig2_stream = __w_pdfjs_require__(161);
+
+var _jpeg_stream = __w_pdfjs_require__(164);
+
+var _jpx_stream = __w_pdfjs_require__(166);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var MAX_LENGTH_TO_CACHE = 1000;
+var MAX_ADLER32_LENGTH = 5552;
+
+function computeAdler32(bytes) {
+  var bytesLength = bytes.length;
+  var a = 1,
+      b = 0;
+
+  for (var i = 0; i < bytesLength; ++i) {
+    a += bytes[i] & 0xFF;
+    b += a;
+  }
+
+  return b % 65521 << 16 | a % 65521;
+}
+
+var Parser =
+/*#__PURE__*/
+function () {
+  function Parser(_ref) {
+    var lexer = _ref.lexer,
+        xref = _ref.xref,
+        _ref$allowStreams = _ref.allowStreams,
+        allowStreams = _ref$allowStreams === void 0 ? false : _ref$allowStreams,
+        _ref$recoveryMode = _ref.recoveryMode,
+        recoveryMode = _ref$recoveryMode === void 0 ? false : _ref$recoveryMode;
+
+    _classCallCheck(this, Parser);
+
+    this.lexer = lexer;
+    this.xref = xref;
+    this.allowStreams = allowStreams;
+    this.recoveryMode = recoveryMode;
+    this.imageCache = Object.create(null);
+    this.refill();
+  }
+
+  _createClass(Parser, [{
+    key: "refill",
+    value: function refill() {
+      this.buf1 = this.lexer.getObj();
+      this.buf2 = this.lexer.getObj();
+    }
+  }, {
+    key: "shift",
+    value: function shift() {
+      if ((0, _primitives.isCmd)(this.buf2, 'ID')) {
+        this.buf1 = this.buf2;
+        this.buf2 = null;
+      } else {
+        this.buf1 = this.buf2;
+        this.buf2 = this.lexer.getObj();
+      }
+    }
+  }, {
+    key: "tryShift",
+    value: function tryShift() {
+      try {
+        this.shift();
+        return true;
+      } catch (e) {
+        if (e instanceof _core_utils.MissingDataException) {
+          throw e;
+        }
+
+        return false;
+      }
+    }
+  }, {
+    key: "getObj",
+    value: function getObj(cipherTransform) {
+      var buf1 = this.buf1;
+      this.shift();
+
+      if (buf1 instanceof _primitives.Cmd) {
+        switch (buf1.cmd) {
+          case 'BI':
+            return this.makeInlineImage(cipherTransform);
+
+          case '[':
+            var array = [];
+
+            while (!(0, _primitives.isCmd)(this.buf1, ']') && !(0, _primitives.isEOF)(this.buf1)) {
+              array.push(this.getObj(cipherTransform));
+            }
+
+            if ((0, _primitives.isEOF)(this.buf1)) {
+              if (!this.recoveryMode) {
+                throw new _util.FormatError('End of file inside array');
+              }
+
+              return array;
+            }
+
+            this.shift();
+            return array;
+
+          case '<<':
+            var dict = new _primitives.Dict(this.xref);
+
+            while (!(0, _primitives.isCmd)(this.buf1, '>>') && !(0, _primitives.isEOF)(this.buf1)) {
+              if (!(0, _primitives.isName)(this.buf1)) {
+                (0, _util.info)('Malformed dictionary: key must be a name object');
+                this.shift();
+                continue;
+              }
+
+              var key = this.buf1.name;
+              this.shift();
+
+              if ((0, _primitives.isEOF)(this.buf1)) {
+                break;
+              }
+
+              dict.set(key, this.getObj(cipherTransform));
+            }
+
+            if ((0, _primitives.isEOF)(this.buf1)) {
+              if (!this.recoveryMode) {
+                throw new _util.FormatError('End of file inside dictionary');
+              }
+
+              return dict;
+            }
+
+            if ((0, _primitives.isCmd)(this.buf2, 'stream')) {
+              return this.allowStreams ? this.makeStream(dict, cipherTransform) : dict;
+            }
+
+            this.shift();
+            return dict;
+
+          default:
+            return buf1;
+        }
+      }
+
+      if (Number.isInteger(buf1)) {
+        var num = buf1;
+
+        if (Number.isInteger(this.buf1) && (0, _primitives.isCmd)(this.buf2, 'R')) {
+          var ref = _primitives.Ref.get(num, this.buf1);
+
+          this.shift();
+          this.shift();
+          return ref;
+        }
+
+        return num;
+      }
+
+      if ((0, _util.isString)(buf1)) {
+        var str = buf1;
+
+        if (cipherTransform) {
+          str = cipherTransform.decryptString(str);
+        }
+
+        return str;
+      }
+
+      return buf1;
+    }
+  }, {
+    key: "findDefaultInlineStreamEnd",
+    value: function findDefaultInlineStreamEnd(stream) {
+      var E = 0x45,
+          I = 0x49,
+          SPACE = 0x20,
+          LF = 0xA,
+          CR = 0xD;
+      var n = 10,
+          NUL = 0x0;
+      var startPos = stream.pos,
+          state = 0,
+          ch,
+          maybeEIPos;
+
+      while ((ch = stream.getByte()) !== -1) {
+        if (state === 0) {
+          state = ch === E ? 1 : 0;
+        } else if (state === 1) {
+          state = ch === I ? 2 : 0;
+        } else {
+          (0, _util.assert)(state === 2);
+
+          if (ch === SPACE || ch === LF || ch === CR) {
+            maybeEIPos = stream.pos;
+            var followingBytes = stream.peekBytes(n);
+
+            for (var i = 0, ii = followingBytes.length; i < ii; i++) {
+              ch = followingBytes[i];
+
+              if (ch === NUL && followingBytes[i + 1] !== NUL) {
+                continue;
+              }
+
+              if (ch !== LF && ch !== CR && (ch < SPACE || ch > 0x7F)) {
+                state = 0;
+                break;
+              }
+            }
+
+            if (state === 2) {
+              break;
+            }
+          } else {
+            state = 0;
+          }
+        }
+      }
+
+      if (ch === -1) {
+        (0, _util.warn)('findDefaultInlineStreamEnd: ' + 'Reached the end of the stream without finding a valid EI marker');
+
+        if (maybeEIPos) {
+          (0, _util.warn)('... trying to recover by using the last "EI" occurrence.');
+          stream.skip(-(stream.pos - maybeEIPos));
+        }
+      }
+
+      var endOffset = 4;
+      stream.skip(-endOffset);
+      ch = stream.peekByte();
+      stream.skip(endOffset);
+
+      if (!(0, _util.isSpace)(ch)) {
+        endOffset--;
+      }
+
+      return stream.pos - endOffset - startPos;
+    }
+  }, {
+    key: "findDCTDecodeInlineStreamEnd",
+    value: function findDCTDecodeInlineStreamEnd(stream) {
+      var startPos = stream.pos,
+          foundEOI = false,
+          b,
+          markerLength,
+          length;
+
+      while ((b = stream.getByte()) !== -1) {
+        if (b !== 0xFF) {
+          continue;
+        }
+
+        switch (stream.getByte()) {
+          case 0x00:
+            break;
+
+          case 0xFF:
+            stream.skip(-1);
+            break;
+
+          case 0xD9:
+            foundEOI = true;
+            break;
+
+          case 0xC0:
+          case 0xC1:
+          case 0xC2:
+          case 0xC3:
+          case 0xC5:
+          case 0xC6:
+          case 0xC7:
+          case 0xC9:
+          case 0xCA:
+          case 0xCB:
+          case 0xCD:
+          case 0xCE:
+          case 0xCF:
+          case 0xC4:
+          case 0xCC:
+          case 0xDA:
+          case 0xDB:
+          case 0xDC:
+          case 0xDD:
+          case 0xDE:
+          case 0xDF:
+          case 0xE0:
+          case 0xE1:
+          case 0xE2:
+          case 0xE3:
+          case 0xE4:
+          case 0xE5:
+          case 0xE6:
+          case 0xE7:
+          case 0xE8:
+          case 0xE9:
+          case 0xEA:
+          case 0xEB:
+          case 0xEC:
+          case 0xED:
+          case 0xEE:
+          case 0xEF:
+          case 0xFE:
+            markerLength = stream.getUint16();
+
+            if (markerLength > 2) {
+              stream.skip(markerLength - 2);
+            } else {
+              stream.skip(-2);
+            }
+
+            break;
+        }
+
+        if (foundEOI) {
+          break;
+        }
+      }
+
+      length = stream.pos - startPos;
+
+      if (b === -1) {
+        (0, _util.warn)('Inline DCTDecode image stream: ' + 'EOI marker not found, searching for /EI/ instead.');
+        stream.skip(-length);
+        return this.findDefaultInlineStreamEnd(stream);
+      }
+
+      this.inlineStreamSkipEI(stream);
+      return length;
+    }
+  }, {
+    key: "findASCII85DecodeInlineStreamEnd",
+    value: function findASCII85DecodeInlineStreamEnd(stream) {
+      var TILDE = 0x7E,
+          GT = 0x3E;
+      var startPos = stream.pos,
+          ch,
+          length;
+
+      while ((ch = stream.getByte()) !== -1) {
+        if (ch === TILDE) {
+          ch = stream.peekByte();
+
+          while ((0, _util.isSpace)(ch)) {
+            stream.skip();
+            ch = stream.peekByte();
+          }
+
+          if (ch === GT) {
+            stream.skip();
+            break;
+          }
+        }
+      }
+
+      length = stream.pos - startPos;
+
+      if (ch === -1) {
+        (0, _util.warn)('Inline ASCII85Decode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
+        stream.skip(-length);
+        return this.findDefaultInlineStreamEnd(stream);
+      }
+
+      this.inlineStreamSkipEI(stream);
+      return length;
+    }
+  }, {
+    key: "findASCIIHexDecodeInlineStreamEnd",
+    value: function findASCIIHexDecodeInlineStreamEnd(stream) {
+      var GT = 0x3E;
+      var startPos = stream.pos,
+          ch,
+          length;
+
+      while ((ch = stream.getByte()) !== -1) {
+        if (ch === GT) {
+          break;
+        }
+      }
+
+      length = stream.pos - startPos;
+
+      if (ch === -1) {
+        (0, _util.warn)('Inline ASCIIHexDecode image stream: ' + 'EOD marker not found, searching for /EI/ instead.');
+        stream.skip(-length);
+        return this.findDefaultInlineStreamEnd(stream);
+      }
+
+      this.inlineStreamSkipEI(stream);
+      return length;
+    }
+  }, {
+    key: "inlineStreamSkipEI",
+    value: function inlineStreamSkipEI(stream) {
+      var E = 0x45,
+          I = 0x49;
+      var state = 0,
+          ch;
+
+      while ((ch = stream.getByte()) !== -1) {
+        if (state === 0) {
+          state = ch === E ? 1 : 0;
+        } else if (state === 1) {
+          state = ch === I ? 2 : 0;
+        } else if (state === 2) {
+          break;
+        }
+      }
+    }
+  }, {
+    key: "makeInlineImage",
+    value: function makeInlineImage(cipherTransform) {
+      var lexer = this.lexer;
+      var stream = lexer.stream;
+      var dict = new _primitives.Dict(this.xref);
+      var dictLength;
+
+      while (!(0, _primitives.isCmd)(this.buf1, 'ID') && !(0, _primitives.isEOF)(this.buf1)) {
+        if (!(0, _primitives.isName)(this.buf1)) {
+          throw new _util.FormatError('Dictionary key must be a name object');
+        }
+
+        var key = this.buf1.name;
+        this.shift();
+
+        if ((0, _primitives.isEOF)(this.buf1)) {
+          break;
+        }
+
+        dict.set(key, this.getObj(cipherTransform));
+      }
+
+      if (lexer.beginInlineImagePos !== -1) {
+        dictLength = stream.pos - lexer.beginInlineImagePos;
+      }
+
+      var filter = dict.get('Filter', 'F');
+      var filterName;
+
+      if ((0, _primitives.isName)(filter)) {
+        filterName = filter.name;
+      } else if (Array.isArray(filter)) {
+        var filterZero = this.xref.fetchIfRef(filter[0]);
+
+        if ((0, _primitives.isName)(filterZero)) {
+          filterName = filterZero.name;
+        }
+      }
+
+      var startPos = stream.pos;
+      var length;
+
+      if (filterName === 'DCTDecode' || filterName === 'DCT') {
+        length = this.findDCTDecodeInlineStreamEnd(stream);
+      } else if (filterName === 'ASCII85Decode' || filterName === 'A85') {
+        length = this.findASCII85DecodeInlineStreamEnd(stream);
+      } else if (filterName === 'ASCIIHexDecode' || filterName === 'AHx') {
+        length = this.findASCIIHexDecodeInlineStreamEnd(stream);
+      } else {
+        length = this.findDefaultInlineStreamEnd(stream);
+      }
+
+      var imageStream = stream.makeSubStream(startPos, length, dict);
+      var cacheKey;
+
+      if (length < MAX_LENGTH_TO_CACHE && dictLength < MAX_ADLER32_LENGTH) {
+        var imageBytes = imageStream.getBytes();
+        imageStream.reset();
+        var initialStreamPos = stream.pos;
+        stream.pos = lexer.beginInlineImagePos;
+        var dictBytes = stream.getBytes(dictLength);
+        stream.pos = initialStreamPos;
+        cacheKey = computeAdler32(imageBytes) + '_' + computeAdler32(dictBytes);
+        var cacheEntry = this.imageCache[cacheKey];
+
+        if (cacheEntry !== undefined) {
+          this.buf2 = _primitives.Cmd.get('EI');
+          this.shift();
+          cacheEntry.reset();
+          return cacheEntry;
+        }
+      }
+
+      if (cipherTransform) {
+        imageStream = cipherTransform.createStream(imageStream, length);
+      }
+
+      imageStream = this.filter(imageStream, dict, length);
+      imageStream.dict = dict;
+
+      if (cacheKey !== undefined) {
+        imageStream.cacheKey = "inline_".concat(length, "_").concat(cacheKey);
+        this.imageCache[cacheKey] = imageStream;
+      }
+
+      this.buf2 = _primitives.Cmd.get('EI');
+      this.shift();
+      return imageStream;
+    }
+  }, {
+    key: "_findStreamLength",
+    value: function _findStreamLength(startPos, signature) {
+      var stream = this.lexer.stream;
+      stream.pos = startPos;
+      var SCAN_BLOCK_LENGTH = 2048;
+      var signatureLength = signature.length;
+
+      while (stream.pos < stream.end) {
+        var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
+        var scanLength = scanBytes.length - signatureLength;
+
+        if (scanLength <= 0) {
+          break;
+        }
+
+        var pos = 0;
+
+        while (pos < scanLength) {
+          var j = 0;
+
+          while (j < signatureLength && scanBytes[pos + j] === signature[j]) {
+            j++;
+          }
+
+          if (j >= signatureLength) {
+            stream.pos += pos;
+            return stream.pos - startPos;
+          }
+
+          pos++;
+        }
+
+        stream.pos += scanLength;
+      }
+
+      return -1;
+    }
+  }, {
+    key: "makeStream",
+    value: function makeStream(dict, cipherTransform) {
+      var lexer = this.lexer;
+      var stream = lexer.stream;
+      lexer.skipToNextLine();
+      var startPos = stream.pos - 1;
+      var length = dict.get('Length');
+
+      if (!Number.isInteger(length)) {
+        (0, _util.info)("Bad length \"".concat(length, "\" in stream"));
+        length = 0;
+      }
+
+      stream.pos = startPos + length;
+      lexer.nextChar();
+
+      if (this.tryShift() && (0, _primitives.isCmd)(this.buf2, 'endstream')) {
+        this.shift();
+      } else {
+        var ENDSTREAM_SIGNATURE = new Uint8Array([0x65, 0x6E, 0x64, 0x73, 0x74, 0x72, 0x65, 0x61, 0x6D]);
+
+        var actualLength = this._findStreamLength(startPos, ENDSTREAM_SIGNATURE);
+
+        if (actualLength < 0) {
+          var MAX_TRUNCATION = 1;
+
+          for (var i = 1; i <= MAX_TRUNCATION; i++) {
+            var end = ENDSTREAM_SIGNATURE.length - i;
+            var TRUNCATED_SIGNATURE = ENDSTREAM_SIGNATURE.slice(0, end);
+
+            var maybeLength = this._findStreamLength(startPos, TRUNCATED_SIGNATURE);
+
+            if (maybeLength >= 0) {
+              var lastByte = stream.peekBytes(end + 1)[end];
+
+              if (!(0, _util.isSpace)(lastByte)) {
+                break;
+              }
+
+              (0, _util.info)("Found \"".concat((0, _util.bytesToString)(TRUNCATED_SIGNATURE), "\" when ") + 'searching for endstream command.');
+              actualLength = maybeLength;
+              break;
+            }
+          }
+
+          if (actualLength < 0) {
+            throw new _util.FormatError('Missing endstream command.');
+          }
+        }
+
+        length = actualLength;
+        lexer.nextChar();
+        this.shift();
+        this.shift();
+      }
+
+      this.shift();
+      stream = stream.makeSubStream(startPos, length, dict);
+
+      if (cipherTransform) {
+        stream = cipherTransform.createStream(stream, length);
+      }
+
+      stream = this.filter(stream, dict, length);
+      stream.dict = dict;
+      return stream;
+    }
+  }, {
+    key: "filter",
+    value: function filter(stream, dict, length) {
+      var filter = dict.get('Filter', 'F');
+      var params = dict.get('DecodeParms', 'DP');
+
+      if ((0, _primitives.isName)(filter)) {
+        if (Array.isArray(params)) {
+          (0, _util.warn)('/DecodeParms should not contain an Array, ' + 'when /Filter contains a Name.');
+        }
+
+        return this.makeFilter(stream, filter.name, length, params);
+      }
+
+      var maybeLength = length;
+
+      if (Array.isArray(filter)) {
+        var filterArray = filter;
+        var paramsArray = params;
+
+        for (var i = 0, ii = filterArray.length; i < ii; ++i) {
+          filter = this.xref.fetchIfRef(filterArray[i]);
+
+          if (!(0, _primitives.isName)(filter)) {
+            throw new _util.FormatError("Bad filter name \"".concat(filter, "\""));
+          }
+
+          params = null;
+
+          if (Array.isArray(paramsArray) && i in paramsArray) {
+            params = this.xref.fetchIfRef(paramsArray[i]);
+          }
+
+          stream = this.makeFilter(stream, filter.name, maybeLength, params);
+          maybeLength = null;
+        }
+      }
+
+      return stream;
+    }
+  }, {
+    key: "makeFilter",
+    value: function makeFilter(stream, name, maybeLength, params) {
+      if (maybeLength === 0) {
+        (0, _util.warn)("Empty \"".concat(name, "\" stream."));
+        return new _stream.NullStream();
+      }
+
+      try {
+        var xrefStreamStats = this.xref.stats.streamTypes;
+
+        if (name === 'FlateDecode' || name === 'Fl') {
+          xrefStreamStats[_util.StreamType.FLATE] = true;
+
+          if (params) {
+            return new _stream.PredictorStream(new _stream.FlateStream(stream, maybeLength), maybeLength, params);
+          }
+
+          return new _stream.FlateStream(stream, maybeLength);
+        }
+
+        if (name === 'LZWDecode' || name === 'LZW') {
+          xrefStreamStats[_util.StreamType.LZW] = true;
+          var earlyChange = 1;
+
+          if (params) {
+            if (params.has('EarlyChange')) {
+              earlyChange = params.get('EarlyChange');
+            }
+
+            return new _stream.PredictorStream(new _stream.LZWStream(stream, maybeLength, earlyChange), maybeLength, params);
+          }
+
+          return new _stream.LZWStream(stream, maybeLength, earlyChange);
+        }
+
+        if (name === 'DCTDecode' || name === 'DCT') {
+          xrefStreamStats[_util.StreamType.DCT] = true;
+          return new _jpeg_stream.JpegStream(stream, maybeLength, stream.dict, params);
+        }
+
+        if (name === 'JPXDecode' || name === 'JPX') {
+          xrefStreamStats[_util.StreamType.JPX] = true;
+          return new _jpx_stream.JpxStream(stream, maybeLength, stream.dict, params);
+        }
+
+        if (name === 'ASCII85Decode' || name === 'A85') {
+          xrefStreamStats[_util.StreamType.A85] = true;
+          return new _stream.Ascii85Stream(stream, maybeLength);
+        }
+
+        if (name === 'ASCIIHexDecode' || name === 'AHx') {
+          xrefStreamStats[_util.StreamType.AHX] = true;
+          return new _stream.AsciiHexStream(stream, maybeLength);
+        }
+
+        if (name === 'CCITTFaxDecode' || name === 'CCF') {
+          xrefStreamStats[_util.StreamType.CCF] = true;
+          return new _ccitt_stream.CCITTFaxStream(stream, maybeLength, params);
+        }
+
+        if (name === 'RunLengthDecode' || name === 'RL') {
+          xrefStreamStats[_util.StreamType.RL] = true;
+          return new _stream.RunLengthStream(stream, maybeLength);
+        }
+
+        if (name === 'JBIG2Decode') {
+          xrefStreamStats[_util.StreamType.JBIG] = true;
+          return new _jbig2_stream.Jbig2Stream(stream, maybeLength, stream.dict, params);
+        }
+
+        (0, _util.warn)("Filter \"".concat(name, "\" is not supported."));
+        return stream;
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)("Invalid stream: \"".concat(ex, "\""));
+        return new _stream.NullStream();
+      }
+    }
+  }]);
+
+  return Parser;
+}();
+
+exports.Parser = Parser;
+var specialChars = [1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 2, 0, 0, 2, 2, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
+
+function toHexDigit(ch) {
+  if (ch >= 0x30 && ch <= 0x39) {
+    return ch & 0x0F;
+  }
+
+  if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
+    return (ch & 0x0F) + 9;
+  }
+
+  return -1;
+}
+
+var Lexer =
+/*#__PURE__*/
+function () {
+  function Lexer(stream) {
+    var knownCommands = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
+
+    _classCallCheck(this, Lexer);
+
+    this.stream = stream;
+    this.nextChar();
+    this.strBuf = [];
+    this.knownCommands = knownCommands;
+    this.beginInlineImagePos = -1;
+  }
+
+  _createClass(Lexer, [{
+    key: "nextChar",
+    value: function nextChar() {
+      return this.currentChar = this.stream.getByte();
+    }
+  }, {
+    key: "peekChar",
+    value: function peekChar() {
+      return this.stream.peekByte();
+    }
+  }, {
+    key: "getNumber",
+    value: function getNumber() {
+      var ch = this.currentChar;
+      var eNotation = false;
+      var divideBy = 0;
+      var sign = 0;
+
+      if (ch === 0x2D) {
+        sign = -1;
+        ch = this.nextChar();
+
+        if (ch === 0x2D) {
+          ch = this.nextChar();
+        }
+      } else if (ch === 0x2B) {
+        sign = 1;
+        ch = this.nextChar();
+      }
+
+      if (ch === 0x0A || ch === 0x0D) {
+        do {
+          ch = this.nextChar();
+        } while (ch === 0x0A || ch === 0x0D);
+      }
+
+      if (ch === 0x2E) {
+        divideBy = 10;
+        ch = this.nextChar();
+      }
+
+      if (ch < 0x30 || ch > 0x39) {
+        if (divideBy === 10 && sign === 0 && ((0, _util.isSpace)(ch) || ch === -1)) {
+          (0, _util.warn)('Lexer.getNumber - treating a single decimal point as zero.');
+          return 0;
+        }
+
+        throw new _util.FormatError("Invalid number: ".concat(String.fromCharCode(ch), " (charCode ").concat(ch, ")"));
+      }
+
+      sign = sign || 1;
+      var baseValue = ch - 0x30;
+      var powerValue = 0;
+      var powerValueSign = 1;
+
+      while ((ch = this.nextChar()) >= 0) {
+        if (0x30 <= ch && ch <= 0x39) {
+          var currentDigit = ch - 0x30;
+
+          if (eNotation) {
+            powerValue = powerValue * 10 + currentDigit;
+          } else {
+            if (divideBy !== 0) {
+              divideBy *= 10;
+            }
+
+            baseValue = baseValue * 10 + currentDigit;
+          }
+        } else if (ch === 0x2E) {
+          if (divideBy === 0) {
+            divideBy = 1;
+          } else {
+            break;
+          }
+        } else if (ch === 0x2D) {
+          (0, _util.warn)('Badly formatted number: minus sign in the middle');
+        } else if (ch === 0x45 || ch === 0x65) {
+          ch = this.peekChar();
+
+          if (ch === 0x2B || ch === 0x2D) {
+            powerValueSign = ch === 0x2D ? -1 : 1;
+            this.nextChar();
+          } else if (ch < 0x30 || ch > 0x39) {
+            break;
+          }
+
+          eNotation = true;
+        } else {
+          break;
+        }
+      }
+
+      if (divideBy !== 0) {
+        baseValue /= divideBy;
+      }
+
+      if (eNotation) {
+        baseValue *= Math.pow(10, powerValueSign * powerValue);
+      }
+
+      return sign * baseValue;
+    }
+  }, {
+    key: "getString",
+    value: function getString() {
+      var numParen = 1;
+      var done = false;
+      var strBuf = this.strBuf;
+      strBuf.length = 0;
+      var ch = this.nextChar();
+
+      while (true) {
+        var charBuffered = false;
+
+        switch (ch | 0) {
+          case -1:
+            (0, _util.warn)('Unterminated string');
+            done = true;
+            break;
+
+          case 0x28:
+            ++numParen;
+            strBuf.push('(');
+            break;
+
+          case 0x29:
+            if (--numParen === 0) {
+              this.nextChar();
+              done = true;
+            } else {
+              strBuf.push(')');
+            }
+
+            break;
+
+          case 0x5C:
+            ch = this.nextChar();
+
+            switch (ch) {
+              case -1:
+                (0, _util.warn)('Unterminated string');
+                done = true;
+                break;
+
+              case 0x6E:
+                strBuf.push('\n');
+                break;
+
+              case 0x72:
+                strBuf.push('\r');
+                break;
+
+              case 0x74:
+                strBuf.push('\t');
+                break;
+
+              case 0x62:
+                strBuf.push('\b');
+                break;
+
+              case 0x66:
+                strBuf.push('\f');
+                break;
+
+              case 0x5C:
+              case 0x28:
+              case 0x29:
+                strBuf.push(String.fromCharCode(ch));
+                break;
+
+              case 0x30:
+              case 0x31:
+              case 0x32:
+              case 0x33:
+              case 0x34:
+              case 0x35:
+              case 0x36:
+              case 0x37:
+                var x = ch & 0x0F;
+                ch = this.nextChar();
+                charBuffered = true;
+
+                if (ch >= 0x30 && ch <= 0x37) {
+                  x = (x << 3) + (ch & 0x0F);
+                  ch = this.nextChar();
+
+                  if (ch >= 0x30 && ch <= 0x37) {
+                    charBuffered = false;
+                    x = (x << 3) + (ch & 0x0F);
+                  }
+                }
+
+                strBuf.push(String.fromCharCode(x));
+                break;
+
+              case 0x0D:
+                if (this.peekChar() === 0x0A) {
+                  this.nextChar();
+                }
+
+                break;
+
+              case 0x0A:
+                break;
+
+              default:
+                strBuf.push(String.fromCharCode(ch));
+                break;
+            }
+
+            break;
+
+          default:
+            strBuf.push(String.fromCharCode(ch));
+            break;
+        }
+
+        if (done) {
+          break;
+        }
+
+        if (!charBuffered) {
+          ch = this.nextChar();
+        }
+      }
+
+      return strBuf.join('');
+    }
+  }, {
+    key: "getName",
+    value: function getName() {
+      var ch, previousCh;
+      var strBuf = this.strBuf;
+      strBuf.length = 0;
+
+      while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
+        if (ch === 0x23) {
+          ch = this.nextChar();
+
+          if (specialChars[ch]) {
+            (0, _util.warn)('Lexer_getName: ' + 'NUMBER SIGN (#) should be followed by a hexadecimal number.');
+            strBuf.push('#');
+            break;
+          }
+
+          var x = toHexDigit(ch);
+
+          if (x !== -1) {
+            previousCh = ch;
+            ch = this.nextChar();
+            var x2 = toHexDigit(ch);
+
+            if (x2 === -1) {
+              (0, _util.warn)("Lexer_getName: Illegal digit (".concat(String.fromCharCode(ch), ") ") + 'in hexadecimal number.');
+              strBuf.push('#', String.fromCharCode(previousCh));
+
+              if (specialChars[ch]) {
+                break;
+              }
+
+              strBuf.push(String.fromCharCode(ch));
+              continue;
+            }
+
+            strBuf.push(String.fromCharCode(x << 4 | x2));
+          } else {
+            strBuf.push('#', String.fromCharCode(ch));
+          }
+        } else {
+          strBuf.push(String.fromCharCode(ch));
+        }
+      }
+
+      if (strBuf.length > 127) {
+        (0, _util.warn)("Name token is longer than allowed by the spec: ".concat(strBuf.length));
+      }
+
+      return _primitives.Name.get(strBuf.join(''));
+    }
+  }, {
+    key: "getHexString",
+    value: function getHexString() {
+      var strBuf = this.strBuf;
+      strBuf.length = 0;
+      var ch = this.currentChar;
+      var isFirstHex = true;
+      var firstDigit, secondDigit;
+
+      while (true) {
+        if (ch < 0) {
+          (0, _util.warn)('Unterminated hex string');
+          break;
+        } else if (ch === 0x3E) {
+          this.nextChar();
+          break;
+        } else if (specialChars[ch] === 1) {
+          ch = this.nextChar();
+          continue;
+        } else {
+          if (isFirstHex) {
+            firstDigit = toHexDigit(ch);
+
+            if (firstDigit === -1) {
+              (0, _util.warn)("Ignoring invalid character \"".concat(ch, "\" in hex string"));
+              ch = this.nextChar();
+              continue;
+            }
+          } else {
+            secondDigit = toHexDigit(ch);
+
+            if (secondDigit === -1) {
+              (0, _util.warn)("Ignoring invalid character \"".concat(ch, "\" in hex string"));
+              ch = this.nextChar();
+              continue;
+            }
+
+            strBuf.push(String.fromCharCode(firstDigit << 4 | secondDigit));
+          }
+
+          isFirstHex = !isFirstHex;
+          ch = this.nextChar();
+        }
+      }
+
+      return strBuf.join('');
+    }
+  }, {
+    key: "getObj",
+    value: function getObj() {
+      var comment = false;
+      var ch = this.currentChar;
+
+      while (true) {
+        if (ch < 0) {
+          return _primitives.EOF;
+        }
+
+        if (comment) {
+          if (ch === 0x0A || ch === 0x0D) {
+            comment = false;
+          }
+        } else if (ch === 0x25) {
+          comment = true;
+        } else if (specialChars[ch] !== 1) {
+          break;
+        }
+
+        ch = this.nextChar();
+      }
+
+      switch (ch | 0) {
+        case 0x30:
+        case 0x31:
+        case 0x32:
+        case 0x33:
+        case 0x34:
+        case 0x35:
+        case 0x36:
+        case 0x37:
+        case 0x38:
+        case 0x39:
+        case 0x2B:
+        case 0x2D:
+        case 0x2E:
+          return this.getNumber();
+
+        case 0x28:
+          return this.getString();
+
+        case 0x2F:
+          return this.getName();
+
+        case 0x5B:
+          this.nextChar();
+          return _primitives.Cmd.get('[');
+
+        case 0x5D:
+          this.nextChar();
+          return _primitives.Cmd.get(']');
+
+        case 0x3C:
+          ch = this.nextChar();
+
+          if (ch === 0x3C) {
+            this.nextChar();
+            return _primitives.Cmd.get('<<');
+          }
+
+          return this.getHexString();
+
+        case 0x3E:
+          ch = this.nextChar();
+
+          if (ch === 0x3E) {
+            this.nextChar();
+            return _primitives.Cmd.get('>>');
+          }
+
+          return _primitives.Cmd.get('>');
+
+        case 0x7B:
+          this.nextChar();
+          return _primitives.Cmd.get('{');
+
+        case 0x7D:
+          this.nextChar();
+          return _primitives.Cmd.get('}');
+
+        case 0x29:
+          this.nextChar();
+          throw new _util.FormatError("Illegal character: ".concat(ch));
+      }
+
+      var str = String.fromCharCode(ch);
+      var knownCommands = this.knownCommands;
+      var knownCommandFound = knownCommands && knownCommands[str] !== undefined;
+
+      while ((ch = this.nextChar()) >= 0 && !specialChars[ch]) {
+        var possibleCommand = str + String.fromCharCode(ch);
+
+        if (knownCommandFound && knownCommands[possibleCommand] === undefined) {
+          break;
+        }
+
+        if (str.length === 128) {
+          throw new _util.FormatError("Command token too long: ".concat(str.length));
+        }
+
+        str = possibleCommand;
+        knownCommandFound = knownCommands && knownCommands[str] !== undefined;
+      }
+
+      if (str === 'true') {
+        return true;
+      }
+
+      if (str === 'false') {
+        return false;
+      }
+
+      if (str === 'null') {
+        return null;
+      }
+
+      if (str === 'BI') {
+        this.beginInlineImagePos = this.stream.pos;
+      }
+
+      return _primitives.Cmd.get(str);
+    }
+  }, {
+    key: "skipToNextLine",
+    value: function skipToNextLine() {
+      var ch = this.currentChar;
+
+      while (ch >= 0) {
+        if (ch === 0x0D) {
+          ch = this.nextChar();
+
+          if (ch === 0x0A) {
+            this.nextChar();
+          }
+
+          break;
+        } else if (ch === 0x0A) {
+          this.nextChar();
+          break;
+        }
+
+        ch = this.nextChar();
+      }
+    }
+  }]);
+
+  return Lexer;
+}();
+
+exports.Lexer = Lexer;
+
+var Linearization =
+/*#__PURE__*/
+function () {
+  function Linearization() {
+    _classCallCheck(this, Linearization);
+  }
+
+  _createClass(Linearization, null, [{
+    key: "create",
+    value: function create(stream) {
+      function getInt(linDict, name) {
+        var allowZeroValue = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+        var obj = linDict.get(name);
+
+        if (Number.isInteger(obj) && (allowZeroValue ? obj >= 0 : obj > 0)) {
+          return obj;
+        }
+
+        throw new Error("The \"".concat(name, "\" parameter in the linearization ") + 'dictionary is invalid.');
+      }
+
+      function getHints(linDict) {
+        var hints = linDict.get('H');
+        var hintsLength;
+
+        if (Array.isArray(hints) && ((hintsLength = hints.length) === 2 || hintsLength === 4)) {
+          for (var index = 0; index < hintsLength; index++) {
+            var hint = hints[index];
+
+            if (!(Number.isInteger(hint) && hint > 0)) {
+              throw new Error("Hint (".concat(index, ") in the linearization dictionary ") + 'is invalid.');
+            }
+          }
+
+          return hints;
+        }
+
+        throw new Error('Hint array in the linearization dictionary is invalid.');
+      }
+
+      var parser = new Parser({
+        lexer: new Lexer(stream),
+        xref: null
+      });
+      var obj1 = parser.getObj();
+      var obj2 = parser.getObj();
+      var obj3 = parser.getObj();
+      var linDict = parser.getObj();
+      var obj, length;
+
+      if (!(Number.isInteger(obj1) && Number.isInteger(obj2) && (0, _primitives.isCmd)(obj3, 'obj') && (0, _primitives.isDict)(linDict) && (0, _util.isNum)(obj = linDict.get('Linearized')) && obj > 0)) {
+        return null;
+      } else if ((length = getInt(linDict, 'L')) !== stream.length) {
+        throw new Error('The "L" parameter in the linearization dictionary ' + 'does not equal the stream length.');
+      }
+
+      return {
+        length: length,
+        hints: getHints(linDict),
+        objectNumberFirst: getInt(linDict, 'O'),
+        endFirst: getInt(linDict, 'E'),
+        numPages: getInt(linDict, 'N'),
+        mainXRefEntriesOffset: getInt(linDict, 'T'),
+        pageFirst: linDict.has('P') ? getInt(linDict, 'P', true) : 0
+      };
+    }
+  }]);
+
+  return Linearization;
+}();
+
+exports.Linearization = Linearization;
+
+/***/ }),
+/* 158 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.LZWStream = exports.StringStream = exports.StreamsSequenceStream = exports.Stream = exports.RunLengthStream = exports.PredictorStream = exports.NullStream = exports.FlateStream = exports.DecodeStream = exports.DecryptStream = exports.AsciiHexStream = exports.Ascii85Stream = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread(); }
+
+function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance"); }
+
+function _iterableToArray(iter) { if (Symbol.iterator in Object(iter) || Object.prototype.toString.call(iter) === "[object Arguments]") return Array.from(iter); }
+
+function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } }
+
+var Stream = function StreamClosure() {
+  function Stream(arrayBuffer, start, length, dict) {
+    this.bytes = arrayBuffer instanceof Uint8Array ? arrayBuffer : new Uint8Array(arrayBuffer);
+    this.start = start || 0;
+    this.pos = this.start;
+    this.end = start + length || this.bytes.length;
+    this.dict = dict;
+  }
+
+  Stream.prototype = {
+    get length() {
+      return this.end - this.start;
+    },
+
+    get isEmpty() {
+      return this.length === 0;
+    },
+
+    getByte: function Stream_getByte() {
+      if (this.pos >= this.end) {
+        return -1;
+      }
+
+      return this.bytes[this.pos++];
+    },
+    getUint16: function Stream_getUint16() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+
+      if (b0 === -1 || b1 === -1) {
+        return -1;
+      }
+
+      return (b0 << 8) + b1;
+    },
+    getInt32: function Stream_getInt32() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+      var b2 = this.getByte();
+      var b3 = this.getByte();
+      return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+    },
+    getBytes: function getBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var bytes = this.bytes;
+      var pos = this.pos;
+      var strEnd = this.end;
+
+      if (!length) {
+        var _subarray = bytes.subarray(pos, strEnd);
+
+        return forceClamped ? new Uint8ClampedArray(_subarray) : _subarray;
+      }
+
+      var end = pos + length;
+
+      if (end > strEnd) {
+        end = strEnd;
+      }
+
+      this.pos = end;
+      var subarray = bytes.subarray(pos, end);
+      return forceClamped ? new Uint8ClampedArray(subarray) : subarray;
+    },
+    peekByte: function Stream_peekByte() {
+      var peekedByte = this.getByte();
+      this.pos--;
+      return peekedByte;
+    },
+    peekBytes: function peekBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var bytes = this.getBytes(length, forceClamped);
+      this.pos -= bytes.length;
+      return bytes;
+    },
+    skip: function Stream_skip(n) {
+      if (!n) {
+        n = 1;
+      }
+
+      this.pos += n;
+    },
+    reset: function Stream_reset() {
+      this.pos = this.start;
+    },
+    moveStart: function Stream_moveStart() {
+      this.start = this.pos;
+    },
+    makeSubStream: function Stream_makeSubStream(start, length, dict) {
+      return new Stream(this.bytes.buffer, start, length, dict);
+    }
+  };
+  return Stream;
+}();
+
+exports.Stream = Stream;
+
+var StringStream = function StringStreamClosure() {
+  function StringStream(str) {
+    var bytes = (0, _util.stringToBytes)(str);
+    Stream.call(this, bytes);
+  }
+
+  StringStream.prototype = Stream.prototype;
+  return StringStream;
+}();
+
+exports.StringStream = StringStream;
+
+var DecodeStream = function DecodeStreamClosure() {
+  var emptyBuffer = new Uint8Array(0);
+
+  function DecodeStream(maybeMinBufferLength) {
+    this._rawMinBufferLength = maybeMinBufferLength || 0;
+    this.pos = 0;
+    this.bufferLength = 0;
+    this.eof = false;
+    this.buffer = emptyBuffer;
+    this.minBufferLength = 512;
+
+    if (maybeMinBufferLength) {
+      while (this.minBufferLength < maybeMinBufferLength) {
+        this.minBufferLength *= 2;
+      }
+    }
+  }
+
+  DecodeStream.prototype = {
+    get isEmpty() {
+      while (!this.eof && this.bufferLength === 0) {
+        this.readBlock();
+      }
+
+      return this.bufferLength === 0;
+    },
+
+    ensureBuffer: function DecodeStream_ensureBuffer(requested) {
+      var buffer = this.buffer;
+
+      if (requested <= buffer.byteLength) {
+        return buffer;
+      }
+
+      var size = this.minBufferLength;
+
+      while (size < requested) {
+        size *= 2;
+      }
+
+      var buffer2 = new Uint8Array(size);
+      buffer2.set(buffer);
+      return this.buffer = buffer2;
+    },
+    getByte: function DecodeStream_getByte() {
+      var pos = this.pos;
+
+      while (this.bufferLength <= pos) {
+        if (this.eof) {
+          return -1;
+        }
+
+        this.readBlock();
+      }
+
+      return this.buffer[this.pos++];
+    },
+    getUint16: function DecodeStream_getUint16() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+
+      if (b0 === -1 || b1 === -1) {
+        return -1;
+      }
+
+      return (b0 << 8) + b1;
+    },
+    getInt32: function DecodeStream_getInt32() {
+      var b0 = this.getByte();
+      var b1 = this.getByte();
+      var b2 = this.getByte();
+      var b3 = this.getByte();
+      return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+    },
+    getBytes: function getBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var end,
+          pos = this.pos;
+
+      if (length) {
+        this.ensureBuffer(pos + length);
+        end = pos + length;
+
+        while (!this.eof && this.bufferLength < end) {
+          this.readBlock();
+        }
+
+        var bufEnd = this.bufferLength;
+
+        if (end > bufEnd) {
+          end = bufEnd;
+        }
+      } else {
+        while (!this.eof) {
+          this.readBlock();
+        }
+
+        end = this.bufferLength;
+      }
+
+      this.pos = end;
+      var subarray = this.buffer.subarray(pos, end);
+      return forceClamped && !(subarray instanceof Uint8ClampedArray) ? new Uint8ClampedArray(subarray) : subarray;
+    },
+    peekByte: function DecodeStream_peekByte() {
+      var peekedByte = this.getByte();
+      this.pos--;
+      return peekedByte;
+    },
+    peekBytes: function peekBytes(length) {
+      var forceClamped = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
+      var bytes = this.getBytes(length, forceClamped);
+      this.pos -= bytes.length;
+      return bytes;
+    },
+    makeSubStream: function DecodeStream_makeSubStream(start, length, dict) {
+      var end = start + length;
+
+      while (this.bufferLength <= end && !this.eof) {
+        this.readBlock();
+      }
+
+      return new Stream(this.buffer, start, length, dict);
+    },
+    skip: function DecodeStream_skip(n) {
+      if (!n) {
+        n = 1;
+      }
+
+      this.pos += n;
+    },
+    reset: function DecodeStream_reset() {
+      this.pos = 0;
+    },
+    getBaseStreams: function DecodeStream_getBaseStreams() {
+      if (this.str && this.str.getBaseStreams) {
+        return this.str.getBaseStreams();
+      }
+
+      return [];
+    }
+  };
+  return DecodeStream;
+}();
+
+exports.DecodeStream = DecodeStream;
+
+var StreamsSequenceStream = function StreamsSequenceStreamClosure() {
+  function StreamsSequenceStream(streams) {
+    this.streams = streams;
+    var maybeLength = 0;
+
+    for (var i = 0, ii = streams.length; i < ii; i++) {
+      var stream = streams[i];
+
+      if (stream instanceof DecodeStream) {
+        maybeLength += stream._rawMinBufferLength;
+      } else {
+        maybeLength += stream.length;
+      }
+    }
+
+    DecodeStream.call(this, maybeLength);
+  }
+
+  StreamsSequenceStream.prototype = Object.create(DecodeStream.prototype);
+
+  StreamsSequenceStream.prototype.readBlock = function streamSequenceStreamReadBlock() {
+    var streams = this.streams;
+
+    if (streams.length === 0) {
+      this.eof = true;
+      return;
+    }
+
+    var stream = streams.shift();
+    var chunk = stream.getBytes();
+    var bufferLength = this.bufferLength;
+    var newLength = bufferLength + chunk.length;
+    var buffer = this.ensureBuffer(newLength);
+    buffer.set(chunk, bufferLength);
+    this.bufferLength = newLength;
+  };
+
+  StreamsSequenceStream.prototype.getBaseStreams = function StreamsSequenceStream_getBaseStreams() {
+    var baseStreams = [];
+
+    for (var i = 0, ii = this.streams.length; i < ii; i++) {
+      var stream = this.streams[i];
+
+      if (stream.getBaseStreams) {
+        baseStreams.push.apply(baseStreams, _toConsumableArray(stream.getBaseStreams()));
+      }
+    }
+
+    return baseStreams;
+  };
+
+  return StreamsSequenceStream;
+}();
+
+exports.StreamsSequenceStream = StreamsSequenceStream;
+
+var FlateStream = function FlateStreamClosure() {
+  var codeLenCodeMap = new Int32Array([16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15]);
+  var lengthDecode = new Int32Array([0x00003, 0x00004, 0x00005, 0x00006, 0x00007, 0x00008, 0x00009, 0x0000a, 0x1000b, 0x1000d, 0x1000f, 0x10011, 0x20013, 0x20017, 0x2001b, 0x2001f, 0x30023, 0x3002b, 0x30033, 0x3003b, 0x40043, 0x40053, 0x40063, 0x40073, 0x50083, 0x500a3, 0x500c3, 0x500e3, 0x00102, 0x00102, 0x00102]);
+  var distDecode = new Int32Array([0x00001, 0x00002, 0x00003, 0x00004, 0x10005, 0x10007, 0x20009, 0x2000d, 0x30011, 0x30019, 0x40021, 0x40031, 0x50041, 0x50061, 0x60081, 0x600c1, 0x70101, 0x70181, 0x80201, 0x80301, 0x90401, 0x90601, 0xa0801, 0xa0c01, 0xb1001, 0xb1801, 0xc2001, 0xc3001, 0xd4001, 0xd6001]);
+  var fixedLitCodeTab = [new Int32Array([0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c0, 0x70108, 0x80060, 0x80020, 0x900a0, 0x80000, 0x80080, 0x80040, 0x900e0, 0x70104, 0x80058, 0x80018, 0x90090, 0x70114, 0x80078, 0x80038, 0x900d0, 0x7010c, 0x80068, 0x80028, 0x900b0, 0x80008, 0x80088, 0x80048, 0x900f0, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c8, 0x7010a, 0x80064, 0x80024, 0x900a8, 0x80004, 0x80084, 0x80044, 0x900e8, 0x70106, 0x8005c, 0x8001c, 0x90098, 0x70116, 0x8007c, 0x8003c, 0x900d8, 0x7010e, 0x8006c, 0x8002c, 0x900b8, 0x8000c, 0x8008c, 0x8004c, 0x900f8, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c4, 0x70109, 0x80062, 0x80022, 0x900a4, 0x80002, 0x80082, 0x80042, 0x900e4, 0x70105, 0x8005a, 0x8001a, 0x90094, 0x70115, 0x8007a, 0x8003a, 0x900d4, 0x7010d, 0x8006a, 0x8002a, 0x900b4, 0x8000a, 0x8008a, 0x8004a, 0x900f4, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cc, 0x7010b, 0x80066, 0x80026, 0x900ac, 0x80006, 0x80086, 0x80046, 0x900ec, 0x70107, 0x8005e, 0x8001e, 0x9009c, 0x70117, 0x8007e, 0x8003e, 0x900dc, 0x7010f, 0x8006e, 0x8002e, 0x900bc, 0x8000e, 0x8008e, 0x8004e, 0x900fc, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c2, 0x70108, 0x80061, 0x80021, 0x900a2, 0x80001, 0x80081, 0x80041, 0x900e2, 0x70104, 0x80059, 0x80019, 0x90092, 0x70114, 0x80079, 0x80039, 0x900d2, 0x7010c, 0x80069, 0x80029, 0x900b2, 0x80009, 0x80089, 0x80049, 0x900f2, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900ca, 0x7010a, 0x80065, 0x80025, 0x900aa, 0x80005, 0x80085, 0x80045, 0x900ea, 0x70106, 0x8005d, 0x8001d, 0x9009a, 0x70116, 0x8007d, 0x8003d, 0x900da, 0x7010e, 0x8006d, 0x8002d, 0x900ba, 0x8000d, 0x8008d, 0x8004d, 0x900fa, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c6, 0x70109, 0x80063, 0x80023, 0x900a6, 0x80003, 0x80083, 0x80043, 0x900e6, 0x70105, 0x8005b, 0x8001b, 0x90096, 0x70115, 0x8007b, 0x8003b, 0x900d6, 0x7010d, 0x8006b, 0x8002b, 0x900b6, 0x8000b, 0x8008b, 0x8004b, 0x900f6, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900ce, 0x7010b, 0x80067, 0x80027, 0x900ae, 0x80007, 0x80087, 0x80047, 0x900ee, 0x70107, 0x8005f, 0x8001f, 0x9009e, 0x70117, 0x8007f, 0x8003f, 0x900de, 0x7010f, 0x8006f, 0x8002f, 0x900be, 0x8000f, 0x8008f, 0x8004f, 0x900fe, 0x70100, 0x80050, 0x80010, 0x80118, 0x70110, 0x80070, 0x80030, 0x900c1, 0x70108, 0x80060, 0x80020, 0x900a1, 0x80000, 0x80080, 0x80040, 0x900e1, 0x70104, 0x80058, 0x80018, 0x90091, 0x70114, 0x80078, 0x80038, 0x900d1, 0x7010c, 0x80068, 0x80028, 0x900b1, 0x80008, 0x80088, 0x80048, 0x900f1, 0x70102, 0x80054, 0x80014, 0x8011c, 0x70112, 0x80074, 0x80034, 0x900c9, 0x7010a, 0x80064, 0x80024, 0x900a9, 0x80004, 0x80084, 0x80044, 0x900e9, 0x70106, 0x8005c, 0x8001c, 0x90099, 0x70116, 0x8007c, 0x8003c, 0x900d9, 0x7010e, 0x8006c, 0x8002c, 0x900b9, 0x8000c, 0x8008c, 0x8004c, 0x900f9, 0x70101, 0x80052, 0x80012, 0x8011a, 0x70111, 0x80072, 0x80032, 0x900c5, 0x70109, 0x80062, 0x80022, 0x900a5, 0x80002, 0x80082, 0x80042, 0x900e5, 0x70105, 0x8005a, 0x8001a, 0x90095, 0x70115, 0x8007a, 0x8003a, 0x900d5, 0x7010d, 0x8006a, 0x8002a, 0x900b5, 0x8000a, 0x8008a, 0x8004a, 0x900f5, 0x70103, 0x80056, 0x80016, 0x8011e, 0x70113, 0x80076, 0x80036, 0x900cd, 0x7010b, 0x80066, 0x80026, 0x900ad, 0x80006, 0x80086, 0x80046, 0x900ed, 0x70107, 0x8005e, 0x8001e, 0x9009d, 0x70117, 0x8007e, 0x8003e, 0x900dd, 0x7010f, 0x8006e, 0x8002e, 0x900bd, 0x8000e, 0x8008e, 0x8004e, 0x900fd, 0x70100, 0x80051, 0x80011, 0x80119, 0x70110, 0x80071, 0x80031, 0x900c3, 0x70108, 0x80061, 0x80021, 0x900a3, 0x80001, 0x80081, 0x80041, 0x900e3, 0x70104, 0x80059, 0x80019, 0x90093, 0x70114, 0x80079, 0x80039, 0x900d3, 0x7010c, 0x80069, 0x80029, 0x900b3, 0x80009, 0x80089, 0x80049, 0x900f3, 0x70102, 0x80055, 0x80015, 0x8011d, 0x70112, 0x80075, 0x80035, 0x900cb, 0x7010a, 0x80065, 0x80025, 0x900ab, 0x80005, 0x80085, 0x80045, 0x900eb, 0x70106, 0x8005d, 0x8001d, 0x9009b, 0x70116, 0x8007d, 0x8003d, 0x900db, 0x7010e, 0x8006d, 0x8002d, 0x900bb, 0x8000d, 0x8008d, 0x8004d, 0x900fb, 0x70101, 0x80053, 0x80013, 0x8011b, 0x70111, 0x80073, 0x80033, 0x900c7, 0x70109, 0x80063, 0x80023, 0x900a7, 0x80003, 0x80083, 0x80043, 0x900e7, 0x70105, 0x8005b, 0x8001b, 0x90097, 0x70115, 0x8007b, 0x8003b, 0x900d7, 0x7010d, 0x8006b, 0x8002b, 0x900b7, 0x8000b, 0x8008b, 0x8004b, 0x900f7, 0x70103, 0x80057, 0x80017, 0x8011f, 0x70113, 0x80077, 0x80037, 0x900cf, 0x7010b, 0x80067, 0x80027, 0x900af, 0x80007, 0x80087, 0x80047, 0x900ef, 0x70107, 0x8005f, 0x8001f, 0x9009f, 0x70117, 0x8007f, 0x8003f, 0x900df, 0x7010f, 0x8006f, 0x8002f, 0x900bf, 0x8000f, 0x8008f, 0x8004f, 0x900ff]), 9];
+  var fixedDistCodeTab = [new Int32Array([0x50000, 0x50010, 0x50008, 0x50018, 0x50004, 0x50014, 0x5000c, 0x5001c, 0x50002, 0x50012, 0x5000a, 0x5001a, 0x50006, 0x50016, 0x5000e, 0x00000, 0x50001, 0x50011, 0x50009, 0x50019, 0x50005, 0x50015, 0x5000d, 0x5001d, 0x50003, 0x50013, 0x5000b, 0x5001b, 0x50007, 0x50017, 0x5000f, 0x00000]), 5];
+
+  function FlateStream(str, maybeLength) {
+    this.str = str;
+    this.dict = str.dict;
+    var cmf = str.getByte();
+    var flg = str.getByte();
+
+    if (cmf === -1 || flg === -1) {
+      throw new _util.FormatError("Invalid header in flate stream: ".concat(cmf, ", ").concat(flg));
+    }
+
+    if ((cmf & 0x0f) !== 0x08) {
+      throw new _util.FormatError("Unknown compression method in flate stream: ".concat(cmf, ", ").concat(flg));
+    }
+
+    if (((cmf << 8) + flg) % 31 !== 0) {
+      throw new _util.FormatError("Bad FCHECK in flate stream: ".concat(cmf, ", ").concat(flg));
+    }
+
+    if (flg & 0x20) {
+      throw new _util.FormatError("FDICT bit set in flate stream: ".concat(cmf, ", ").concat(flg));
+    }
+
+    this.codeSize = 0;
+    this.codeBuf = 0;
+    DecodeStream.call(this, maybeLength);
+  }
+
+  FlateStream.prototype = Object.create(DecodeStream.prototype);
+
+  FlateStream.prototype.getBits = function FlateStream_getBits(bits) {
+    var str = this.str;
+    var codeSize = this.codeSize;
+    var codeBuf = this.codeBuf;
+    var b;
+
+    while (codeSize < bits) {
+      if ((b = str.getByte()) === -1) {
+        throw new _util.FormatError('Bad encoding in flate stream');
+      }
+
+      codeBuf |= b << codeSize;
+      codeSize += 8;
+    }
+
+    b = codeBuf & (1 << bits) - 1;
+    this.codeBuf = codeBuf >> bits;
+    this.codeSize = codeSize -= bits;
+    return b;
+  };
+
+  FlateStream.prototype.getCode = function FlateStream_getCode(table) {
+    var str = this.str;
+    var codes = table[0];
+    var maxLen = table[1];
+    var codeSize = this.codeSize;
+    var codeBuf = this.codeBuf;
+    var b;
+
+    while (codeSize < maxLen) {
+      if ((b = str.getByte()) === -1) {
+        break;
+      }
+
+      codeBuf |= b << codeSize;
+      codeSize += 8;
+    }
+
+    var code = codes[codeBuf & (1 << maxLen) - 1];
+    var codeLen = code >> 16;
+    var codeVal = code & 0xffff;
+
+    if (codeLen < 1 || codeSize < codeLen) {
+      throw new _util.FormatError('Bad encoding in flate stream');
+    }
+
+    this.codeBuf = codeBuf >> codeLen;
+    this.codeSize = codeSize - codeLen;
+    return codeVal;
+  };
+
+  FlateStream.prototype.generateHuffmanTable = function flateStreamGenerateHuffmanTable(lengths) {
+    var n = lengths.length;
+    var maxLen = 0;
+    var i;
+
+    for (i = 0; i < n; ++i) {
+      if (lengths[i] > maxLen) {
+        maxLen = lengths[i];
+      }
+    }
+
+    var size = 1 << maxLen;
+    var codes = new Int32Array(size);
+
+    for (var len = 1, code = 0, skip = 2; len <= maxLen; ++len, code <<= 1, skip <<= 1) {
+      for (var val = 0; val < n; ++val) {
+        if (lengths[val] === len) {
+          var code2 = 0;
+          var t = code;
+
+          for (i = 0; i < len; ++i) {
+            code2 = code2 << 1 | t & 1;
+            t >>= 1;
+          }
+
+          for (i = code2; i < size; i += skip) {
+            codes[i] = len << 16 | val;
+          }
+
+          ++code;
+        }
+      }
+    }
+
+    return [codes, maxLen];
+  };
+
+  FlateStream.prototype.readBlock = function FlateStream_readBlock() {
+    var buffer, len;
+    var str = this.str;
+    var hdr = this.getBits(3);
+
+    if (hdr & 1) {
+      this.eof = true;
+    }
+
+    hdr >>= 1;
+
+    if (hdr === 0) {
+      var b;
+
+      if ((b = str.getByte()) === -1) {
+        throw new _util.FormatError('Bad block header in flate stream');
+      }
+
+      var blockLen = b;
+
+      if ((b = str.getByte()) === -1) {
+        throw new _util.FormatError('Bad block header in flate stream');
+      }
+
+      blockLen |= b << 8;
+
+      if ((b = str.getByte()) === -1) {
+        throw new _util.FormatError('Bad block header in flate stream');
+      }
+
+      var check = b;
+
+      if ((b = str.getByte()) === -1) {
+        throw new _util.FormatError('Bad block header in flate stream');
+      }
+
+      check |= b << 8;
+
+      if (check !== (~blockLen & 0xffff) && (blockLen !== 0 || check !== 0)) {
+        throw new _util.FormatError('Bad uncompressed block length in flate stream');
+      }
+
+      this.codeBuf = 0;
+      this.codeSize = 0;
+      var bufferLength = this.bufferLength;
+      buffer = this.ensureBuffer(bufferLength + blockLen);
+      var end = bufferLength + blockLen;
+      this.bufferLength = end;
+
+      if (blockLen === 0) {
+        if (str.peekByte() === -1) {
+          this.eof = true;
+        }
+      } else {
+        for (var n = bufferLength; n < end; ++n) {
+          if ((b = str.getByte()) === -1) {
+            this.eof = true;
+            break;
+          }
+
+          buffer[n] = b;
+        }
+      }
+
+      return;
+    }
+
+    var litCodeTable;
+    var distCodeTable;
+
+    if (hdr === 1) {
+      litCodeTable = fixedLitCodeTab;
+      distCodeTable = fixedDistCodeTab;
+    } else if (hdr === 2) {
+      var numLitCodes = this.getBits(5) + 257;
+      var numDistCodes = this.getBits(5) + 1;
+      var numCodeLenCodes = this.getBits(4) + 4;
+      var codeLenCodeLengths = new Uint8Array(codeLenCodeMap.length);
+      var i;
+
+      for (i = 0; i < numCodeLenCodes; ++i) {
+        codeLenCodeLengths[codeLenCodeMap[i]] = this.getBits(3);
+      }
+
+      var codeLenCodeTab = this.generateHuffmanTable(codeLenCodeLengths);
+      len = 0;
+      i = 0;
+      var codes = numLitCodes + numDistCodes;
+      var codeLengths = new Uint8Array(codes);
+      var bitsLength, bitsOffset, what;
+
+      while (i < codes) {
+        var code = this.getCode(codeLenCodeTab);
+
+        if (code === 16) {
+          bitsLength = 2;
+          bitsOffset = 3;
+          what = len;
+        } else if (code === 17) {
+          bitsLength = 3;
+          bitsOffset = 3;
+          what = len = 0;
+        } else if (code === 18) {
+          bitsLength = 7;
+          bitsOffset = 11;
+          what = len = 0;
+        } else {
+          codeLengths[i++] = len = code;
+          continue;
+        }
+
+        var repeatLength = this.getBits(bitsLength) + bitsOffset;
+
+        while (repeatLength-- > 0) {
+          codeLengths[i++] = what;
+        }
+      }
+
+      litCodeTable = this.generateHuffmanTable(codeLengths.subarray(0, numLitCodes));
+      distCodeTable = this.generateHuffmanTable(codeLengths.subarray(numLitCodes, codes));
+    } else {
+      throw new _util.FormatError('Unknown block type in flate stream');
+    }
+
+    buffer = this.buffer;
+    var limit = buffer ? buffer.length : 0;
+    var pos = this.bufferLength;
+
+    while (true) {
+      var code1 = this.getCode(litCodeTable);
+
+      if (code1 < 256) {
+        if (pos + 1 >= limit) {
+          buffer = this.ensureBuffer(pos + 1);
+          limit = buffer.length;
+        }
+
+        buffer[pos++] = code1;
+        continue;
+      }
+
+      if (code1 === 256) {
+        this.bufferLength = pos;
+        return;
+      }
+
+      code1 -= 257;
+      code1 = lengthDecode[code1];
+      var code2 = code1 >> 16;
+
+      if (code2 > 0) {
+        code2 = this.getBits(code2);
+      }
+
+      len = (code1 & 0xffff) + code2;
+      code1 = this.getCode(distCodeTable);
+      code1 = distDecode[code1];
+      code2 = code1 >> 16;
+
+      if (code2 > 0) {
+        code2 = this.getBits(code2);
+      }
+
+      var dist = (code1 & 0xffff) + code2;
+
+      if (pos + len >= limit) {
+        buffer = this.ensureBuffer(pos + len);
+        limit = buffer.length;
+      }
+
+      for (var k = 0; k < len; ++k, ++pos) {
+        buffer[pos] = buffer[pos - dist];
+      }
+    }
+  };
+
+  return FlateStream;
+}();
+
+exports.FlateStream = FlateStream;
+
+var PredictorStream = function PredictorStreamClosure() {
+  function PredictorStream(str, maybeLength, params) {
+    if (!(0, _primitives.isDict)(params)) {
+      return str;
+    }
+
+    var predictor = this.predictor = params.get('Predictor') || 1;
+
+    if (predictor <= 1) {
+      return str;
+    }
+
+    if (predictor !== 2 && (predictor < 10 || predictor > 15)) {
+      throw new _util.FormatError("Unsupported predictor: ".concat(predictor));
+    }
+
+    if (predictor === 2) {
+      this.readBlock = this.readBlockTiff;
+    } else {
+      this.readBlock = this.readBlockPng;
+    }
+
+    this.str = str;
+    this.dict = str.dict;
+    var colors = this.colors = params.get('Colors') || 1;
+    var bits = this.bits = params.get('BitsPerComponent') || 8;
+    var columns = this.columns = params.get('Columns') || 1;
+    this.pixBytes = colors * bits + 7 >> 3;
+    this.rowBytes = columns * colors * bits + 7 >> 3;
+    DecodeStream.call(this, maybeLength);
+    return this;
+  }
+
+  PredictorStream.prototype = Object.create(DecodeStream.prototype);
+
+  PredictorStream.prototype.readBlockTiff = function predictorStreamReadBlockTiff() {
+    var rowBytes = this.rowBytes;
+    var bufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(bufferLength + rowBytes);
+    var bits = this.bits;
+    var colors = this.colors;
+    var rawBytes = this.str.getBytes(rowBytes);
+    this.eof = !rawBytes.length;
+
+    if (this.eof) {
+      return;
+    }
+
+    var inbuf = 0,
+        outbuf = 0;
+    var inbits = 0,
+        outbits = 0;
+    var pos = bufferLength;
+    var i;
+
+    if (bits === 1 && colors === 1) {
+      for (i = 0; i < rowBytes; ++i) {
+        var c = rawBytes[i] ^ inbuf;
+        c ^= c >> 1;
+        c ^= c >> 2;
+        c ^= c >> 4;
+        inbuf = (c & 1) << 7;
+        buffer[pos++] = c;
+      }
+    } else if (bits === 8) {
+      for (i = 0; i < colors; ++i) {
+        buffer[pos++] = rawBytes[i];
+      }
+
+      for (; i < rowBytes; ++i) {
+        buffer[pos] = buffer[pos - colors] + rawBytes[i];
+        pos++;
+      }
+    } else if (bits === 16) {
+      var bytesPerPixel = colors * 2;
+
+      for (i = 0; i < bytesPerPixel; ++i) {
+        buffer[pos++] = rawBytes[i];
+      }
+
+      for (; i < rowBytes; i += 2) {
+        var sum = ((rawBytes[i] & 0xFF) << 8) + (rawBytes[i + 1] & 0xFF) + ((buffer[pos - bytesPerPixel] & 0xFF) << 8) + (buffer[pos - bytesPerPixel + 1] & 0xFF);
+        buffer[pos++] = sum >> 8 & 0xFF;
+        buffer[pos++] = sum & 0xFF;
+      }
+    } else {
+      var compArray = new Uint8Array(colors + 1);
+      var bitMask = (1 << bits) - 1;
+      var j = 0,
+          k = bufferLength;
+      var columns = this.columns;
+
+      for (i = 0; i < columns; ++i) {
+        for (var kk = 0; kk < colors; ++kk) {
+          if (inbits < bits) {
+            inbuf = inbuf << 8 | rawBytes[j++] & 0xFF;
+            inbits += 8;
+          }
+
+          compArray[kk] = compArray[kk] + (inbuf >> inbits - bits) & bitMask;
+          inbits -= bits;
+          outbuf = outbuf << bits | compArray[kk];
+          outbits += bits;
+
+          if (outbits >= 8) {
+            buffer[k++] = outbuf >> outbits - 8 & 0xFF;
+            outbits -= 8;
+          }
+        }
+      }
+
+      if (outbits > 0) {
+        buffer[k++] = (outbuf << 8 - outbits) + (inbuf & (1 << 8 - outbits) - 1);
+      }
+    }
+
+    this.bufferLength += rowBytes;
+  };
+
+  PredictorStream.prototype.readBlockPng = function predictorStreamReadBlockPng() {
+    var rowBytes = this.rowBytes;
+    var pixBytes = this.pixBytes;
+    var predictor = this.str.getByte();
+    var rawBytes = this.str.getBytes(rowBytes);
+    this.eof = !rawBytes.length;
+
+    if (this.eof) {
+      return;
+    }
+
+    var bufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(bufferLength + rowBytes);
+    var prevRow = buffer.subarray(bufferLength - rowBytes, bufferLength);
+
+    if (prevRow.length === 0) {
+      prevRow = new Uint8Array(rowBytes);
+    }
+
+    var i,
+        j = bufferLength,
+        up,
+        c;
+
+    switch (predictor) {
+      case 0:
+        for (i = 0; i < rowBytes; ++i) {
+          buffer[j++] = rawBytes[i];
+        }
+
+        break;
+
+      case 1:
+        for (i = 0; i < pixBytes; ++i) {
+          buffer[j++] = rawBytes[i];
+        }
+
+        for (; i < rowBytes; ++i) {
+          buffer[j] = buffer[j - pixBytes] + rawBytes[i] & 0xFF;
+          j++;
+        }
+
+        break;
+
+      case 2:
+        for (i = 0; i < rowBytes; ++i) {
+          buffer[j++] = prevRow[i] + rawBytes[i] & 0xFF;
+        }
+
+        break;
+
+      case 3:
+        for (i = 0; i < pixBytes; ++i) {
+          buffer[j++] = (prevRow[i] >> 1) + rawBytes[i];
+        }
+
+        for (; i < rowBytes; ++i) {
+          buffer[j] = (prevRow[i] + buffer[j - pixBytes] >> 1) + rawBytes[i] & 0xFF;
+          j++;
+        }
+
+        break;
+
+      case 4:
+        for (i = 0; i < pixBytes; ++i) {
+          up = prevRow[i];
+          c = rawBytes[i];
+          buffer[j++] = up + c;
+        }
+
+        for (; i < rowBytes; ++i) {
+          up = prevRow[i];
+          var upLeft = prevRow[i - pixBytes];
+          var left = buffer[j - pixBytes];
+          var p = left + up - upLeft;
+          var pa = p - left;
+
+          if (pa < 0) {
+            pa = -pa;
+          }
+
+          var pb = p - up;
+
+          if (pb < 0) {
+            pb = -pb;
+          }
+
+          var pc = p - upLeft;
+
+          if (pc < 0) {
+            pc = -pc;
+          }
+
+          c = rawBytes[i];
+
+          if (pa <= pb && pa <= pc) {
+            buffer[j++] = left + c;
+          } else if (pb <= pc) {
+            buffer[j++] = up + c;
+          } else {
+            buffer[j++] = upLeft + c;
+          }
+        }
+
+        break;
+
+      default:
+        throw new _util.FormatError("Unsupported predictor: ".concat(predictor));
+    }
+
+    this.bufferLength += rowBytes;
+  };
+
+  return PredictorStream;
+}();
+
+exports.PredictorStream = PredictorStream;
+
+var DecryptStream = function DecryptStreamClosure() {
+  function DecryptStream(str, maybeLength, decrypt) {
+    this.str = str;
+    this.dict = str.dict;
+    this.decrypt = decrypt;
+    this.nextChunk = null;
+    this.initialized = false;
+    DecodeStream.call(this, maybeLength);
+  }
+
+  var chunkSize = 512;
+  DecryptStream.prototype = Object.create(DecodeStream.prototype);
+
+  DecryptStream.prototype.readBlock = function DecryptStream_readBlock() {
+    var chunk;
+
+    if (this.initialized) {
+      chunk = this.nextChunk;
+    } else {
+      chunk = this.str.getBytes(chunkSize);
+      this.initialized = true;
+    }
+
+    if (!chunk || chunk.length === 0) {
+      this.eof = true;
+      return;
+    }
+
+    this.nextChunk = this.str.getBytes(chunkSize);
+    var hasMoreData = this.nextChunk && this.nextChunk.length > 0;
+    var decrypt = this.decrypt;
+    chunk = decrypt(chunk, !hasMoreData);
+    var bufferLength = this.bufferLength;
+    var i,
+        n = chunk.length;
+    var buffer = this.ensureBuffer(bufferLength + n);
+
+    for (i = 0; i < n; i++) {
+      buffer[bufferLength++] = chunk[i];
+    }
+
+    this.bufferLength = bufferLength;
+  };
+
+  return DecryptStream;
+}();
+
+exports.DecryptStream = DecryptStream;
+
+var Ascii85Stream = function Ascii85StreamClosure() {
+  function Ascii85Stream(str, maybeLength) {
+    this.str = str;
+    this.dict = str.dict;
+    this.input = new Uint8Array(5);
+
+    if (maybeLength) {
+      maybeLength = 0.8 * maybeLength;
+    }
+
+    DecodeStream.call(this, maybeLength);
+  }
+
+  Ascii85Stream.prototype = Object.create(DecodeStream.prototype);
+
+  Ascii85Stream.prototype.readBlock = function Ascii85Stream_readBlock() {
+    var TILDA_CHAR = 0x7E;
+    var Z_LOWER_CHAR = 0x7A;
+    var EOF = -1;
+    var str = this.str;
+    var c = str.getByte();
+
+    while ((0, _util.isSpace)(c)) {
+      c = str.getByte();
+    }
+
+    if (c === EOF || c === TILDA_CHAR) {
+      this.eof = true;
+      return;
+    }
+
+    var bufferLength = this.bufferLength,
+        buffer;
+    var i;
+
+    if (c === Z_LOWER_CHAR) {
+      buffer = this.ensureBuffer(bufferLength + 4);
+
+      for (i = 0; i < 4; ++i) {
+        buffer[bufferLength + i] = 0;
+      }
+
+      this.bufferLength += 4;
+    } else {
+      var input = this.input;
+      input[0] = c;
+
+      for (i = 1; i < 5; ++i) {
+        c = str.getByte();
+
+        while ((0, _util.isSpace)(c)) {
+          c = str.getByte();
+        }
+
+        input[i] = c;
+
+        if (c === EOF || c === TILDA_CHAR) {
+          break;
+        }
+      }
+
+      buffer = this.ensureBuffer(bufferLength + i - 1);
+      this.bufferLength += i - 1;
+
+      if (i < 5) {
+        for (; i < 5; ++i) {
+          input[i] = 0x21 + 84;
+        }
+
+        this.eof = true;
+      }
+
+      var t = 0;
+
+      for (i = 0; i < 5; ++i) {
+        t = t * 85 + (input[i] - 0x21);
+      }
+
+      for (i = 3; i >= 0; --i) {
+        buffer[bufferLength + i] = t & 0xFF;
+        t >>= 8;
+      }
+    }
+  };
+
+  return Ascii85Stream;
+}();
+
+exports.Ascii85Stream = Ascii85Stream;
+
+var AsciiHexStream = function AsciiHexStreamClosure() {
+  function AsciiHexStream(str, maybeLength) {
+    this.str = str;
+    this.dict = str.dict;
+    this.firstDigit = -1;
+
+    if (maybeLength) {
+      maybeLength = 0.5 * maybeLength;
+    }
+
+    DecodeStream.call(this, maybeLength);
+  }
+
+  AsciiHexStream.prototype = Object.create(DecodeStream.prototype);
+
+  AsciiHexStream.prototype.readBlock = function AsciiHexStream_readBlock() {
+    var UPSTREAM_BLOCK_SIZE = 8000;
+    var bytes = this.str.getBytes(UPSTREAM_BLOCK_SIZE);
+
+    if (!bytes.length) {
+      this.eof = true;
+      return;
+    }
+
+    var maxDecodeLength = bytes.length + 1 >> 1;
+    var buffer = this.ensureBuffer(this.bufferLength + maxDecodeLength);
+    var bufferLength = this.bufferLength;
+    var firstDigit = this.firstDigit;
+
+    for (var i = 0, ii = bytes.length; i < ii; i++) {
+      var ch = bytes[i],
+          digit;
+
+      if (ch >= 0x30 && ch <= 0x39) {
+        digit = ch & 0x0F;
+      } else if (ch >= 0x41 && ch <= 0x46 || ch >= 0x61 && ch <= 0x66) {
+        digit = (ch & 0x0F) + 9;
+      } else if (ch === 0x3E) {
+        this.eof = true;
+        break;
+      } else {
+        continue;
+      }
+
+      if (firstDigit < 0) {
+        firstDigit = digit;
+      } else {
+        buffer[bufferLength++] = firstDigit << 4 | digit;
+        firstDigit = -1;
+      }
+    }
+
+    if (firstDigit >= 0 && this.eof) {
+      buffer[bufferLength++] = firstDigit << 4;
+      firstDigit = -1;
+    }
+
+    this.firstDigit = firstDigit;
+    this.bufferLength = bufferLength;
+  };
+
+  return AsciiHexStream;
+}();
+
+exports.AsciiHexStream = AsciiHexStream;
+
+var RunLengthStream = function RunLengthStreamClosure() {
+  function RunLengthStream(str, maybeLength) {
+    this.str = str;
+    this.dict = str.dict;
+    DecodeStream.call(this, maybeLength);
+  }
+
+  RunLengthStream.prototype = Object.create(DecodeStream.prototype);
+
+  RunLengthStream.prototype.readBlock = function RunLengthStream_readBlock() {
+    var repeatHeader = this.str.getBytes(2);
+
+    if (!repeatHeader || repeatHeader.length < 2 || repeatHeader[0] === 128) {
+      this.eof = true;
+      return;
+    }
+
+    var buffer;
+    var bufferLength = this.bufferLength;
+    var n = repeatHeader[0];
+
+    if (n < 128) {
+      buffer = this.ensureBuffer(bufferLength + n + 1);
+      buffer[bufferLength++] = repeatHeader[1];
+
+      if (n > 0) {
+        var source = this.str.getBytes(n);
+        buffer.set(source, bufferLength);
+        bufferLength += n;
+      }
+    } else {
+      n = 257 - n;
+      var b = repeatHeader[1];
+      buffer = this.ensureBuffer(bufferLength + n + 1);
+
+      for (var i = 0; i < n; i++) {
+        buffer[bufferLength++] = b;
+      }
+    }
+
+    this.bufferLength = bufferLength;
+  };
+
+  return RunLengthStream;
+}();
+
+exports.RunLengthStream = RunLengthStream;
+
+var LZWStream = function LZWStreamClosure() {
+  function LZWStream(str, maybeLength, earlyChange) {
+    this.str = str;
+    this.dict = str.dict;
+    this.cachedData = 0;
+    this.bitsCached = 0;
+    var maxLzwDictionarySize = 4096;
+    var lzwState = {
+      earlyChange: earlyChange,
+      codeLength: 9,
+      nextCode: 258,
+      dictionaryValues: new Uint8Array(maxLzwDictionarySize),
+      dictionaryLengths: new Uint16Array(maxLzwDictionarySize),
+      dictionaryPrevCodes: new Uint16Array(maxLzwDictionarySize),
+      currentSequence: new Uint8Array(maxLzwDictionarySize),
+      currentSequenceLength: 0
+    };
+
+    for (var i = 0; i < 256; ++i) {
+      lzwState.dictionaryValues[i] = i;
+      lzwState.dictionaryLengths[i] = 1;
+    }
+
+    this.lzwState = lzwState;
+    DecodeStream.call(this, maybeLength);
+  }
+
+  LZWStream.prototype = Object.create(DecodeStream.prototype);
+
+  LZWStream.prototype.readBits = function LZWStream_readBits(n) {
+    var bitsCached = this.bitsCached;
+    var cachedData = this.cachedData;
+
+    while (bitsCached < n) {
+      var c = this.str.getByte();
+
+      if (c === -1) {
+        this.eof = true;
+        return null;
+      }
+
+      cachedData = cachedData << 8 | c;
+      bitsCached += 8;
+    }
+
+    this.bitsCached = bitsCached -= n;
+    this.cachedData = cachedData;
+    this.lastCode = null;
+    return cachedData >>> bitsCached & (1 << n) - 1;
+  };
+
+  LZWStream.prototype.readBlock = function LZWStream_readBlock() {
+    var blockSize = 512;
+    var estimatedDecodedSize = blockSize * 2,
+        decodedSizeDelta = blockSize;
+    var i, j, q;
+    var lzwState = this.lzwState;
+
+    if (!lzwState) {
+      return;
+    }
+
+    var earlyChange = lzwState.earlyChange;
+    var nextCode = lzwState.nextCode;
+    var dictionaryValues = lzwState.dictionaryValues;
+    var dictionaryLengths = lzwState.dictionaryLengths;
+    var dictionaryPrevCodes = lzwState.dictionaryPrevCodes;
+    var codeLength = lzwState.codeLength;
+    var prevCode = lzwState.prevCode;
+    var currentSequence = lzwState.currentSequence;
+    var currentSequenceLength = lzwState.currentSequenceLength;
+    var decodedLength = 0;
+    var currentBufferLength = this.bufferLength;
+    var buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+
+    for (i = 0; i < blockSize; i++) {
+      var code = this.readBits(codeLength);
+      var hasPrev = currentSequenceLength > 0;
+
+      if (code < 256) {
+        currentSequence[0] = code;
+        currentSequenceLength = 1;
+      } else if (code >= 258) {
+        if (code < nextCode) {
+          currentSequenceLength = dictionaryLengths[code];
+
+          for (j = currentSequenceLength - 1, q = code; j >= 0; j--) {
+            currentSequence[j] = dictionaryValues[q];
+            q = dictionaryPrevCodes[q];
+          }
+        } else {
+          currentSequence[currentSequenceLength++] = currentSequence[0];
+        }
+      } else if (code === 256) {
+        codeLength = 9;
+        nextCode = 258;
+        currentSequenceLength = 0;
+        continue;
+      } else {
+        this.eof = true;
+        delete this.lzwState;
+        break;
+      }
+
+      if (hasPrev) {
+        dictionaryPrevCodes[nextCode] = prevCode;
+        dictionaryLengths[nextCode] = dictionaryLengths[prevCode] + 1;
+        dictionaryValues[nextCode] = currentSequence[0];
+        nextCode++;
+        codeLength = nextCode + earlyChange & nextCode + earlyChange - 1 ? codeLength : Math.min(Math.log(nextCode + earlyChange) / 0.6931471805599453 + 1, 12) | 0;
+      }
+
+      prevCode = code;
+      decodedLength += currentSequenceLength;
+
+      if (estimatedDecodedSize < decodedLength) {
+        do {
+          estimatedDecodedSize += decodedSizeDelta;
+        } while (estimatedDecodedSize < decodedLength);
+
+        buffer = this.ensureBuffer(this.bufferLength + estimatedDecodedSize);
+      }
+
+      for (j = 0; j < currentSequenceLength; j++) {
+        buffer[currentBufferLength++] = currentSequence[j];
+      }
+    }
+
+    lzwState.nextCode = nextCode;
+    lzwState.codeLength = codeLength;
+    lzwState.prevCode = prevCode;
+    lzwState.currentSequenceLength = currentSequenceLength;
+    this.bufferLength = currentBufferLength;
+  };
+
+  return LZWStream;
+}();
+
+exports.LZWStream = LZWStream;
+
+var NullStream = function NullStreamClosure() {
+  function NullStream() {
+    Stream.call(this, new Uint8Array(0));
+  }
+
+  NullStream.prototype = Stream.prototype;
+  return NullStream;
+}();
+
+exports.NullStream = NullStream;
+
+/***/ }),
+/* 159 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.CCITTFaxStream = void 0;
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _ccitt = __w_pdfjs_require__(160);
+
+var _stream = __w_pdfjs_require__(158);
+
+var CCITTFaxStream = function CCITTFaxStreamClosure() {
+  function CCITTFaxStream(str, maybeLength, params) {
+    this.str = str;
+    this.dict = str.dict;
+
+    if (!(0, _primitives.isDict)(params)) {
+      params = _primitives.Dict.empty;
+    }
+
+    var source = {
+      next: function next() {
+        return str.getByte();
+      }
+    };
+    this.ccittFaxDecoder = new _ccitt.CCITTFaxDecoder(source, {
+      K: params.get('K'),
+      EndOfLine: params.get('EndOfLine'),
+      EncodedByteAlign: params.get('EncodedByteAlign'),
+      Columns: params.get('Columns'),
+      Rows: params.get('Rows'),
+      EndOfBlock: params.get('EndOfBlock'),
+      BlackIs1: params.get('BlackIs1')
+    });
+
+    _stream.DecodeStream.call(this, maybeLength);
+  }
+
+  CCITTFaxStream.prototype = Object.create(_stream.DecodeStream.prototype);
+
+  CCITTFaxStream.prototype.readBlock = function () {
+    while (!this.eof) {
+      var c = this.ccittFaxDecoder.readNextChar();
+
+      if (c === -1) {
+        this.eof = true;
+        return;
+      }
+
+      this.ensureBuffer(this.bufferLength + 1);
+      this.buffer[this.bufferLength++] = c;
+    }
+  };
+
+  return CCITTFaxStream;
+}();
+
+exports.CCITTFaxStream = CCITTFaxStream;
+
+/***/ }),
+/* 160 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.CCITTFaxDecoder = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var CCITTFaxDecoder = function CCITTFaxDecoder() {
+  var ccittEOL = -2;
+  var ccittEOF = -1;
+  var twoDimPass = 0;
+  var twoDimHoriz = 1;
+  var twoDimVert0 = 2;
+  var twoDimVertR1 = 3;
+  var twoDimVertL1 = 4;
+  var twoDimVertR2 = 5;
+  var twoDimVertL2 = 6;
+  var twoDimVertR3 = 7;
+  var twoDimVertL3 = 8;
+  var twoDimTable = [[-1, -1], [-1, -1], [7, twoDimVertL3], [7, twoDimVertR3], [6, twoDimVertL2], [6, twoDimVertL2], [6, twoDimVertR2], [6, twoDimVertR2], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [4, twoDimPass], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimHoriz], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertL1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [3, twoDimVertR1], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0], [1, twoDimVert0]];
+  var whiteTable1 = [[-1, -1], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [12, 1984], [12, 2048], [12, 2112], [12, 2176], [12, 2240], [12, 2304], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [12, 2368], [12, 2432], [12, 2496], [12, 2560]];
+  var whiteTable2 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [8, 29], [8, 29], [8, 30], [8, 30], [8, 45], [8, 45], [8, 46], [8, 46], [7, 22], [7, 22], [7, 22], [7, 22], [7, 23], [7, 23], [7, 23], [7, 23], [8, 47], [8, 47], [8, 48], [8, 48], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [6, 13], [7, 20], [7, 20], [7, 20], [7, 20], [8, 33], [8, 33], [8, 34], [8, 34], [8, 35], [8, 35], [8, 36], [8, 36], [8, 37], [8, 37], [8, 38], [8, 38], [7, 19], [7, 19], [7, 19], [7, 19], [8, 31], [8, 31], [8, 32], [8, 32], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 1], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [6, 12], [8, 53], [8, 53], [8, 54], [8, 54], [7, 26], [7, 26], [7, 26], [7, 26], [8, 39], [8, 39], [8, 40], [8, 40], [8, 41], [8, 41], [8, 42], [8, 42], [8, 43], [8, 43], [8, 44], [8, 44], [7, 21], [7, 21], [7, 21], [7, 21], [7, 28], [7, 28], [7, 28], [7, 28], [8, 61], [8, 61], [8, 62], [8, 62], [8, 63], [8, 63], [8, 0], [8, 0], [8, 320], [8, 320], [8, 384], [8, 384], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 10], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [5, 11], [7, 27], [7, 27], [7, 27], [7, 27], [8, 59], [8, 59], [8, 60], [8, 60], [9, 1472], [9, 1536], [9, 1600], [9, 1728], [7, 18], [7, 18], [7, 18], [7, 18], [7, 24], [7, 24], [7, 24], [7, 24], [8, 49], [8, 49], [8, 50], [8, 50], [8, 51], [8, 51], [8, 52], [8, 52], [7, 25], [7, 25], [7, 25], [7, 25], [8, 55], [8, 55], [8, 56], [8, 56], [8, 57], [8, 57], [8, 58], [8, 58], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 192], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [6, 1664], [8, 448], [8, 448], [8, 512], [8, 512], [9, 704], [9, 768], [8, 640], [8, 640], [8, 576], [8, 576], [9, 832], [9, 896], [9, 960], [9, 1024], [9, 1088], [9, 1152], [9, 1216], [9, 1280], [9, 1344], [9, 1408], [7, 256], [7, 256], [7, 256], [7, 256], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 2], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [4, 3], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 128], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 8], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [5, 9], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 16], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [6, 17], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 4], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [4, 5], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 14], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [6, 15], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [5, 64], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 6], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7], [4, 7]];
+  var blackTable1 = [[-1, -1], [-1, -1], [12, ccittEOL], [12, ccittEOL], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [-1, -1], [11, 1792], [11, 1792], [11, 1792], [11, 1792], [12, 1984], [12, 1984], [12, 2048], [12, 2048], [12, 2112], [12, 2112], [12, 2176], [12, 2176], [12, 2240], [12, 2240], [12, 2304], [12, 2304], [11, 1856], [11, 1856], [11, 1856], [11, 1856], [11, 1920], [11, 1920], [11, 1920], [11, 1920], [12, 2368], [12, 2368], [12, 2432], [12, 2432], [12, 2496], [12, 2496], [12, 2560], [12, 2560], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [10, 18], [12, 52], [12, 52], [13, 640], [13, 704], [13, 768], [13, 832], [12, 55], [12, 55], [12, 56], [12, 56], [13, 1280], [13, 1344], [13, 1408], [13, 1472], [12, 59], [12, 59], [12, 60], [12, 60], [13, 1536], [13, 1600], [11, 24], [11, 24], [11, 24], [11, 24], [11, 25], [11, 25], [11, 25], [11, 25], [13, 1664], [13, 1728], [12, 320], [12, 320], [12, 384], [12, 384], [12, 448], [12, 448], [13, 512], [13, 576], [12, 53], [12, 53], [12, 54], [12, 54], [13, 896], [13, 960], [13, 1024], [13, 1088], [13, 1152], [13, 1216], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64], [10, 64]];
+  var blackTable2 = [[8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [8, 13], [11, 23], [11, 23], [12, 50], [12, 51], [12, 44], [12, 45], [12, 46], [12, 47], [12, 57], [12, 58], [12, 61], [12, 256], [10, 16], [10, 16], [10, 16], [10, 16], [10, 17], [10, 17], [10, 17], [10, 17], [12, 48], [12, 49], [12, 62], [12, 63], [12, 30], [12, 31], [12, 32], [12, 33], [12, 40], [12, 41], [11, 22], [11, 22], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [8, 14], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 10], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [7, 11], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [9, 15], [12, 128], [12, 192], [12, 26], [12, 27], [12, 28], [12, 29], [11, 19], [11, 19], [11, 20], [11, 20], [12, 34], [12, 35], [12, 36], [12, 37], [12, 38], [12, 39], [11, 21], [11, 21], [12, 42], [12, 43], [10, 0], [10, 0], [10, 0], [10, 0], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12], [7, 12]];
+  var blackTable3 = [[-1, -1], [-1, -1], [-1, -1], [-1, -1], [6, 9], [6, 8], [5, 7], [5, 7], [4, 6], [4, 6], [4, 6], [4, 6], [4, 5], [4, 5], [4, 5], [4, 5], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 1], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [3, 4], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 3], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2], [2, 2]];
+
+  function CCITTFaxDecoder(source) {
+    var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
+
+    if (!source || typeof source.next !== 'function') {
+      throw new Error('CCITTFaxDecoder - invalid "source" parameter.');
+    }
+
+    this.source = source;
+    this.eof = false;
+    this.encoding = options['K'] || 0;
+    this.eoline = options['EndOfLine'] || false;
+    this.byteAlign = options['EncodedByteAlign'] || false;
+    this.columns = options['Columns'] || 1728;
+    this.rows = options['Rows'] || 0;
+    var eoblock = options['EndOfBlock'];
+
+    if (eoblock === null || eoblock === undefined) {
+      eoblock = true;
+    }
+
+    this.eoblock = eoblock;
+    this.black = options['BlackIs1'] || false;
+    this.codingLine = new Uint32Array(this.columns + 1);
+    this.refLine = new Uint32Array(this.columns + 2);
+    this.codingLine[0] = this.columns;
+    this.codingPos = 0;
+    this.row = 0;
+    this.nextLine2D = this.encoding < 0;
+    this.inputBits = 0;
+    this.inputBuf = 0;
+    this.outputBits = 0;
+    this.rowsDone = false;
+    var code1;
+
+    while ((code1 = this._lookBits(12)) === 0) {
+      this._eatBits(1);
+    }
+
+    if (code1 === 1) {
+      this._eatBits(12);
+    }
+
+    if (this.encoding > 0) {
+      this.nextLine2D = !this._lookBits(1);
+
+      this._eatBits(1);
+    }
+  }
+
+  CCITTFaxDecoder.prototype = {
+    readNextChar: function readNextChar() {
+      if (this.eof) {
+        return -1;
+      }
+
+      var refLine = this.refLine;
+      var codingLine = this.codingLine;
+      var columns = this.columns;
+      var refPos, blackPixels, bits, i;
+
+      if (this.outputBits === 0) {
+        if (this.rowsDone) {
+          this.eof = true;
+        }
+
+        if (this.eof) {
+          return -1;
+        }
+
+        this.err = false;
+        var code1, code2, code3;
+
+        if (this.nextLine2D) {
+          for (i = 0; codingLine[i] < columns; ++i) {
+            refLine[i] = codingLine[i];
+          }
+
+          refLine[i++] = columns;
+          refLine[i] = columns;
+          codingLine[0] = 0;
+          this.codingPos = 0;
+          refPos = 0;
+          blackPixels = 0;
+
+          while (codingLine[this.codingPos] < columns) {
+            code1 = this._getTwoDimCode();
+
+            switch (code1) {
+              case twoDimPass:
+                this._addPixels(refLine[refPos + 1], blackPixels);
+
+                if (refLine[refPos + 1] < columns) {
+                  refPos += 2;
+                }
+
+                break;
+
+              case twoDimHoriz:
+                code1 = code2 = 0;
+
+                if (blackPixels) {
+                  do {
+                    code1 += code3 = this._getBlackCode();
+                  } while (code3 >= 64);
+
+                  do {
+                    code2 += code3 = this._getWhiteCode();
+                  } while (code3 >= 64);
+                } else {
+                  do {
+                    code1 += code3 = this._getWhiteCode();
+                  } while (code3 >= 64);
+
+                  do {
+                    code2 += code3 = this._getBlackCode();
+                  } while (code3 >= 64);
+                }
+
+                this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
+
+                if (codingLine[this.codingPos] < columns) {
+                  this._addPixels(codingLine[this.codingPos] + code2, blackPixels ^ 1);
+                }
+
+                while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                  refPos += 2;
+                }
+
+                break;
+
+              case twoDimVertR3:
+                this._addPixels(refLine[refPos] + 3, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  ++refPos;
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVertR2:
+                this._addPixels(refLine[refPos] + 2, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  ++refPos;
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVertR1:
+                this._addPixels(refLine[refPos] + 1, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  ++refPos;
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVert0:
+                this._addPixels(refLine[refPos], blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  ++refPos;
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVertL3:
+                this._addPixelsNeg(refLine[refPos] - 3, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  if (refPos > 0) {
+                    --refPos;
+                  } else {
+                    ++refPos;
+                  }
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVertL2:
+                this._addPixelsNeg(refLine[refPos] - 2, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  if (refPos > 0) {
+                    --refPos;
+                  } else {
+                    ++refPos;
+                  }
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case twoDimVertL1:
+                this._addPixelsNeg(refLine[refPos] - 1, blackPixels);
+
+                blackPixels ^= 1;
+
+                if (codingLine[this.codingPos] < columns) {
+                  if (refPos > 0) {
+                    --refPos;
+                  } else {
+                    ++refPos;
+                  }
+
+                  while (refLine[refPos] <= codingLine[this.codingPos] && refLine[refPos] < columns) {
+                    refPos += 2;
+                  }
+                }
+
+                break;
+
+              case ccittEOF:
+                this._addPixels(columns, 0);
+
+                this.eof = true;
+                break;
+
+              default:
+                (0, _util.info)('bad 2d code');
+
+                this._addPixels(columns, 0);
+
+                this.err = true;
+            }
+          }
+        } else {
+          codingLine[0] = 0;
+          this.codingPos = 0;
+          blackPixels = 0;
+
+          while (codingLine[this.codingPos] < columns) {
+            code1 = 0;
+
+            if (blackPixels) {
+              do {
+                code1 += code3 = this._getBlackCode();
+              } while (code3 >= 64);
+            } else {
+              do {
+                code1 += code3 = this._getWhiteCode();
+              } while (code3 >= 64);
+            }
+
+            this._addPixels(codingLine[this.codingPos] + code1, blackPixels);
+
+            blackPixels ^= 1;
+          }
+        }
+
+        var gotEOL = false;
+
+        if (this.byteAlign) {
+          this.inputBits &= ~7;
+        }
+
+        if (!this.eoblock && this.row === this.rows - 1) {
+          this.rowsDone = true;
+        } else {
+          code1 = this._lookBits(12);
+
+          if (this.eoline) {
+            while (code1 !== ccittEOF && code1 !== 1) {
+              this._eatBits(1);
+
+              code1 = this._lookBits(12);
+            }
+          } else {
+            while (code1 === 0) {
+              this._eatBits(1);
+
+              code1 = this._lookBits(12);
+            }
+          }
+
+          if (code1 === 1) {
+            this._eatBits(12);
+
+            gotEOL = true;
+          } else if (code1 === ccittEOF) {
+            this.eof = true;
+          }
+        }
+
+        if (!this.eof && this.encoding > 0 && !this.rowsDone) {
+          this.nextLine2D = !this._lookBits(1);
+
+          this._eatBits(1);
+        }
+
+        if (this.eoblock && gotEOL && this.byteAlign) {
+          code1 = this._lookBits(12);
+
+          if (code1 === 1) {
+            this._eatBits(12);
+
+            if (this.encoding > 0) {
+              this._lookBits(1);
+
+              this._eatBits(1);
+            }
+
+            if (this.encoding >= 0) {
+              for (i = 0; i < 4; ++i) {
+                code1 = this._lookBits(12);
+
+                if (code1 !== 1) {
+                  (0, _util.info)('bad rtc code: ' + code1);
+                }
+
+                this._eatBits(12);
+
+                if (this.encoding > 0) {
+                  this._lookBits(1);
+
+                  this._eatBits(1);
+                }
+              }
+            }
+
+            this.eof = true;
+          }
+        } else if (this.err && this.eoline) {
+          while (true) {
+            code1 = this._lookBits(13);
+
+            if (code1 === ccittEOF) {
+              this.eof = true;
+              return -1;
+            }
+
+            if (code1 >> 1 === 1) {
+              break;
+            }
+
+            this._eatBits(1);
+          }
+
+          this._eatBits(12);
+
+          if (this.encoding > 0) {
+            this._eatBits(1);
+
+            this.nextLine2D = !(code1 & 1);
+          }
+        }
+
+        if (codingLine[0] > 0) {
+          this.outputBits = codingLine[this.codingPos = 0];
+        } else {
+          this.outputBits = codingLine[this.codingPos = 1];
+        }
+
+        this.row++;
+      }
+
+      var c;
+
+      if (this.outputBits >= 8) {
+        c = this.codingPos & 1 ? 0 : 0xFF;
+        this.outputBits -= 8;
+
+        if (this.outputBits === 0 && codingLine[this.codingPos] < columns) {
+          this.codingPos++;
+          this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
+        }
+      } else {
+        bits = 8;
+        c = 0;
+
+        do {
+          if (this.outputBits > bits) {
+            c <<= bits;
+
+            if (!(this.codingPos & 1)) {
+              c |= 0xFF >> 8 - bits;
+            }
+
+            this.outputBits -= bits;
+            bits = 0;
+          } else {
+            c <<= this.outputBits;
+
+            if (!(this.codingPos & 1)) {
+              c |= 0xFF >> 8 - this.outputBits;
+            }
+
+            bits -= this.outputBits;
+            this.outputBits = 0;
+
+            if (codingLine[this.codingPos] < columns) {
+              this.codingPos++;
+              this.outputBits = codingLine[this.codingPos] - codingLine[this.codingPos - 1];
+            } else if (bits > 0) {
+              c <<= bits;
+              bits = 0;
+            }
+          }
+        } while (bits);
+      }
+
+      if (this.black) {
+        c ^= 0xFF;
+      }
+
+      return c;
+    },
+    _addPixels: function _addPixels(a1, blackPixels) {
+      var codingLine = this.codingLine;
+      var codingPos = this.codingPos;
+
+      if (a1 > codingLine[codingPos]) {
+        if (a1 > this.columns) {
+          (0, _util.info)('row is wrong length');
+          this.err = true;
+          a1 = this.columns;
+        }
+
+        if (codingPos & 1 ^ blackPixels) {
+          ++codingPos;
+        }
+
+        codingLine[codingPos] = a1;
+      }
+
+      this.codingPos = codingPos;
+    },
+    _addPixelsNeg: function _addPixelsNeg(a1, blackPixels) {
+      var codingLine = this.codingLine;
+      var codingPos = this.codingPos;
+
+      if (a1 > codingLine[codingPos]) {
+        if (a1 > this.columns) {
+          (0, _util.info)('row is wrong length');
+          this.err = true;
+          a1 = this.columns;
+        }
+
+        if (codingPos & 1 ^ blackPixels) {
+          ++codingPos;
+        }
+
+        codingLine[codingPos] = a1;
+      } else if (a1 < codingLine[codingPos]) {
+        if (a1 < 0) {
+          (0, _util.info)('invalid code');
+          this.err = true;
+          a1 = 0;
+        }
+
+        while (codingPos > 0 && a1 < codingLine[codingPos - 1]) {
+          --codingPos;
+        }
+
+        codingLine[codingPos] = a1;
+      }
+
+      this.codingPos = codingPos;
+    },
+    _findTableCode: function _findTableCode(start, end, table, limit) {
+      var limitValue = limit || 0;
+
+      for (var i = start; i <= end; ++i) {
+        var code = this._lookBits(i);
+
+        if (code === ccittEOF) {
+          return [true, 1, false];
+        }
+
+        if (i < end) {
+          code <<= end - i;
+        }
+
+        if (!limitValue || code >= limitValue) {
+          var p = table[code - limitValue];
+
+          if (p[0] === i) {
+            this._eatBits(i);
+
+            return [true, p[1], true];
+          }
+        }
+      }
+
+      return [false, 0, false];
+    },
+    _getTwoDimCode: function _getTwoDimCode() {
+      var code = 0;
+      var p;
+
+      if (this.eoblock) {
+        code = this._lookBits(7);
+        p = twoDimTable[code];
+
+        if (p && p[0] > 0) {
+          this._eatBits(p[0]);
+
+          return p[1];
+        }
+      } else {
+        var result = this._findTableCode(1, 7, twoDimTable);
+
+        if (result[0] && result[2]) {
+          return result[1];
+        }
+      }
+
+      (0, _util.info)('Bad two dim code');
+      return ccittEOF;
+    },
+    _getWhiteCode: function _getWhiteCode() {
+      var code = 0;
+      var p;
+
+      if (this.eoblock) {
+        code = this._lookBits(12);
+
+        if (code === ccittEOF) {
+          return 1;
+        }
+
+        if (code >> 5 === 0) {
+          p = whiteTable1[code];
+        } else {
+          p = whiteTable2[code >> 3];
+        }
+
+        if (p[0] > 0) {
+          this._eatBits(p[0]);
+
+          return p[1];
+        }
+      } else {
+        var result = this._findTableCode(1, 9, whiteTable2);
+
+        if (result[0]) {
+          return result[1];
+        }
+
+        result = this._findTableCode(11, 12, whiteTable1);
+
+        if (result[0]) {
+          return result[1];
+        }
+      }
+
+      (0, _util.info)('bad white code');
+
+      this._eatBits(1);
+
+      return 1;
+    },
+    _getBlackCode: function _getBlackCode() {
+      var code, p;
+
+      if (this.eoblock) {
+        code = this._lookBits(13);
+
+        if (code === ccittEOF) {
+          return 1;
+        }
+
+        if (code >> 7 === 0) {
+          p = blackTable1[code];
+        } else if (code >> 9 === 0 && code >> 7 !== 0) {
+          p = blackTable2[(code >> 1) - 64];
+        } else {
+          p = blackTable3[code >> 7];
+        }
+
+        if (p[0] > 0) {
+          this._eatBits(p[0]);
+
+          return p[1];
+        }
+      } else {
+        var result = this._findTableCode(2, 6, blackTable3);
+
+        if (result[0]) {
+          return result[1];
+        }
+
+        result = this._findTableCode(7, 12, blackTable2, 64);
+
+        if (result[0]) {
+          return result[1];
+        }
+
+        result = this._findTableCode(10, 13, blackTable1);
+
+        if (result[0]) {
+          return result[1];
+        }
+      }
+
+      (0, _util.info)('bad black code');
+
+      this._eatBits(1);
+
+      return 1;
+    },
+    _lookBits: function _lookBits(n) {
+      var c;
+
+      while (this.inputBits < n) {
+        if ((c = this.source.next()) === -1) {
+          if (this.inputBits === 0) {
+            return ccittEOF;
+          }
+
+          return this.inputBuf << n - this.inputBits & 0xFFFF >> 16 - n;
+        }
+
+        this.inputBuf = this.inputBuf << 8 | c;
+        this.inputBits += 8;
+      }
+
+      return this.inputBuf >> this.inputBits - n & 0xFFFF >> 16 - n;
+    },
+    _eatBits: function _eatBits(n) {
+      if ((this.inputBits -= n) < 0) {
+        this.inputBits = 0;
+      }
+    }
+  };
+  return CCITTFaxDecoder;
+}();
+
+exports.CCITTFaxDecoder = CCITTFaxDecoder;
+
+/***/ }),
+/* 161 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Jbig2Stream = void 0;
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _stream = __w_pdfjs_require__(158);
+
+var _jbig = __w_pdfjs_require__(162);
+
+var _util = __w_pdfjs_require__(5);
+
+var Jbig2Stream = function Jbig2StreamClosure() {
+  function Jbig2Stream(stream, maybeLength, dict, params) {
+    this.stream = stream;
+    this.maybeLength = maybeLength;
+    this.dict = dict;
+    this.params = params;
+
+    _stream.DecodeStream.call(this, maybeLength);
+  }
+
+  Jbig2Stream.prototype = Object.create(_stream.DecodeStream.prototype);
+  Object.defineProperty(Jbig2Stream.prototype, 'bytes', {
+    get: function get() {
+      return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
+    },
+    configurable: true
+  });
+
+  Jbig2Stream.prototype.ensureBuffer = function (requested) {};
+
+  Jbig2Stream.prototype.readBlock = function () {
+    if (this.eof) {
+      return;
+    }
+
+    var jbig2Image = new _jbig.Jbig2Image();
+    var chunks = [];
+
+    if ((0, _primitives.isDict)(this.params)) {
+      var globalsStream = this.params.get('JBIG2Globals');
+
+      if ((0, _primitives.isStream)(globalsStream)) {
+        var globals = globalsStream.getBytes();
+        chunks.push({
+          data: globals,
+          start: 0,
+          end: globals.length
+        });
+      }
+    }
+
+    chunks.push({
+      data: this.bytes,
+      start: 0,
+      end: this.bytes.length
+    });
+    var data = jbig2Image.parseChunks(chunks);
+    var dataLength = data.length;
+
+    for (var i = 0; i < dataLength; i++) {
+      data[i] ^= 0xFF;
+    }
+
+    this.buffer = data;
+    this.bufferLength = dataLength;
+    this.eof = true;
+  };
+
+  return Jbig2Stream;
+}();
+
+exports.Jbig2Stream = Jbig2Stream;
+
+/***/ }),
+/* 162 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Jbig2Image = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _arithmetic_decoder = __w_pdfjs_require__(163);
+
+var _ccitt = __w_pdfjs_require__(160);
+
+var Jbig2Error = function Jbig2ErrorClosure() {
+  function Jbig2Error(msg) {
+    this.message = 'JBIG2 error: ' + msg;
+  }
+
+  Jbig2Error.prototype = new Error();
+  Jbig2Error.prototype.name = 'Jbig2Error';
+  Jbig2Error.constructor = Jbig2Error;
+  return Jbig2Error;
+}();
+
+var Jbig2Image = function Jbig2ImageClosure() {
+  function ContextCache() {}
+
+  ContextCache.prototype = {
+    getContexts: function getContexts(id) {
+      if (id in this) {
+        return this[id];
+      }
+
+      return this[id] = new Int8Array(1 << 16);
+    }
+  };
+
+  function DecodingContext(data, start, end) {
+    this.data = data;
+    this.start = start;
+    this.end = end;
+  }
+
+  DecodingContext.prototype = {
+    get decoder() {
+      var decoder = new _arithmetic_decoder.ArithmeticDecoder(this.data, this.start, this.end);
+      return (0, _util.shadow)(this, 'decoder', decoder);
+    },
+
+    get contextCache() {
+      var cache = new ContextCache();
+      return (0, _util.shadow)(this, 'contextCache', cache);
+    }
+
+  };
+
+  function decodeInteger(contextCache, procedure, decoder) {
+    var contexts = contextCache.getContexts(procedure);
+    var prev = 1;
+
+    function readBits(length) {
+      var v = 0;
+
+      for (var i = 0; i < length; i++) {
+        var bit = decoder.readBit(contexts, prev);
+        prev = prev < 256 ? prev << 1 | bit : (prev << 1 | bit) & 511 | 256;
+        v = v << 1 | bit;
+      }
+
+      return v >>> 0;
+    }
+
+    var sign = readBits(1);
+    var value = readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(1) ? readBits(32) + 4436 : readBits(12) + 340 : readBits(8) + 84 : readBits(6) + 20 : readBits(4) + 4 : readBits(2);
+    return sign === 0 ? value : value > 0 ? -value : null;
+  }
+
+  function decodeIAID(contextCache, decoder, codeLength) {
+    var contexts = contextCache.getContexts('IAID');
+    var prev = 1;
+
+    for (var i = 0; i < codeLength; i++) {
+      var bit = decoder.readBit(contexts, prev);
+      prev = prev << 1 | bit;
+    }
+
+    if (codeLength < 31) {
+      return prev & (1 << codeLength) - 1;
+    }
+
+    return prev & 0x7FFFFFFF;
+  }
+
+  var SegmentTypes = ['SymbolDictionary', null, null, null, 'IntermediateTextRegion', null, 'ImmediateTextRegion', 'ImmediateLosslessTextRegion', null, null, null, null, null, null, null, null, 'PatternDictionary', null, null, null, 'IntermediateHalftoneRegion', null, 'ImmediateHalftoneRegion', 'ImmediateLosslessHalftoneRegion', null, null, null, null, null, null, null, null, null, null, null, null, 'IntermediateGenericRegion', null, 'ImmediateGenericRegion', 'ImmediateLosslessGenericRegion', 'IntermediateGenericRefinementRegion', null, 'ImmediateGenericRefinementRegion', 'ImmediateLosslessGenericRefinementRegion', null, null, null, null, 'PageInformation', 'EndOfPage', 'EndOfStripe', 'EndOfFile', 'Profiles', 'Tables', null, null, null, null, null, null, null, null, 'Extension'];
+  var CodingTemplates = [[{
+    x: -1,
+    y: -2
+  }, {
+    x: 0,
+    y: -2
+  }, {
+    x: 1,
+    y: -2
+  }, {
+    x: -2,
+    y: -1
+  }, {
+    x: -1,
+    y: -1
+  }, {
+    x: 0,
+    y: -1
+  }, {
+    x: 1,
+    y: -1
+  }, {
+    x: 2,
+    y: -1
+  }, {
+    x: -4,
+    y: 0
+  }, {
+    x: -3,
+    y: 0
+  }, {
+    x: -2,
+    y: 0
+  }, {
+    x: -1,
+    y: 0
+  }], [{
+    x: -1,
+    y: -2
+  }, {
+    x: 0,
+    y: -2
+  }, {
+    x: 1,
+    y: -2
+  }, {
+    x: 2,
+    y: -2
+  }, {
+    x: -2,
+    y: -1
+  }, {
+    x: -1,
+    y: -1
+  }, {
+    x: 0,
+    y: -1
+  }, {
+    x: 1,
+    y: -1
+  }, {
+    x: 2,
+    y: -1
+  }, {
+    x: -3,
+    y: 0
+  }, {
+    x: -2,
+    y: 0
+  }, {
+    x: -1,
+    y: 0
+  }], [{
+    x: -1,
+    y: -2
+  }, {
+    x: 0,
+    y: -2
+  }, {
+    x: 1,
+    y: -2
+  }, {
+    x: -2,
+    y: -1
+  }, {
+    x: -1,
+    y: -1
+  }, {
+    x: 0,
+    y: -1
+  }, {
+    x: 1,
+    y: -1
+  }, {
+    x: -2,
+    y: 0
+  }, {
+    x: -1,
+    y: 0
+  }], [{
+    x: -3,
+    y: -1
+  }, {
+    x: -2,
+    y: -1
+  }, {
+    x: -1,
+    y: -1
+  }, {
+    x: 0,
+    y: -1
+  }, {
+    x: 1,
+    y: -1
+  }, {
+    x: -4,
+    y: 0
+  }, {
+    x: -3,
+    y: 0
+  }, {
+    x: -2,
+    y: 0
+  }, {
+    x: -1,
+    y: 0
+  }]];
+  var RefinementTemplates = [{
+    coding: [{
+      x: 0,
+      y: -1
+    }, {
+      x: 1,
+      y: -1
+    }, {
+      x: -1,
+      y: 0
+    }],
+    reference: [{
+      x: 0,
+      y: -1
+    }, {
+      x: 1,
+      y: -1
+    }, {
+      x: -1,
+      y: 0
+    }, {
+      x: 0,
+      y: 0
+    }, {
+      x: 1,
+      y: 0
+    }, {
+      x: -1,
+      y: 1
+    }, {
+      x: 0,
+      y: 1
+    }, {
+      x: 1,
+      y: 1
+    }]
+  }, {
+    coding: [{
+      x: -1,
+      y: -1
+    }, {
+      x: 0,
+      y: -1
+    }, {
+      x: 1,
+      y: -1
+    }, {
+      x: -1,
+      y: 0
+    }],
+    reference: [{
+      x: 0,
+      y: -1
+    }, {
+      x: -1,
+      y: 0
+    }, {
+      x: 0,
+      y: 0
+    }, {
+      x: 1,
+      y: 0
+    }, {
+      x: 0,
+      y: 1
+    }, {
+      x: 1,
+      y: 1
+    }]
+  }];
+  var ReusedContexts = [0x9B25, 0x0795, 0x00E5, 0x0195];
+  var RefinementReusedContexts = [0x0020, 0x0008];
+
+  function decodeBitmapTemplate0(width, height, decodingContext) {
+    var decoder = decodingContext.decoder;
+    var contexts = decodingContext.contextCache.getContexts('GB');
+    var contextLabel,
+        i,
+        j,
+        pixel,
+        row,
+        row1,
+        row2,
+        bitmap = [];
+    var OLD_PIXEL_MASK = 0x7BF7;
+
+    for (i = 0; i < height; i++) {
+      row = bitmap[i] = new Uint8Array(width);
+      row1 = i < 1 ? row : bitmap[i - 1];
+      row2 = i < 2 ? row : bitmap[i - 2];
+      contextLabel = row2[0] << 13 | row2[1] << 12 | row2[2] << 11 | row1[0] << 7 | row1[1] << 6 | row1[2] << 5 | row1[3] << 4;
+
+      for (j = 0; j < width; j++) {
+        row[j] = pixel = decoder.readBit(contexts, contextLabel);
+        contextLabel = (contextLabel & OLD_PIXEL_MASK) << 1 | (j + 3 < width ? row2[j + 3] << 11 : 0) | (j + 4 < width ? row1[j + 4] << 4 : 0) | pixel;
+      }
+    }
+
+    return bitmap;
+  }
+
+  function decodeBitmap(mmr, width, height, templateIndex, prediction, skip, at, decodingContext) {
+    if (mmr) {
+      var input = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
+      return decodeMMRBitmap(input, width, height, false);
+    }
+
+    if (templateIndex === 0 && !skip && !prediction && at.length === 4 && at[0].x === 3 && at[0].y === -1 && at[1].x === -3 && at[1].y === -1 && at[2].x === 2 && at[2].y === -2 && at[3].x === -2 && at[3].y === -2) {
+      return decodeBitmapTemplate0(width, height, decodingContext);
+    }
+
+    var useskip = !!skip;
+    var template = CodingTemplates[templateIndex].concat(at);
+    template.sort(function (a, b) {
+      return a.y - b.y || a.x - b.x;
+    });
+    var templateLength = template.length;
+    var templateX = new Int8Array(templateLength);
+    var templateY = new Int8Array(templateLength);
+    var changingTemplateEntries = [];
+    var reuseMask = 0,
+        minX = 0,
+        maxX = 0,
+        minY = 0;
+    var c, k;
+
+    for (k = 0; k < templateLength; k++) {
+      templateX[k] = template[k].x;
+      templateY[k] = template[k].y;
+      minX = Math.min(minX, template[k].x);
+      maxX = Math.max(maxX, template[k].x);
+      minY = Math.min(minY, template[k].y);
+
+      if (k < templateLength - 1 && template[k].y === template[k + 1].y && template[k].x === template[k + 1].x - 1) {
+        reuseMask |= 1 << templateLength - 1 - k;
+      } else {
+        changingTemplateEntries.push(k);
+      }
+    }
+
+    var changingEntriesLength = changingTemplateEntries.length;
+    var changingTemplateX = new Int8Array(changingEntriesLength);
+    var changingTemplateY = new Int8Array(changingEntriesLength);
+    var changingTemplateBit = new Uint16Array(changingEntriesLength);
+
+    for (c = 0; c < changingEntriesLength; c++) {
+      k = changingTemplateEntries[c];
+      changingTemplateX[c] = template[k].x;
+      changingTemplateY[c] = template[k].y;
+      changingTemplateBit[c] = 1 << templateLength - 1 - k;
+    }
+
+    var sbb_left = -minX;
+    var sbb_top = -minY;
+    var sbb_right = width - maxX;
+    var pseudoPixelContext = ReusedContexts[templateIndex];
+    var row = new Uint8Array(width);
+    var bitmap = [];
+    var decoder = decodingContext.decoder;
+    var contexts = decodingContext.contextCache.getContexts('GB');
+    var ltp = 0,
+        j,
+        i0,
+        j0,
+        contextLabel = 0,
+        bit,
+        shift;
+
+    for (var i = 0; i < height; i++) {
+      if (prediction) {
+        var sltp = decoder.readBit(contexts, pseudoPixelContext);
+        ltp ^= sltp;
+
+        if (ltp) {
+          bitmap.push(row);
+          continue;
+        }
+      }
+
+      row = new Uint8Array(row);
+      bitmap.push(row);
+
+      for (j = 0; j < width; j++) {
+        if (useskip && skip[i][j]) {
+          row[j] = 0;
+          continue;
+        }
+
+        if (j >= sbb_left && j < sbb_right && i >= sbb_top) {
+          contextLabel = contextLabel << 1 & reuseMask;
+
+          for (k = 0; k < changingEntriesLength; k++) {
+            i0 = i + changingTemplateY[k];
+            j0 = j + changingTemplateX[k];
+            bit = bitmap[i0][j0];
+
+            if (bit) {
+              bit = changingTemplateBit[k];
+              contextLabel |= bit;
+            }
+          }
+        } else {
+          contextLabel = 0;
+          shift = templateLength - 1;
+
+          for (k = 0; k < templateLength; k++, shift--) {
+            j0 = j + templateX[k];
+
+            if (j0 >= 0 && j0 < width) {
+              i0 = i + templateY[k];
+
+              if (i0 >= 0) {
+                bit = bitmap[i0][j0];
+
+                if (bit) {
+                  contextLabel |= bit << shift;
+                }
+              }
+            }
+          }
+        }
+
+        var pixel = decoder.readBit(contexts, contextLabel);
+        row[j] = pixel;
+      }
+    }
+
+    return bitmap;
+  }
+
+  function decodeRefinement(width, height, templateIndex, referenceBitmap, offsetX, offsetY, prediction, at, decodingContext) {
+    var codingTemplate = RefinementTemplates[templateIndex].coding;
+
+    if (templateIndex === 0) {
+      codingTemplate = codingTemplate.concat([at[0]]);
+    }
+
+    var codingTemplateLength = codingTemplate.length;
+    var codingTemplateX = new Int32Array(codingTemplateLength);
+    var codingTemplateY = new Int32Array(codingTemplateLength);
+    var k;
+
+    for (k = 0; k < codingTemplateLength; k++) {
+      codingTemplateX[k] = codingTemplate[k].x;
+      codingTemplateY[k] = codingTemplate[k].y;
+    }
+
+    var referenceTemplate = RefinementTemplates[templateIndex].reference;
+
+    if (templateIndex === 0) {
+      referenceTemplate = referenceTemplate.concat([at[1]]);
+    }
+
+    var referenceTemplateLength = referenceTemplate.length;
+    var referenceTemplateX = new Int32Array(referenceTemplateLength);
+    var referenceTemplateY = new Int32Array(referenceTemplateLength);
+
+    for (k = 0; k < referenceTemplateLength; k++) {
+      referenceTemplateX[k] = referenceTemplate[k].x;
+      referenceTemplateY[k] = referenceTemplate[k].y;
+    }
+
+    var referenceWidth = referenceBitmap[0].length;
+    var referenceHeight = referenceBitmap.length;
+    var pseudoPixelContext = RefinementReusedContexts[templateIndex];
+    var bitmap = [];
+    var decoder = decodingContext.decoder;
+    var contexts = decodingContext.contextCache.getContexts('GR');
+    var ltp = 0;
+
+    for (var i = 0; i < height; i++) {
+      if (prediction) {
+        var sltp = decoder.readBit(contexts, pseudoPixelContext);
+        ltp ^= sltp;
+
+        if (ltp) {
+          throw new Jbig2Error('prediction is not supported');
+        }
+      }
+
+      var row = new Uint8Array(width);
+      bitmap.push(row);
+
+      for (var j = 0; j < width; j++) {
+        var i0, j0;
+        var contextLabel = 0;
+
+        for (k = 0; k < codingTemplateLength; k++) {
+          i0 = i + codingTemplateY[k];
+          j0 = j + codingTemplateX[k];
+
+          if (i0 < 0 || j0 < 0 || j0 >= width) {
+            contextLabel <<= 1;
+          } else {
+            contextLabel = contextLabel << 1 | bitmap[i0][j0];
+          }
+        }
+
+        for (k = 0; k < referenceTemplateLength; k++) {
+          i0 = i + referenceTemplateY[k] - offsetY;
+          j0 = j + referenceTemplateX[k] - offsetX;
+
+          if (i0 < 0 || i0 >= referenceHeight || j0 < 0 || j0 >= referenceWidth) {
+            contextLabel <<= 1;
+          } else {
+            contextLabel = contextLabel << 1 | referenceBitmap[i0][j0];
+          }
+        }
+
+        var pixel = decoder.readBit(contexts, contextLabel);
+        row[j] = pixel;
+      }
+    }
+
+    return bitmap;
+  }
+
+  function decodeSymbolDictionary(huffman, refinement, symbols, numberOfNewSymbols, numberOfExportedSymbols, huffmanTables, templateIndex, at, refinementTemplateIndex, refinementAt, decodingContext, huffmanInput) {
+    if (huffman && refinement) {
+      throw new Jbig2Error('symbol refinement with Huffman is not supported');
+    }
+
+    var newSymbols = [];
+    var currentHeight = 0;
+    var symbolCodeLength = (0, _util.log2)(symbols.length + numberOfNewSymbols);
+    var decoder = decodingContext.decoder;
+    var contextCache = decodingContext.contextCache;
+    var tableB1, symbolWidths;
+
+    if (huffman) {
+      tableB1 = getStandardTable(1);
+      symbolWidths = [];
+      symbolCodeLength = Math.max(symbolCodeLength, 1);
+    }
+
+    while (newSymbols.length < numberOfNewSymbols) {
+      var deltaHeight = huffman ? huffmanTables.tableDeltaHeight.decode(huffmanInput) : decodeInteger(contextCache, 'IADH', decoder);
+      currentHeight += deltaHeight;
+      var currentWidth = 0,
+          totalWidth = 0;
+      var firstSymbol = huffman ? symbolWidths.length : 0;
+
+      while (true) {
+        var deltaWidth = huffman ? huffmanTables.tableDeltaWidth.decode(huffmanInput) : decodeInteger(contextCache, 'IADW', decoder);
+
+        if (deltaWidth === null) {
+          break;
+        }
+
+        currentWidth += deltaWidth;
+        totalWidth += currentWidth;
+        var bitmap;
+
+        if (refinement) {
+          var numberOfInstances = decodeInteger(contextCache, 'IAAI', decoder);
+
+          if (numberOfInstances > 1) {
+            bitmap = decodeTextRegion(huffman, refinement, currentWidth, currentHeight, 0, numberOfInstances, 1, symbols.concat(newSymbols), symbolCodeLength, 0, 0, 1, 0, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, 0, huffmanInput);
+          } else {
+            var symbolId = decodeIAID(contextCache, decoder, symbolCodeLength);
+            var rdx = decodeInteger(contextCache, 'IARDX', decoder);
+            var rdy = decodeInteger(contextCache, 'IARDY', decoder);
+            var symbol = symbolId < symbols.length ? symbols[symbolId] : newSymbols[symbolId - symbols.length];
+            bitmap = decodeRefinement(currentWidth, currentHeight, refinementTemplateIndex, symbol, rdx, rdy, false, refinementAt, decodingContext);
+          }
+
+          newSymbols.push(bitmap);
+        } else if (huffman) {
+          symbolWidths.push(currentWidth);
+        } else {
+          bitmap = decodeBitmap(false, currentWidth, currentHeight, templateIndex, false, null, at, decodingContext);
+          newSymbols.push(bitmap);
+        }
+      }
+
+      if (huffman && !refinement) {
+        var bitmapSize = huffmanTables.tableBitmapSize.decode(huffmanInput);
+        huffmanInput.byteAlign();
+        var collectiveBitmap = void 0;
+
+        if (bitmapSize === 0) {
+          collectiveBitmap = readUncompressedBitmap(huffmanInput, totalWidth, currentHeight);
+        } else {
+          var originalEnd = huffmanInput.end;
+          var bitmapEnd = huffmanInput.position + bitmapSize;
+          huffmanInput.end = bitmapEnd;
+          collectiveBitmap = decodeMMRBitmap(huffmanInput, totalWidth, currentHeight, false);
+          huffmanInput.end = originalEnd;
+          huffmanInput.position = bitmapEnd;
+        }
+
+        var numberOfSymbolsDecoded = symbolWidths.length;
+
+        if (firstSymbol === numberOfSymbolsDecoded - 1) {
+          newSymbols.push(collectiveBitmap);
+        } else {
+          var _i = void 0,
+              y = void 0,
+              xMin = 0,
+              xMax = void 0,
+              bitmapWidth = void 0,
+              symbolBitmap = void 0;
+
+          for (_i = firstSymbol; _i < numberOfSymbolsDecoded; _i++) {
+            bitmapWidth = symbolWidths[_i];
+            xMax = xMin + bitmapWidth;
+            symbolBitmap = [];
+
+            for (y = 0; y < currentHeight; y++) {
+              symbolBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
+            }
+
+            newSymbols.push(symbolBitmap);
+            xMin = xMax;
+          }
+        }
+      }
+    }
+
+    var exportedSymbols = [];
+    var flags = [],
+        currentFlag = false;
+    var totalSymbolsLength = symbols.length + numberOfNewSymbols;
+
+    while (flags.length < totalSymbolsLength) {
+      var runLength = huffman ? tableB1.decode(huffmanInput) : decodeInteger(contextCache, 'IAEX', decoder);
+
+      while (runLength--) {
+        flags.push(currentFlag);
+      }
+
+      currentFlag = !currentFlag;
+    }
+
+    for (var i = 0, ii = symbols.length; i < ii; i++) {
+      if (flags[i]) {
+        exportedSymbols.push(symbols[i]);
+      }
+    }
+
+    for (var j = 0; j < numberOfNewSymbols; i++, j++) {
+      if (flags[i]) {
+        exportedSymbols.push(newSymbols[j]);
+      }
+    }
+
+    return exportedSymbols;
+  }
+
+  function decodeTextRegion(huffman, refinement, width, height, defaultPixelValue, numberOfSymbolInstances, stripSize, inputSymbols, symbolCodeLength, transposed, dsOffset, referenceCorner, combinationOperator, huffmanTables, refinementTemplateIndex, refinementAt, decodingContext, logStripSize, huffmanInput) {
+    if (huffman && refinement) {
+      throw new Jbig2Error('refinement with Huffman is not supported');
+    }
+
+    var bitmap = [];
+    var i, row;
+
+    for (i = 0; i < height; i++) {
+      row = new Uint8Array(width);
+
+      if (defaultPixelValue) {
+        for (var j = 0; j < width; j++) {
+          row[j] = defaultPixelValue;
+        }
+      }
+
+      bitmap.push(row);
+    }
+
+    var decoder = decodingContext.decoder;
+    var contextCache = decodingContext.contextCache;
+    var stripT = huffman ? -huffmanTables.tableDeltaT.decode(huffmanInput) : -decodeInteger(contextCache, 'IADT', decoder);
+    var firstS = 0;
+    i = 0;
+
+    while (i < numberOfSymbolInstances) {
+      var deltaT = huffman ? huffmanTables.tableDeltaT.decode(huffmanInput) : decodeInteger(contextCache, 'IADT', decoder);
+      stripT += deltaT;
+      var deltaFirstS = huffman ? huffmanTables.tableFirstS.decode(huffmanInput) : decodeInteger(contextCache, 'IAFS', decoder);
+      firstS += deltaFirstS;
+      var currentS = firstS;
+
+      do {
+        var currentT = 0;
+
+        if (stripSize > 1) {
+          currentT = huffman ? huffmanInput.readBits(logStripSize) : decodeInteger(contextCache, 'IAIT', decoder);
+        }
+
+        var t = stripSize * stripT + currentT;
+        var symbolId = huffman ? huffmanTables.symbolIDTable.decode(huffmanInput) : decodeIAID(contextCache, decoder, symbolCodeLength);
+        var applyRefinement = refinement && (huffman ? huffmanInput.readBit() : decodeInteger(contextCache, 'IARI', decoder));
+        var symbolBitmap = inputSymbols[symbolId];
+        var symbolWidth = symbolBitmap[0].length;
+        var symbolHeight = symbolBitmap.length;
+
+        if (applyRefinement) {
+          var rdw = decodeInteger(contextCache, 'IARDW', decoder);
+          var rdh = decodeInteger(contextCache, 'IARDH', decoder);
+          var rdx = decodeInteger(contextCache, 'IARDX', decoder);
+          var rdy = decodeInteger(contextCache, 'IARDY', decoder);
+          symbolWidth += rdw;
+          symbolHeight += rdh;
+          symbolBitmap = decodeRefinement(symbolWidth, symbolHeight, refinementTemplateIndex, symbolBitmap, (rdw >> 1) + rdx, (rdh >> 1) + rdy, false, refinementAt, decodingContext);
+        }
+
+        var offsetT = t - (referenceCorner & 1 ? 0 : symbolHeight - 1);
+        var offsetS = currentS - (referenceCorner & 2 ? symbolWidth - 1 : 0);
+        var s2, t2, symbolRow;
+
+        if (transposed) {
+          for (s2 = 0; s2 < symbolHeight; s2++) {
+            row = bitmap[offsetS + s2];
+
+            if (!row) {
+              continue;
+            }
+
+            symbolRow = symbolBitmap[s2];
+            var maxWidth = Math.min(width - offsetT, symbolWidth);
+
+            switch (combinationOperator) {
+              case 0:
+                for (t2 = 0; t2 < maxWidth; t2++) {
+                  row[offsetT + t2] |= symbolRow[t2];
+                }
+
+                break;
+
+              case 2:
+                for (t2 = 0; t2 < maxWidth; t2++) {
+                  row[offsetT + t2] ^= symbolRow[t2];
+                }
+
+                break;
+
+              default:
+                throw new Jbig2Error("operator ".concat(combinationOperator, " is not supported"));
+            }
+          }
+
+          currentS += symbolHeight - 1;
+        } else {
+          for (t2 = 0; t2 < symbolHeight; t2++) {
+            row = bitmap[offsetT + t2];
+
+            if (!row) {
+              continue;
+            }
+
+            symbolRow = symbolBitmap[t2];
+
+            switch (combinationOperator) {
+              case 0:
+                for (s2 = 0; s2 < symbolWidth; s2++) {
+                  row[offsetS + s2] |= symbolRow[s2];
+                }
+
+                break;
+
+              case 2:
+                for (s2 = 0; s2 < symbolWidth; s2++) {
+                  row[offsetS + s2] ^= symbolRow[s2];
+                }
+
+                break;
+
+              default:
+                throw new Jbig2Error("operator ".concat(combinationOperator, " is not supported"));
+            }
+          }
+
+          currentS += symbolWidth - 1;
+        }
+
+        i++;
+        var deltaS = huffman ? huffmanTables.tableDeltaS.decode(huffmanInput) : decodeInteger(contextCache, 'IADS', decoder);
+
+        if (deltaS === null) {
+          break;
+        }
+
+        currentS += deltaS + dsOffset;
+      } while (true);
+    }
+
+    return bitmap;
+  }
+
+  function decodePatternDictionary(mmr, patternWidth, patternHeight, maxPatternIndex, template, decodingContext) {
+    var at = [];
+
+    if (!mmr) {
+      at.push({
+        x: -patternWidth,
+        y: 0
+      });
+
+      if (template === 0) {
+        at.push({
+          x: -3,
+          y: -1
+        });
+        at.push({
+          x: 2,
+          y: -2
+        });
+        at.push({
+          x: -2,
+          y: -2
+        });
+      }
+    }
+
+    var collectiveWidth = (maxPatternIndex + 1) * patternWidth;
+    var collectiveBitmap = decodeBitmap(mmr, collectiveWidth, patternHeight, template, false, null, at, decodingContext);
+    var patterns = [],
+        i = 0,
+        patternBitmap,
+        xMin,
+        xMax,
+        y;
+
+    while (i <= maxPatternIndex) {
+      patternBitmap = [];
+      xMin = patternWidth * i;
+      xMax = xMin + patternWidth;
+
+      for (y = 0; y < patternHeight; y++) {
+        patternBitmap.push(collectiveBitmap[y].subarray(xMin, xMax));
+      }
+
+      patterns.push(patternBitmap);
+      i++;
+    }
+
+    return patterns;
+  }
+
+  function decodeHalftoneRegion(mmr, patterns, template, regionWidth, regionHeight, defaultPixelValue, enableSkip, combinationOperator, gridWidth, gridHeight, gridOffsetX, gridOffsetY, gridVectorX, gridVectorY, decodingContext) {
+    var skip = null;
+
+    if (enableSkip) {
+      throw new Jbig2Error('skip is not supported');
+    }
+
+    if (combinationOperator !== 0) {
+      throw new Jbig2Error('operator ' + combinationOperator + ' is not supported in halftone region');
+    }
+
+    var regionBitmap = [];
+    var i, j, row;
+
+    for (i = 0; i < regionHeight; i++) {
+      row = new Uint8Array(regionWidth);
+
+      if (defaultPixelValue) {
+        for (j = 0; j < regionWidth; j++) {
+          row[j] = defaultPixelValue;
+        }
+      }
+
+      regionBitmap.push(row);
+    }
+
+    var numberOfPatterns = patterns.length;
+    var pattern0 = patterns[0];
+    var patternWidth = pattern0[0].length,
+        patternHeight = pattern0.length;
+    var bitsPerValue = (0, _util.log2)(numberOfPatterns);
+    var at = [];
+
+    if (!mmr) {
+      at.push({
+        x: template <= 1 ? 3 : 2,
+        y: -1
+      });
+
+      if (template === 0) {
+        at.push({
+          x: -3,
+          y: -1
+        });
+        at.push({
+          x: 2,
+          y: -2
+        });
+        at.push({
+          x: -2,
+          y: -2
+        });
+      }
+    }
+
+    var grayScaleBitPlanes = [],
+        mmrInput,
+        bitmap;
+
+    if (mmr) {
+      mmrInput = new Reader(decodingContext.data, decodingContext.start, decodingContext.end);
+    }
+
+    for (i = bitsPerValue - 1; i >= 0; i--) {
+      if (mmr) {
+        bitmap = decodeMMRBitmap(mmrInput, gridWidth, gridHeight, true);
+      } else {
+        bitmap = decodeBitmap(false, gridWidth, gridHeight, template, false, skip, at, decodingContext);
+      }
+
+      grayScaleBitPlanes[i] = bitmap;
+    }
+
+    var mg, ng, bit, patternIndex, patternBitmap, x, y, patternRow, regionRow;
+
+    for (mg = 0; mg < gridHeight; mg++) {
+      for (ng = 0; ng < gridWidth; ng++) {
+        bit = 0;
+        patternIndex = 0;
+
+        for (j = bitsPerValue - 1; j >= 0; j--) {
+          bit = grayScaleBitPlanes[j][mg][ng] ^ bit;
+          patternIndex |= bit << j;
+        }
+
+        patternBitmap = patterns[patternIndex];
+        x = gridOffsetX + mg * gridVectorY + ng * gridVectorX >> 8;
+        y = gridOffsetY + mg * gridVectorX - ng * gridVectorY >> 8;
+
+        if (x >= 0 && x + patternWidth <= regionWidth && y >= 0 && y + patternHeight <= regionHeight) {
+          for (i = 0; i < patternHeight; i++) {
+            regionRow = regionBitmap[y + i];
+            patternRow = patternBitmap[i];
+
+            for (j = 0; j < patternWidth; j++) {
+              regionRow[x + j] |= patternRow[j];
+            }
+          }
+        } else {
+          var regionX = void 0,
+              regionY = void 0;
+
+          for (i = 0; i < patternHeight; i++) {
+            regionY = y + i;
+
+            if (regionY < 0 || regionY >= regionHeight) {
+              continue;
+            }
+
+            regionRow = regionBitmap[regionY];
+            patternRow = patternBitmap[i];
+
+            for (j = 0; j < patternWidth; j++) {
+              regionX = x + j;
+
+              if (regionX >= 0 && regionX < regionWidth) {
+                regionRow[regionX] |= patternRow[j];
+              }
+            }
+          }
+        }
+      }
+    }
+
+    return regionBitmap;
+  }
+
+  function readSegmentHeader(data, start) {
+    var segmentHeader = {};
+    segmentHeader.number = (0, _util.readUint32)(data, start);
+    var flags = data[start + 4];
+    var segmentType = flags & 0x3F;
+
+    if (!SegmentTypes[segmentType]) {
+      throw new Jbig2Error('invalid segment type: ' + segmentType);
+    }
+
+    segmentHeader.type = segmentType;
+    segmentHeader.typeName = SegmentTypes[segmentType];
+    segmentHeader.deferredNonRetain = !!(flags & 0x80);
+    var pageAssociationFieldSize = !!(flags & 0x40);
+    var referredFlags = data[start + 5];
+    var referredToCount = referredFlags >> 5 & 7;
+    var retainBits = [referredFlags & 31];
+    var position = start + 6;
+
+    if (referredFlags === 7) {
+      referredToCount = (0, _util.readUint32)(data, position - 1) & 0x1FFFFFFF;
+      position += 3;
+      var bytes = referredToCount + 7 >> 3;
+      retainBits[0] = data[position++];
+
+      while (--bytes > 0) {
+        retainBits.push(data[position++]);
+      }
+    } else if (referredFlags === 5 || referredFlags === 6) {
+      throw new Jbig2Error('invalid referred-to flags');
+    }
+
+    segmentHeader.retainBits = retainBits;
+    var referredToSegmentNumberSize = segmentHeader.number <= 256 ? 1 : segmentHeader.number <= 65536 ? 2 : 4;
+    var referredTo = [];
+    var i, ii;
+
+    for (i = 0; i < referredToCount; i++) {
+      var number = referredToSegmentNumberSize === 1 ? data[position] : referredToSegmentNumberSize === 2 ? (0, _util.readUint16)(data, position) : (0, _util.readUint32)(data, position);
+      referredTo.push(number);
+      position += referredToSegmentNumberSize;
+    }
+
+    segmentHeader.referredTo = referredTo;
+
+    if (!pageAssociationFieldSize) {
+      segmentHeader.pageAssociation = data[position++];
+    } else {
+      segmentHeader.pageAssociation = (0, _util.readUint32)(data, position);
+      position += 4;
+    }
+
+    segmentHeader.length = (0, _util.readUint32)(data, position);
+    position += 4;
+
+    if (segmentHeader.length === 0xFFFFFFFF) {
+      if (segmentType === 38) {
+        var genericRegionInfo = readRegionSegmentInformation(data, position);
+        var genericRegionSegmentFlags = data[position + RegionSegmentInformationFieldLength];
+        var genericRegionMmr = !!(genericRegionSegmentFlags & 1);
+        var searchPatternLength = 6;
+        var searchPattern = new Uint8Array(searchPatternLength);
+
+        if (!genericRegionMmr) {
+          searchPattern[0] = 0xFF;
+          searchPattern[1] = 0xAC;
+        }
+
+        searchPattern[2] = genericRegionInfo.height >>> 24 & 0xFF;
+        searchPattern[3] = genericRegionInfo.height >> 16 & 0xFF;
+        searchPattern[4] = genericRegionInfo.height >> 8 & 0xFF;
+        searchPattern[5] = genericRegionInfo.height & 0xFF;
+
+        for (i = position, ii = data.length; i < ii; i++) {
+          var j = 0;
+
+          while (j < searchPatternLength && searchPattern[j] === data[i + j]) {
+            j++;
+          }
+
+          if (j === searchPatternLength) {
+            segmentHeader.length = i + searchPatternLength;
+            break;
+          }
+        }
+
+        if (segmentHeader.length === 0xFFFFFFFF) {
+          throw new Jbig2Error('segment end was not found');
+        }
+      } else {
+        throw new Jbig2Error('invalid unknown segment length');
+      }
+    }
+
+    segmentHeader.headerEnd = position;
+    return segmentHeader;
+  }
+
+  function readSegments(header, data, start, end) {
+    var segments = [];
+    var position = start;
+
+    while (position < end) {
+      var segmentHeader = readSegmentHeader(data, position);
+      position = segmentHeader.headerEnd;
+      var segment = {
+        header: segmentHeader,
+        data: data
+      };
+
+      if (!header.randomAccess) {
+        segment.start = position;
+        position += segmentHeader.length;
+        segment.end = position;
+      }
+
+      segments.push(segment);
+
+      if (segmentHeader.type === 51) {
+        break;
+      }
+    }
+
+    if (header.randomAccess) {
+      for (var i = 0, ii = segments.length; i < ii; i++) {
+        segments[i].start = position;
+        position += segments[i].header.length;
+        segments[i].end = position;
+      }
+    }
+
+    return segments;
+  }
+
+  function readRegionSegmentInformation(data, start) {
+    return {
+      width: (0, _util.readUint32)(data, start),
+      height: (0, _util.readUint32)(data, start + 4),
+      x: (0, _util.readUint32)(data, start + 8),
+      y: (0, _util.readUint32)(data, start + 12),
+      combinationOperator: data[start + 16] & 7
+    };
+  }
+
+  var RegionSegmentInformationFieldLength = 17;
+
+  function processSegment(segment, visitor) {
+    var header = segment.header;
+    var data = segment.data,
+        position = segment.start,
+        end = segment.end;
+    var args, at, i, atLength;
+
+    switch (header.type) {
+      case 0:
+        var dictionary = {};
+        var dictionaryFlags = (0, _util.readUint16)(data, position);
+        dictionary.huffman = !!(dictionaryFlags & 1);
+        dictionary.refinement = !!(dictionaryFlags & 2);
+        dictionary.huffmanDHSelector = dictionaryFlags >> 2 & 3;
+        dictionary.huffmanDWSelector = dictionaryFlags >> 4 & 3;
+        dictionary.bitmapSizeSelector = dictionaryFlags >> 6 & 1;
+        dictionary.aggregationInstancesSelector = dictionaryFlags >> 7 & 1;
+        dictionary.bitmapCodingContextUsed = !!(dictionaryFlags & 256);
+        dictionary.bitmapCodingContextRetained = !!(dictionaryFlags & 512);
+        dictionary.template = dictionaryFlags >> 10 & 3;
+        dictionary.refinementTemplate = dictionaryFlags >> 12 & 1;
+        position += 2;
+
+        if (!dictionary.huffman) {
+          atLength = dictionary.template === 0 ? 4 : 1;
+          at = [];
+
+          for (i = 0; i < atLength; i++) {
+            at.push({
+              x: (0, _util.readInt8)(data, position),
+              y: (0, _util.readInt8)(data, position + 1)
+            });
+            position += 2;
+          }
+
+          dictionary.at = at;
+        }
+
+        if (dictionary.refinement && !dictionary.refinementTemplate) {
+          at = [];
+
+          for (i = 0; i < 2; i++) {
+            at.push({
+              x: (0, _util.readInt8)(data, position),
+              y: (0, _util.readInt8)(data, position + 1)
+            });
+            position += 2;
+          }
+
+          dictionary.refinementAt = at;
+        }
+
+        dictionary.numberOfExportedSymbols = (0, _util.readUint32)(data, position);
+        position += 4;
+        dictionary.numberOfNewSymbols = (0, _util.readUint32)(data, position);
+        position += 4;
+        args = [dictionary, header.number, header.referredTo, data, position, end];
+        break;
+
+      case 6:
+      case 7:
+        var textRegion = {};
+        textRegion.info = readRegionSegmentInformation(data, position);
+        position += RegionSegmentInformationFieldLength;
+        var textRegionSegmentFlags = (0, _util.readUint16)(data, position);
+        position += 2;
+        textRegion.huffman = !!(textRegionSegmentFlags & 1);
+        textRegion.refinement = !!(textRegionSegmentFlags & 2);
+        textRegion.logStripSize = textRegionSegmentFlags >> 2 & 3;
+        textRegion.stripSize = 1 << textRegion.logStripSize;
+        textRegion.referenceCorner = textRegionSegmentFlags >> 4 & 3;
+        textRegion.transposed = !!(textRegionSegmentFlags & 64);
+        textRegion.combinationOperator = textRegionSegmentFlags >> 7 & 3;
+        textRegion.defaultPixelValue = textRegionSegmentFlags >> 9 & 1;
+        textRegion.dsOffset = textRegionSegmentFlags << 17 >> 27;
+        textRegion.refinementTemplate = textRegionSegmentFlags >> 15 & 1;
+
+        if (textRegion.huffman) {
+          var textRegionHuffmanFlags = (0, _util.readUint16)(data, position);
+          position += 2;
+          textRegion.huffmanFS = textRegionHuffmanFlags & 3;
+          textRegion.huffmanDS = textRegionHuffmanFlags >> 2 & 3;
+          textRegion.huffmanDT = textRegionHuffmanFlags >> 4 & 3;
+          textRegion.huffmanRefinementDW = textRegionHuffmanFlags >> 6 & 3;
+          textRegion.huffmanRefinementDH = textRegionHuffmanFlags >> 8 & 3;
+          textRegion.huffmanRefinementDX = textRegionHuffmanFlags >> 10 & 3;
+          textRegion.huffmanRefinementDY = textRegionHuffmanFlags >> 12 & 3;
+          textRegion.huffmanRefinementSizeSelector = !!(textRegionHuffmanFlags & 0x4000);
+        }
+
+        if (textRegion.refinement && !textRegion.refinementTemplate) {
+          at = [];
+
+          for (i = 0; i < 2; i++) {
+            at.push({
+              x: (0, _util.readInt8)(data, position),
+              y: (0, _util.readInt8)(data, position + 1)
+            });
+            position += 2;
+          }
+
+          textRegion.refinementAt = at;
+        }
+
+        textRegion.numberOfSymbolInstances = (0, _util.readUint32)(data, position);
+        position += 4;
+        args = [textRegion, header.referredTo, data, position, end];
+        break;
+
+      case 16:
+        var patternDictionary = {};
+        var patternDictionaryFlags = data[position++];
+        patternDictionary.mmr = !!(patternDictionaryFlags & 1);
+        patternDictionary.template = patternDictionaryFlags >> 1 & 3;
+        patternDictionary.patternWidth = data[position++];
+        patternDictionary.patternHeight = data[position++];
+        patternDictionary.maxPatternIndex = (0, _util.readUint32)(data, position);
+        position += 4;
+        args = [patternDictionary, header.number, data, position, end];
+        break;
+
+      case 22:
+      case 23:
+        var halftoneRegion = {};
+        halftoneRegion.info = readRegionSegmentInformation(data, position);
+        position += RegionSegmentInformationFieldLength;
+        var halftoneRegionFlags = data[position++];
+        halftoneRegion.mmr = !!(halftoneRegionFlags & 1);
+        halftoneRegion.template = halftoneRegionFlags >> 1 & 3;
+        halftoneRegion.enableSkip = !!(halftoneRegionFlags & 8);
+        halftoneRegion.combinationOperator = halftoneRegionFlags >> 4 & 7;
+        halftoneRegion.defaultPixelValue = halftoneRegionFlags >> 7 & 1;
+        halftoneRegion.gridWidth = (0, _util.readUint32)(data, position);
+        position += 4;
+        halftoneRegion.gridHeight = (0, _util.readUint32)(data, position);
+        position += 4;
+        halftoneRegion.gridOffsetX = (0, _util.readUint32)(data, position) & 0xFFFFFFFF;
+        position += 4;
+        halftoneRegion.gridOffsetY = (0, _util.readUint32)(data, position) & 0xFFFFFFFF;
+        position += 4;
+        halftoneRegion.gridVectorX = (0, _util.readUint16)(data, position);
+        position += 2;
+        halftoneRegion.gridVectorY = (0, _util.readUint16)(data, position);
+        position += 2;
+        args = [halftoneRegion, header.referredTo, data, position, end];
+        break;
+
+      case 38:
+      case 39:
+        var genericRegion = {};
+        genericRegion.info = readRegionSegmentInformation(data, position);
+        position += RegionSegmentInformationFieldLength;
+        var genericRegionSegmentFlags = data[position++];
+        genericRegion.mmr = !!(genericRegionSegmentFlags & 1);
+        genericRegion.template = genericRegionSegmentFlags >> 1 & 3;
+        genericRegion.prediction = !!(genericRegionSegmentFlags & 8);
+
+        if (!genericRegion.mmr) {
+          atLength = genericRegion.template === 0 ? 4 : 1;
+          at = [];
+
+          for (i = 0; i < atLength; i++) {
+            at.push({
+              x: (0, _util.readInt8)(data, position),
+              y: (0, _util.readInt8)(data, position + 1)
+            });
+            position += 2;
+          }
+
+          genericRegion.at = at;
+        }
+
+        args = [genericRegion, data, position, end];
+        break;
+
+      case 48:
+        var pageInfo = {
+          width: (0, _util.readUint32)(data, position),
+          height: (0, _util.readUint32)(data, position + 4),
+          resolutionX: (0, _util.readUint32)(data, position + 8),
+          resolutionY: (0, _util.readUint32)(data, position + 12)
+        };
+
+        if (pageInfo.height === 0xFFFFFFFF) {
+          delete pageInfo.height;
+        }
+
+        var pageSegmentFlags = data[position + 16];
+        (0, _util.readUint16)(data, position + 17);
+        pageInfo.lossless = !!(pageSegmentFlags & 1);
+        pageInfo.refinement = !!(pageSegmentFlags & 2);
+        pageInfo.defaultPixelValue = pageSegmentFlags >> 2 & 1;
+        pageInfo.combinationOperator = pageSegmentFlags >> 3 & 3;
+        pageInfo.requiresBuffer = !!(pageSegmentFlags & 32);
+        pageInfo.combinationOperatorOverride = !!(pageSegmentFlags & 64);
+        args = [pageInfo];
+        break;
+
+      case 49:
+        break;
+
+      case 50:
+        break;
+
+      case 51:
+        break;
+
+      case 53:
+        args = [header.number, data, position, end];
+        break;
+
+      case 62:
+        break;
+
+      default:
+        throw new Jbig2Error("segment type ".concat(header.typeName, "(").concat(header.type, ")") + ' is not implemented');
+    }
+
+    var callbackName = 'on' + header.typeName;
+
+    if (callbackName in visitor) {
+      visitor[callbackName].apply(visitor, args);
+    }
+  }
+
+  function processSegments(segments, visitor) {
+    for (var i = 0, ii = segments.length; i < ii; i++) {
+      processSegment(segments[i], visitor);
+    }
+  }
+
+  function parseJbig2Chunks(chunks) {
+    var visitor = new SimpleSegmentVisitor();
+
+    for (var i = 0, ii = chunks.length; i < ii; i++) {
+      var chunk = chunks[i];
+      var segments = readSegments({}, chunk.data, chunk.start, chunk.end);
+      processSegments(segments, visitor);
+    }
+
+    return visitor.buffer;
+  }
+
+  function parseJbig2(data) {
+    var position = 0,
+        end = data.length;
+
+    if (data[position] !== 0x97 || data[position + 1] !== 0x4A || data[position + 2] !== 0x42 || data[position + 3] !== 0x32 || data[position + 4] !== 0x0D || data[position + 5] !== 0x0A || data[position + 6] !== 0x1A || data[position + 7] !== 0x0A) {
+      throw new Jbig2Error('parseJbig2 - invalid header.');
+    }
+
+    var header = Object.create(null);
+    position += 8;
+    var flags = data[position++];
+    header.randomAccess = !(flags & 1);
+
+    if (!(flags & 2)) {
+      header.numberOfPages = (0, _util.readUint32)(data, position);
+      position += 4;
+    }
+
+    var segments = readSegments(header, data, position, end);
+    var visitor = new SimpleSegmentVisitor();
+    processSegments(segments, visitor);
+    var _visitor$currentPageI = visitor.currentPageInfo,
+        width = _visitor$currentPageI.width,
+        height = _visitor$currentPageI.height;
+    var bitPacked = visitor.buffer;
+    var imgData = new Uint8ClampedArray(width * height);
+    var q = 0,
+        k = 0;
+
+    for (var i = 0; i < height; i++) {
+      var mask = 0,
+          buffer = void 0;
+
+      for (var j = 0; j < width; j++) {
+        if (!mask) {
+          mask = 128;
+          buffer = bitPacked[k++];
+        }
+
+        imgData[q++] = buffer & mask ? 0 : 255;
+        mask >>= 1;
+      }
+    }
+
+    return {
+      imgData: imgData,
+      width: width,
+      height: height
+    };
+  }
+
+  function SimpleSegmentVisitor() {}
+
+  SimpleSegmentVisitor.prototype = {
+    onPageInformation: function SimpleSegmentVisitor_onPageInformation(info) {
+      this.currentPageInfo = info;
+      var rowSize = info.width + 7 >> 3;
+      var buffer = new Uint8ClampedArray(rowSize * info.height);
+
+      if (info.defaultPixelValue) {
+        for (var i = 0, ii = buffer.length; i < ii; i++) {
+          buffer[i] = 0xFF;
+        }
+      }
+
+      this.buffer = buffer;
+    },
+    drawBitmap: function SimpleSegmentVisitor_drawBitmap(regionInfo, bitmap) {
+      var pageInfo = this.currentPageInfo;
+      var width = regionInfo.width,
+          height = regionInfo.height;
+      var rowSize = pageInfo.width + 7 >> 3;
+      var combinationOperator = pageInfo.combinationOperatorOverride ? regionInfo.combinationOperator : pageInfo.combinationOperator;
+      var buffer = this.buffer;
+      var mask0 = 128 >> (regionInfo.x & 7);
+      var offset0 = regionInfo.y * rowSize + (regionInfo.x >> 3);
+      var i, j, mask, offset;
+
+      switch (combinationOperator) {
+        case 0:
+          for (i = 0; i < height; i++) {
+            mask = mask0;
+            offset = offset0;
+
+            for (j = 0; j < width; j++) {
+              if (bitmap[i][j]) {
+                buffer[offset] |= mask;
+              }
+
+              mask >>= 1;
+
+              if (!mask) {
+                mask = 128;
+                offset++;
+              }
+            }
+
+            offset0 += rowSize;
+          }
+
+          break;
+
+        case 2:
+          for (i = 0; i < height; i++) {
+            mask = mask0;
+            offset = offset0;
+
+            for (j = 0; j < width; j++) {
+              if (bitmap[i][j]) {
+                buffer[offset] ^= mask;
+              }
+
+              mask >>= 1;
+
+              if (!mask) {
+                mask = 128;
+                offset++;
+              }
+            }
+
+            offset0 += rowSize;
+          }
+
+          break;
+
+        default:
+          throw new Jbig2Error("operator ".concat(combinationOperator, " is not supported"));
+      }
+    },
+    onImmediateGenericRegion: function SimpleSegmentVisitor_onImmediateGenericRegion(region, data, start, end) {
+      var regionInfo = region.info;
+      var decodingContext = new DecodingContext(data, start, end);
+      var bitmap = decodeBitmap(region.mmr, regionInfo.width, regionInfo.height, region.template, region.prediction, null, region.at, decodingContext);
+      this.drawBitmap(regionInfo, bitmap);
+    },
+    onImmediateLosslessGenericRegion: function SimpleSegmentVisitor_onImmediateLosslessGenericRegion() {
+      this.onImmediateGenericRegion.apply(this, arguments);
+    },
+    onSymbolDictionary: function SimpleSegmentVisitor_onSymbolDictionary(dictionary, currentSegment, referredSegments, data, start, end) {
+      var huffmanTables, huffmanInput;
+
+      if (dictionary.huffman) {
+        huffmanTables = getSymbolDictionaryHuffmanTables(dictionary, referredSegments, this.customTables);
+        huffmanInput = new Reader(data, start, end);
+      }
+
+      var symbols = this.symbols;
+
+      if (!symbols) {
+        this.symbols = symbols = {};
+      }
+
+      var inputSymbols = [];
+
+      for (var i = 0, ii = referredSegments.length; i < ii; i++) {
+        var referredSymbols = symbols[referredSegments[i]];
+
+        if (referredSymbols) {
+          inputSymbols = inputSymbols.concat(referredSymbols);
+        }
+      }
+
+      var decodingContext = new DecodingContext(data, start, end);
+      symbols[currentSegment] = decodeSymbolDictionary(dictionary.huffman, dictionary.refinement, inputSymbols, dictionary.numberOfNewSymbols, dictionary.numberOfExportedSymbols, huffmanTables, dictionary.template, dictionary.at, dictionary.refinementTemplate, dictionary.refinementAt, decodingContext, huffmanInput);
+    },
+    onImmediateTextRegion: function SimpleSegmentVisitor_onImmediateTextRegion(region, referredSegments, data, start, end) {
+      var regionInfo = region.info;
+      var huffmanTables, huffmanInput;
+      var symbols = this.symbols;
+      var inputSymbols = [];
+
+      for (var i = 0, ii = referredSegments.length; i < ii; i++) {
+        var referredSymbols = symbols[referredSegments[i]];
+
+        if (referredSymbols) {
+          inputSymbols = inputSymbols.concat(referredSymbols);
+        }
+      }
+
+      var symbolCodeLength = (0, _util.log2)(inputSymbols.length);
+
+      if (region.huffman) {
+        huffmanInput = new Reader(data, start, end);
+        huffmanTables = getTextRegionHuffmanTables(region, referredSegments, this.customTables, inputSymbols.length, huffmanInput);
+      }
+
+      var decodingContext = new DecodingContext(data, start, end);
+      var bitmap = decodeTextRegion(region.huffman, region.refinement, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.numberOfSymbolInstances, region.stripSize, inputSymbols, symbolCodeLength, region.transposed, region.dsOffset, region.referenceCorner, region.combinationOperator, huffmanTables, region.refinementTemplate, region.refinementAt, decodingContext, region.logStripSize, huffmanInput);
+      this.drawBitmap(regionInfo, bitmap);
+    },
+    onImmediateLosslessTextRegion: function SimpleSegmentVisitor_onImmediateLosslessTextRegion() {
+      this.onImmediateTextRegion.apply(this, arguments);
+    },
+    onPatternDictionary: function onPatternDictionary(dictionary, currentSegment, data, start, end) {
+      var patterns = this.patterns;
+
+      if (!patterns) {
+        this.patterns = patterns = {};
+      }
+
+      var decodingContext = new DecodingContext(data, start, end);
+      patterns[currentSegment] = decodePatternDictionary(dictionary.mmr, dictionary.patternWidth, dictionary.patternHeight, dictionary.maxPatternIndex, dictionary.template, decodingContext);
+    },
+    onImmediateHalftoneRegion: function onImmediateHalftoneRegion(region, referredSegments, data, start, end) {
+      var patterns = this.patterns[referredSegments[0]];
+      var regionInfo = region.info;
+      var decodingContext = new DecodingContext(data, start, end);
+      var bitmap = decodeHalftoneRegion(region.mmr, patterns, region.template, regionInfo.width, regionInfo.height, region.defaultPixelValue, region.enableSkip, region.combinationOperator, region.gridWidth, region.gridHeight, region.gridOffsetX, region.gridOffsetY, region.gridVectorX, region.gridVectorY, decodingContext);
+      this.drawBitmap(regionInfo, bitmap);
+    },
+    onImmediateLosslessHalftoneRegion: function onImmediateLosslessHalftoneRegion() {
+      this.onImmediateHalftoneRegion.apply(this, arguments);
+    },
+    onTables: function onTables(currentSegment, data, start, end) {
+      var customTables = this.customTables;
+
+      if (!customTables) {
+        this.customTables = customTables = {};
+      }
+
+      customTables[currentSegment] = decodeTablesSegment(data, start, end);
+    }
+  };
+
+  function HuffmanLine(lineData) {
+    if (lineData.length === 2) {
+      this.isOOB = true;
+      this.rangeLow = 0;
+      this.prefixLength = lineData[0];
+      this.rangeLength = 0;
+      this.prefixCode = lineData[1];
+      this.isLowerRange = false;
+    } else {
+      this.isOOB = false;
+      this.rangeLow = lineData[0];
+      this.prefixLength = lineData[1];
+      this.rangeLength = lineData[2];
+      this.prefixCode = lineData[3];
+      this.isLowerRange = lineData[4] === 'lower';
+    }
+  }
+
+  function HuffmanTreeNode(line) {
+    this.children = [];
+
+    if (line) {
+      this.isLeaf = true;
+      this.rangeLength = line.rangeLength;
+      this.rangeLow = line.rangeLow;
+      this.isLowerRange = line.isLowerRange;
+      this.isOOB = line.isOOB;
+    } else {
+      this.isLeaf = false;
+    }
+  }
+
+  HuffmanTreeNode.prototype = {
+    buildTree: function buildTree(line, shift) {
+      var bit = line.prefixCode >> shift & 1;
+
+      if (shift <= 0) {
+        this.children[bit] = new HuffmanTreeNode(line);
+      } else {
+        var node = this.children[bit];
+
+        if (!node) {
+          this.children[bit] = node = new HuffmanTreeNode(null);
+        }
+
+        node.buildTree(line, shift - 1);
+      }
+    },
+    decodeNode: function decodeNode(reader) {
+      if (this.isLeaf) {
+        if (this.isOOB) {
+          return null;
+        }
+
+        var htOffset = reader.readBits(this.rangeLength);
+        return this.rangeLow + (this.isLowerRange ? -htOffset : htOffset);
+      }
+
+      var node = this.children[reader.readBit()];
+
+      if (!node) {
+        throw new Jbig2Error('invalid Huffman data');
+      }
+
+      return node.decodeNode(reader);
+    }
+  };
+
+  function HuffmanTable(lines, prefixCodesDone) {
+    if (!prefixCodesDone) {
+      this.assignPrefixCodes(lines);
+    }
+
+    this.rootNode = new HuffmanTreeNode(null);
+    var i,
+        ii = lines.length,
+        line;
+
+    for (i = 0; i < ii; i++) {
+      line = lines[i];
+
+      if (line.prefixLength > 0) {
+        this.rootNode.buildTree(line, line.prefixLength - 1);
+      }
+    }
+  }
+
+  HuffmanTable.prototype = {
+    decode: function decode(reader) {
+      return this.rootNode.decodeNode(reader);
+    },
+    assignPrefixCodes: function assignPrefixCodes(lines) {
+      var linesLength = lines.length,
+          prefixLengthMax = 0,
+          i;
+
+      for (i = 0; i < linesLength; i++) {
+        prefixLengthMax = Math.max(prefixLengthMax, lines[i].prefixLength);
+      }
+
+      var histogram = new Uint32Array(prefixLengthMax + 1);
+
+      for (i = 0; i < linesLength; i++) {
+        histogram[lines[i].prefixLength]++;
+      }
+
+      var currentLength = 1,
+          firstCode = 0,
+          currentCode,
+          currentTemp,
+          line;
+      histogram[0] = 0;
+
+      while (currentLength <= prefixLengthMax) {
+        firstCode = firstCode + histogram[currentLength - 1] << 1;
+        currentCode = firstCode;
+        currentTemp = 0;
+
+        while (currentTemp < linesLength) {
+          line = lines[currentTemp];
+
+          if (line.prefixLength === currentLength) {
+            line.prefixCode = currentCode;
+            currentCode++;
+          }
+
+          currentTemp++;
+        }
+
+        currentLength++;
+      }
+    }
+  };
+
+  function decodeTablesSegment(data, start, end) {
+    var flags = data[start];
+    var lowestValue = (0, _util.readUint32)(data, start + 1) & 0xFFFFFFFF;
+    var highestValue = (0, _util.readUint32)(data, start + 5) & 0xFFFFFFFF;
+    var reader = new Reader(data, start + 9, end);
+    var prefixSizeBits = (flags >> 1 & 7) + 1;
+    var rangeSizeBits = (flags >> 4 & 7) + 1;
+    var lines = [];
+    var prefixLength,
+        rangeLength,
+        currentRangeLow = lowestValue;
+
+    do {
+      prefixLength = reader.readBits(prefixSizeBits);
+      rangeLength = reader.readBits(rangeSizeBits);
+      lines.push(new HuffmanLine([currentRangeLow, prefixLength, rangeLength, 0]));
+      currentRangeLow += 1 << rangeLength;
+    } while (currentRangeLow < highestValue);
+
+    prefixLength = reader.readBits(prefixSizeBits);
+    lines.push(new HuffmanLine([lowestValue - 1, prefixLength, 32, 0, 'lower']));
+    prefixLength = reader.readBits(prefixSizeBits);
+    lines.push(new HuffmanLine([highestValue, prefixLength, 32, 0]));
+
+    if (flags & 1) {
+      prefixLength = reader.readBits(prefixSizeBits);
+      lines.push(new HuffmanLine([prefixLength, 0]));
+    }
+
+    return new HuffmanTable(lines, false);
+  }
+
+  var standardTablesCache = {};
+
+  function getStandardTable(number) {
+    var table = standardTablesCache[number];
+
+    if (table) {
+      return table;
+    }
+
+    var lines;
+
+    switch (number) {
+      case 1:
+        lines = [[0, 1, 4, 0x0], [16, 2, 8, 0x2], [272, 3, 16, 0x6], [65808, 3, 32, 0x7]];
+        break;
+
+      case 2:
+        lines = [[0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [75, 6, 32, 0x3E], [6, 0x3F]];
+        break;
+
+      case 3:
+        lines = [[-256, 8, 8, 0xFE], [0, 1, 0, 0x0], [1, 2, 0, 0x2], [2, 3, 0, 0x6], [3, 4, 3, 0xE], [11, 5, 6, 0x1E], [-257, 8, 32, 0xFF, 'lower'], [75, 7, 32, 0x7E], [6, 0x3E]];
+        break;
+
+      case 4:
+        lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [76, 5, 32, 0x1F]];
+        break;
+
+      case 5:
+        lines = [[-255, 7, 8, 0x7E], [1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 0, 0x6], [4, 4, 3, 0xE], [12, 5, 6, 0x1E], [-256, 7, 32, 0x7F, 'lower'], [76, 6, 32, 0x3E]];
+        break;
+
+      case 6:
+        lines = [[-2048, 5, 10, 0x1C], [-1024, 4, 9, 0x8], [-512, 4, 8, 0x9], [-256, 4, 7, 0xA], [-128, 5, 6, 0x1D], [-64, 5, 5, 0x1E], [-32, 4, 5, 0xB], [0, 2, 7, 0x0], [128, 3, 7, 0x2], [256, 3, 8, 0x3], [512, 4, 9, 0xC], [1024, 4, 10, 0xD], [-2049, 6, 32, 0x3E, 'lower'], [2048, 6, 32, 0x3F]];
+        break;
+
+      case 7:
+        lines = [[-1024, 4, 9, 0x8], [-512, 3, 8, 0x0], [-256, 4, 7, 0x9], [-128, 5, 6, 0x1A], [-64, 5, 5, 0x1B], [-32, 4, 5, 0xA], [0, 4, 5, 0xB], [32, 5, 5, 0x1C], [64, 5, 6, 0x1D], [128, 4, 7, 0xC], [256, 3, 8, 0x1], [512, 3, 9, 0x2], [1024, 3, 10, 0x3], [-1025, 5, 32, 0x1E, 'lower'], [2048, 5, 32, 0x1F]];
+        break;
+
+      case 8:
+        lines = [[-15, 8, 3, 0xFC], [-7, 9, 1, 0x1FC], [-5, 8, 1, 0xFD], [-3, 9, 0, 0x1FD], [-2, 7, 0, 0x7C], [-1, 4, 0, 0xA], [0, 2, 1, 0x0], [2, 5, 0, 0x1A], [3, 6, 0, 0x3A], [4, 3, 4, 0x4], [20, 6, 1, 0x3B], [22, 4, 4, 0xB], [38, 4, 5, 0xC], [70, 5, 6, 0x1B], [134, 5, 7, 0x1C], [262, 6, 7, 0x3C], [390, 7, 8, 0x7D], [646, 6, 10, 0x3D], [-16, 9, 32, 0x1FE, 'lower'], [1670, 9, 32, 0x1FF], [2, 0x1]];
+        break;
+
+      case 9:
+        lines = [[-31, 8, 4, 0xFC], [-15, 9, 2, 0x1FC], [-11, 8, 2, 0xFD], [-7, 9, 1, 0x1FD], [-5, 7, 1, 0x7C], [-3, 4, 1, 0xA], [-1, 3, 1, 0x2], [1, 3, 1, 0x3], [3, 5, 1, 0x1A], [5, 6, 1, 0x3A], [7, 3, 5, 0x4], [39, 6, 2, 0x3B], [43, 4, 5, 0xB], [75, 4, 6, 0xC], [139, 5, 7, 0x1B], [267, 5, 8, 0x1C], [523, 6, 8, 0x3C], [779, 7, 9, 0x7D], [1291, 6, 11, 0x3D], [-32, 9, 32, 0x1FE, 'lower'], [3339, 9, 32, 0x1FF], [2, 0x0]];
+        break;
+
+      case 10:
+        lines = [[-21, 7, 4, 0x7A], [-5, 8, 0, 0xFC], [-4, 7, 0, 0x7B], [-3, 5, 0, 0x18], [-2, 2, 2, 0x0], [2, 5, 0, 0x19], [3, 6, 0, 0x36], [4, 7, 0, 0x7C], [5, 8, 0, 0xFD], [6, 2, 6, 0x1], [70, 5, 5, 0x1A], [102, 6, 5, 0x37], [134, 6, 6, 0x38], [198, 6, 7, 0x39], [326, 6, 8, 0x3A], [582, 6, 9, 0x3B], [1094, 6, 10, 0x3C], [2118, 7, 11, 0x7D], [-22, 8, 32, 0xFE, 'lower'], [4166, 8, 32, 0xFF], [2, 0x2]];
+        break;
+
+      case 11:
+        lines = [[1, 1, 0, 0x0], [2, 2, 1, 0x2], [4, 4, 0, 0xC], [5, 4, 1, 0xD], [7, 5, 1, 0x1C], [9, 5, 2, 0x1D], [13, 6, 2, 0x3C], [17, 7, 2, 0x7A], [21, 7, 3, 0x7B], [29, 7, 4, 0x7C], [45, 7, 5, 0x7D], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
+        break;
+
+      case 12:
+        lines = [[1, 1, 0, 0x0], [2, 2, 0, 0x2], [3, 3, 1, 0x6], [5, 5, 0, 0x1C], [6, 5, 1, 0x1D], [8, 6, 1, 0x3C], [10, 7, 0, 0x7A], [11, 7, 1, 0x7B], [13, 7, 2, 0x7C], [17, 7, 3, 0x7D], [25, 7, 4, 0x7E], [41, 8, 5, 0xFE], [73, 8, 32, 0xFF]];
+        break;
+
+      case 13:
+        lines = [[1, 1, 0, 0x0], [2, 3, 0, 0x4], [3, 4, 0, 0xC], [4, 5, 0, 0x1C], [5, 4, 1, 0xD], [7, 3, 3, 0x5], [15, 6, 1, 0x3A], [17, 6, 2, 0x3B], [21, 6, 3, 0x3C], [29, 6, 4, 0x3D], [45, 6, 5, 0x3E], [77, 7, 6, 0x7E], [141, 7, 32, 0x7F]];
+        break;
+
+      case 14:
+        lines = [[-2, 3, 0, 0x4], [-1, 3, 0, 0x5], [0, 1, 0, 0x0], [1, 3, 0, 0x6], [2, 3, 0, 0x7]];
+        break;
+
+      case 15:
+        lines = [[-24, 7, 4, 0x7C], [-8, 6, 2, 0x3C], [-4, 5, 1, 0x1C], [-2, 4, 0, 0xC], [-1, 3, 0, 0x4], [0, 1, 0, 0x0], [1, 3, 0, 0x5], [2, 4, 0, 0xD], [3, 5, 1, 0x1D], [5, 6, 2, 0x3D], [9, 7, 4, 0x7D], [-25, 7, 32, 0x7E, 'lower'], [25, 7, 32, 0x7F]];
+        break;
+
+      default:
+        throw new Jbig2Error("standard table B.".concat(number, " does not exist"));
+    }
+
+    var length = lines.length,
+        i;
+
+    for (i = 0; i < length; i++) {
+      lines[i] = new HuffmanLine(lines[i]);
+    }
+
+    table = new HuffmanTable(lines, true);
+    standardTablesCache[number] = table;
+    return table;
+  }
+
+  function Reader(data, start, end) {
+    this.data = data;
+    this.start = start;
+    this.end = end;
+    this.position = start;
+    this.shift = -1;
+    this.currentByte = 0;
+  }
+
+  Reader.prototype = {
+    readBit: function readBit() {
+      if (this.shift < 0) {
+        if (this.position >= this.end) {
+          throw new Jbig2Error('end of data while reading bit');
+        }
+
+        this.currentByte = this.data[this.position++];
+        this.shift = 7;
+      }
+
+      var bit = this.currentByte >> this.shift & 1;
+      this.shift--;
+      return bit;
+    },
+    readBits: function readBits(numBits) {
+      var result = 0,
+          i;
+
+      for (i = numBits - 1; i >= 0; i--) {
+        result |= this.readBit() << i;
+      }
+
+      return result;
+    },
+    byteAlign: function byteAlign() {
+      this.shift = -1;
+    },
+    next: function next() {
+      if (this.position >= this.end) {
+        return -1;
+      }
+
+      return this.data[this.position++];
+    }
+  };
+
+  function getCustomHuffmanTable(index, referredTo, customTables) {
+    var currentIndex = 0,
+        i,
+        ii = referredTo.length,
+        table;
+
+    for (i = 0; i < ii; i++) {
+      table = customTables[referredTo[i]];
+
+      if (table) {
+        if (index === currentIndex) {
+          return table;
+        }
+
+        currentIndex++;
+      }
+    }
+
+    throw new Jbig2Error('can\'t find custom Huffman table');
+  }
+
+  function getTextRegionHuffmanTables(textRegion, referredTo, customTables, numberOfSymbols, reader) {
+    var codes = [],
+        i,
+        codeLength;
+
+    for (i = 0; i <= 34; i++) {
+      codeLength = reader.readBits(4);
+      codes.push(new HuffmanLine([i, codeLength, 0, 0]));
+    }
+
+    var runCodesTable = new HuffmanTable(codes, false);
+    codes.length = 0;
+
+    for (i = 0; i < numberOfSymbols;) {
+      codeLength = runCodesTable.decode(reader);
+
+      if (codeLength >= 32) {
+        var repeatedLength = void 0,
+            numberOfRepeats = void 0,
+            j = void 0;
+
+        switch (codeLength) {
+          case 32:
+            if (i === 0) {
+              throw new Jbig2Error('no previous value in symbol ID table');
+            }
+
+            numberOfRepeats = reader.readBits(2) + 3;
+            repeatedLength = codes[i - 1].prefixLength;
+            break;
+
+          case 33:
+            numberOfRepeats = reader.readBits(3) + 3;
+            repeatedLength = 0;
+            break;
+
+          case 34:
+            numberOfRepeats = reader.readBits(7) + 11;
+            repeatedLength = 0;
+            break;
+
+          default:
+            throw new Jbig2Error('invalid code length in symbol ID table');
+        }
+
+        for (j = 0; j < numberOfRepeats; j++) {
+          codes.push(new HuffmanLine([i, repeatedLength, 0, 0]));
+          i++;
+        }
+      } else {
+        codes.push(new HuffmanLine([i, codeLength, 0, 0]));
+        i++;
+      }
+    }
+
+    reader.byteAlign();
+    var symbolIDTable = new HuffmanTable(codes, false);
+    var customIndex = 0,
+        tableFirstS,
+        tableDeltaS,
+        tableDeltaT;
+
+    switch (textRegion.huffmanFS) {
+      case 0:
+      case 1:
+        tableFirstS = getStandardTable(textRegion.huffmanFS + 6);
+        break;
+
+      case 3:
+        tableFirstS = getCustomHuffmanTable(customIndex, referredTo, customTables);
+        customIndex++;
+        break;
+
+      default:
+        throw new Jbig2Error('invalid Huffman FS selector');
+    }
+
+    switch (textRegion.huffmanDS) {
+      case 0:
+      case 1:
+      case 2:
+        tableDeltaS = getStandardTable(textRegion.huffmanDS + 8);
+        break;
+
+      case 3:
+        tableDeltaS = getCustomHuffmanTable(customIndex, referredTo, customTables);
+        customIndex++;
+        break;
+
+      default:
+        throw new Jbig2Error('invalid Huffman DS selector');
+    }
+
+    switch (textRegion.huffmanDT) {
+      case 0:
+      case 1:
+      case 2:
+        tableDeltaT = getStandardTable(textRegion.huffmanDT + 11);
+        break;
+
+      case 3:
+        tableDeltaT = getCustomHuffmanTable(customIndex, referredTo, customTables);
+        customIndex++;
+        break;
+
+      default:
+        throw new Jbig2Error('invalid Huffman DT selector');
+    }
+
+    if (textRegion.refinement) {
+      throw new Jbig2Error('refinement with Huffman is not supported');
+    }
+
+    return {
+      symbolIDTable: symbolIDTable,
+      tableFirstS: tableFirstS,
+      tableDeltaS: tableDeltaS,
+      tableDeltaT: tableDeltaT
+    };
+  }
+
+  function getSymbolDictionaryHuffmanTables(dictionary, referredTo, customTables) {
+    var customIndex = 0,
+        tableDeltaHeight,
+        tableDeltaWidth;
+
+    switch (dictionary.huffmanDHSelector) {
+      case 0:
+      case 1:
+        tableDeltaHeight = getStandardTable(dictionary.huffmanDHSelector + 4);
+        break;
+
+      case 3:
+        tableDeltaHeight = getCustomHuffmanTable(customIndex, referredTo, customTables);
+        customIndex++;
+        break;
+
+      default:
+        throw new Jbig2Error('invalid Huffman DH selector');
+    }
+
+    switch (dictionary.huffmanDWSelector) {
+      case 0:
+      case 1:
+        tableDeltaWidth = getStandardTable(dictionary.huffmanDWSelector + 2);
+        break;
+
+      case 3:
+        tableDeltaWidth = getCustomHuffmanTable(customIndex, referredTo, customTables);
+        customIndex++;
+        break;
+
+      default:
+        throw new Jbig2Error('invalid Huffman DW selector');
+    }
+
+    var tableBitmapSize, tableAggregateInstances;
+
+    if (dictionary.bitmapSizeSelector) {
+      tableBitmapSize = getCustomHuffmanTable(customIndex, referredTo, customTables);
+      customIndex++;
+    } else {
+      tableBitmapSize = getStandardTable(1);
+    }
+
+    if (dictionary.aggregationInstancesSelector) {
+      tableAggregateInstances = getCustomHuffmanTable(customIndex, referredTo, customTables);
+    } else {
+      tableAggregateInstances = getStandardTable(1);
+    }
+
+    return {
+      tableDeltaHeight: tableDeltaHeight,
+      tableDeltaWidth: tableDeltaWidth,
+      tableBitmapSize: tableBitmapSize,
+      tableAggregateInstances: tableAggregateInstances
+    };
+  }
+
+  function readUncompressedBitmap(reader, width, height) {
+    var bitmap = [],
+        x,
+        y,
+        row;
+
+    for (y = 0; y < height; y++) {
+      row = new Uint8Array(width);
+      bitmap.push(row);
+
+      for (x = 0; x < width; x++) {
+        row[x] = reader.readBit();
+      }
+
+      reader.byteAlign();
+    }
+
+    return bitmap;
+  }
+
+  function decodeMMRBitmap(input, width, height, endOfBlock) {
+    var params = {
+      K: -1,
+      Columns: width,
+      Rows: height,
+      BlackIs1: true,
+      EndOfBlock: endOfBlock
+    };
+    var decoder = new _ccitt.CCITTFaxDecoder(input, params);
+    var bitmap = [],
+        x,
+        y,
+        row,
+        currentByte,
+        shift,
+        eof = false;
+
+    for (y = 0; y < height; y++) {
+      row = new Uint8Array(width);
+      bitmap.push(row);
+      shift = -1;
+
+      for (x = 0; x < width; x++) {
+        if (shift < 0) {
+          currentByte = decoder.readNextChar();
+
+          if (currentByte === -1) {
+            currentByte = 0;
+            eof = true;
+          }
+
+          shift = 7;
+        }
+
+        row[x] = currentByte >> shift & 1;
+        shift--;
+      }
+    }
+
+    if (endOfBlock && !eof) {
+      var lookForEOFLimit = 5;
+
+      for (var i = 0; i < lookForEOFLimit; i++) {
+        if (decoder.readNextChar() === -1) {
+          break;
+        }
+      }
+    }
+
+    return bitmap;
+  }
+
+  function Jbig2Image() {}
+
+  Jbig2Image.prototype = {
+    parseChunks: function parseChunks(chunks) {
+      return parseJbig2Chunks(chunks);
+    },
+    parse: function parse(data) {
+      var _parseJbig = parseJbig2(data),
+          imgData = _parseJbig.imgData,
+          width = _parseJbig.width,
+          height = _parseJbig.height;
+
+      this.width = width;
+      this.height = height;
+      return imgData;
+    }
+  };
+  return Jbig2Image;
+}();
+
+exports.Jbig2Image = Jbig2Image;
+
+/***/ }),
+/* 163 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ArithmeticDecoder = void 0;
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var QeTable = [{
+  qe: 0x5601,
+  nmps: 1,
+  nlps: 1,
+  switchFlag: 1
+}, {
+  qe: 0x3401,
+  nmps: 2,
+  nlps: 6,
+  switchFlag: 0
+}, {
+  qe: 0x1801,
+  nmps: 3,
+  nlps: 9,
+  switchFlag: 0
+}, {
+  qe: 0x0AC1,
+  nmps: 4,
+  nlps: 12,
+  switchFlag: 0
+}, {
+  qe: 0x0521,
+  nmps: 5,
+  nlps: 29,
+  switchFlag: 0
+}, {
+  qe: 0x0221,
+  nmps: 38,
+  nlps: 33,
+  switchFlag: 0
+}, {
+  qe: 0x5601,
+  nmps: 7,
+  nlps: 6,
+  switchFlag: 1
+}, {
+  qe: 0x5401,
+  nmps: 8,
+  nlps: 14,
+  switchFlag: 0
+}, {
+  qe: 0x4801,
+  nmps: 9,
+  nlps: 14,
+  switchFlag: 0
+}, {
+  qe: 0x3801,
+  nmps: 10,
+  nlps: 14,
+  switchFlag: 0
+}, {
+  qe: 0x3001,
+  nmps: 11,
+  nlps: 17,
+  switchFlag: 0
+}, {
+  qe: 0x2401,
+  nmps: 12,
+  nlps: 18,
+  switchFlag: 0
+}, {
+  qe: 0x1C01,
+  nmps: 13,
+  nlps: 20,
+  switchFlag: 0
+}, {
+  qe: 0x1601,
+  nmps: 29,
+  nlps: 21,
+  switchFlag: 0
+}, {
+  qe: 0x5601,
+  nmps: 15,
+  nlps: 14,
+  switchFlag: 1
+}, {
+  qe: 0x5401,
+  nmps: 16,
+  nlps: 14,
+  switchFlag: 0
+}, {
+  qe: 0x5101,
+  nmps: 17,
+  nlps: 15,
+  switchFlag: 0
+}, {
+  qe: 0x4801,
+  nmps: 18,
+  nlps: 16,
+  switchFlag: 0
+}, {
+  qe: 0x3801,
+  nmps: 19,
+  nlps: 17,
+  switchFlag: 0
+}, {
+  qe: 0x3401,
+  nmps: 20,
+  nlps: 18,
+  switchFlag: 0
+}, {
+  qe: 0x3001,
+  nmps: 21,
+  nlps: 19,
+  switchFlag: 0
+}, {
+  qe: 0x2801,
+  nmps: 22,
+  nlps: 19,
+  switchFlag: 0
+}, {
+  qe: 0x2401,
+  nmps: 23,
+  nlps: 20,
+  switchFlag: 0
+}, {
+  qe: 0x2201,
+  nmps: 24,
+  nlps: 21,
+  switchFlag: 0
+}, {
+  qe: 0x1C01,
+  nmps: 25,
+  nlps: 22,
+  switchFlag: 0
+}, {
+  qe: 0x1801,
+  nmps: 26,
+  nlps: 23,
+  switchFlag: 0
+}, {
+  qe: 0x1601,
+  nmps: 27,
+  nlps: 24,
+  switchFlag: 0
+}, {
+  qe: 0x1401,
+  nmps: 28,
+  nlps: 25,
+  switchFlag: 0
+}, {
+  qe: 0x1201,
+  nmps: 29,
+  nlps: 26,
+  switchFlag: 0
+}, {
+  qe: 0x1101,
+  nmps: 30,
+  nlps: 27,
+  switchFlag: 0
+}, {
+  qe: 0x0AC1,
+  nmps: 31,
+  nlps: 28,
+  switchFlag: 0
+}, {
+  qe: 0x09C1,
+  nmps: 32,
+  nlps: 29,
+  switchFlag: 0
+}, {
+  qe: 0x08A1,
+  nmps: 33,
+  nlps: 30,
+  switchFlag: 0
+}, {
+  qe: 0x0521,
+  nmps: 34,
+  nlps: 31,
+  switchFlag: 0
+}, {
+  qe: 0x0441,
+  nmps: 35,
+  nlps: 32,
+  switchFlag: 0
+}, {
+  qe: 0x02A1,
+  nmps: 36,
+  nlps: 33,
+  switchFlag: 0
+}, {
+  qe: 0x0221,
+  nmps: 37,
+  nlps: 34,
+  switchFlag: 0
+}, {
+  qe: 0x0141,
+  nmps: 38,
+  nlps: 35,
+  switchFlag: 0
+}, {
+  qe: 0x0111,
+  nmps: 39,
+  nlps: 36,
+  switchFlag: 0
+}, {
+  qe: 0x0085,
+  nmps: 40,
+  nlps: 37,
+  switchFlag: 0
+}, {
+  qe: 0x0049,
+  nmps: 41,
+  nlps: 38,
+  switchFlag: 0
+}, {
+  qe: 0x0025,
+  nmps: 42,
+  nlps: 39,
+  switchFlag: 0
+}, {
+  qe: 0x0015,
+  nmps: 43,
+  nlps: 40,
+  switchFlag: 0
+}, {
+  qe: 0x0009,
+  nmps: 44,
+  nlps: 41,
+  switchFlag: 0
+}, {
+  qe: 0x0005,
+  nmps: 45,
+  nlps: 42,
+  switchFlag: 0
+}, {
+  qe: 0x0001,
+  nmps: 45,
+  nlps: 43,
+  switchFlag: 0
+}, {
+  qe: 0x5601,
+  nmps: 46,
+  nlps: 46,
+  switchFlag: 0
+}];
+
+var ArithmeticDecoder =
+/*#__PURE__*/
+function () {
+  function ArithmeticDecoder(data, start, end) {
+    _classCallCheck(this, ArithmeticDecoder);
+
+    this.data = data;
+    this.bp = start;
+    this.dataEnd = end;
+    this.chigh = data[start];
+    this.clow = 0;
+    this.byteIn();
+    this.chigh = this.chigh << 7 & 0xFFFF | this.clow >> 9 & 0x7F;
+    this.clow = this.clow << 7 & 0xFFFF;
+    this.ct -= 7;
+    this.a = 0x8000;
+  }
+
+  _createClass(ArithmeticDecoder, [{
+    key: "byteIn",
+    value: function byteIn() {
+      var data = this.data;
+      var bp = this.bp;
+
+      if (data[bp] === 0xFF) {
+        if (data[bp + 1] > 0x8F) {
+          this.clow += 0xFF00;
+          this.ct = 8;
+        } else {
+          bp++;
+          this.clow += data[bp] << 9;
+          this.ct = 7;
+          this.bp = bp;
+        }
+      } else {
+        bp++;
+        this.clow += bp < this.dataEnd ? data[bp] << 8 : 0xFF00;
+        this.ct = 8;
+        this.bp = bp;
+      }
+
+      if (this.clow > 0xFFFF) {
+        this.chigh += this.clow >> 16;
+        this.clow &= 0xFFFF;
+      }
+    }
+  }, {
+    key: "readBit",
+    value: function readBit(contexts, pos) {
+      var cx_index = contexts[pos] >> 1,
+          cx_mps = contexts[pos] & 1;
+      var qeTableIcx = QeTable[cx_index];
+      var qeIcx = qeTableIcx.qe;
+      var d;
+      var a = this.a - qeIcx;
+
+      if (this.chigh < qeIcx) {
+        if (a < qeIcx) {
+          a = qeIcx;
+          d = cx_mps;
+          cx_index = qeTableIcx.nmps;
+        } else {
+          a = qeIcx;
+          d = 1 ^ cx_mps;
+
+          if (qeTableIcx.switchFlag === 1) {
+            cx_mps = d;
+          }
+
+          cx_index = qeTableIcx.nlps;
+        }
+      } else {
+        this.chigh -= qeIcx;
+
+        if ((a & 0x8000) !== 0) {
+          this.a = a;
+          return cx_mps;
+        }
+
+        if (a < qeIcx) {
+          d = 1 ^ cx_mps;
+
+          if (qeTableIcx.switchFlag === 1) {
+            cx_mps = d;
+          }
+
+          cx_index = qeTableIcx.nlps;
+        } else {
+          d = cx_mps;
+          cx_index = qeTableIcx.nmps;
+        }
+      }
+
+      do {
+        if (this.ct === 0) {
+          this.byteIn();
+        }
+
+        a <<= 1;
+        this.chigh = this.chigh << 1 & 0xFFFF | this.clow >> 15 & 1;
+        this.clow = this.clow << 1 & 0xFFFF;
+        this.ct--;
+      } while ((a & 0x8000) === 0);
+
+      this.a = a;
+      contexts[pos] = cx_index << 1 | cx_mps;
+      return d;
+    }
+  }]);
+
+  return ArithmeticDecoder;
+}();
+
+exports.ArithmeticDecoder = ArithmeticDecoder;
+
+/***/ }),
+/* 164 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.JpegStream = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _stream = __w_pdfjs_require__(158);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _jpg = __w_pdfjs_require__(165);
+
+var JpegStream = function JpegStreamClosure() {
+  function JpegStream(stream, maybeLength, dict, params) {
+    var ch;
+
+    while ((ch = stream.getByte()) !== -1) {
+      if (ch === 0xFF) {
+        stream.skip(-1);
+        break;
+      }
+    }
+
+    this.stream = stream;
+    this.maybeLength = maybeLength;
+    this.dict = dict;
+    this.params = params;
+
+    _stream.DecodeStream.call(this, maybeLength);
+  }
+
+  JpegStream.prototype = Object.create(_stream.DecodeStream.prototype);
+  Object.defineProperty(JpegStream.prototype, 'bytes', {
+    get: function JpegStream_bytes() {
+      return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
+    },
+    configurable: true
+  });
+
+  JpegStream.prototype.ensureBuffer = function (requested) {};
+
+  JpegStream.prototype.readBlock = function () {
+    if (this.eof) {
+      return;
+    }
+
+    var jpegOptions = {
+      decodeTransform: undefined,
+      colorTransform: undefined
+    };
+    var decodeArr = this.dict.getArray('Decode', 'D');
+
+    if (this.forceRGB && Array.isArray(decodeArr)) {
+      var bitsPerComponent = this.dict.get('BitsPerComponent') || 8;
+      var decodeArrLength = decodeArr.length;
+      var transform = new Int32Array(decodeArrLength);
+      var transformNeeded = false;
+      var maxValue = (1 << bitsPerComponent) - 1;
+
+      for (var i = 0; i < decodeArrLength; i += 2) {
+        transform[i] = (decodeArr[i + 1] - decodeArr[i]) * 256 | 0;
+        transform[i + 1] = decodeArr[i] * maxValue | 0;
+
+        if (transform[i] !== 256 || transform[i + 1] !== 0) {
+          transformNeeded = true;
+        }
+      }
+
+      if (transformNeeded) {
+        jpegOptions.decodeTransform = transform;
+      }
+    }
+
+    if ((0, _primitives.isDict)(this.params)) {
+      var colorTransform = this.params.get('ColorTransform');
+
+      if (Number.isInteger(colorTransform)) {
+        jpegOptions.colorTransform = colorTransform;
+      }
+    }
+
+    var jpegImage = new _jpg.JpegImage(jpegOptions);
+    jpegImage.parse(this.bytes);
+    var data = jpegImage.getData({
+      width: this.drawWidth,
+      height: this.drawHeight,
+      forceRGB: this.forceRGB,
+      isSourcePDF: true
+    });
+    this.buffer = data;
+    this.bufferLength = data.length;
+    this.eof = true;
+  };
+
+  JpegStream.prototype.getIR = function () {
+    var forceDataSchema = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+    return (0, _util.createObjectURL)(this.bytes, 'image/jpeg', forceDataSchema);
+  };
+
+  return JpegStream;
+}();
+
+exports.JpegStream = JpegStream;
+
+/***/ }),
+/* 165 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.JpegImage = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+var JpegError = function JpegErrorClosure() {
+  function JpegError(msg) {
+    this.message = 'JPEG error: ' + msg;
+  }
+
+  JpegError.prototype = new Error();
+  JpegError.prototype.name = 'JpegError';
+  JpegError.constructor = JpegError;
+  return JpegError;
+}();
+
+var DNLMarkerError = function DNLMarkerErrorClosure() {
+  function DNLMarkerError(message, scanLines) {
+    this.message = message;
+    this.scanLines = scanLines;
+  }
+
+  DNLMarkerError.prototype = new Error();
+  DNLMarkerError.prototype.name = 'DNLMarkerError';
+  DNLMarkerError.constructor = DNLMarkerError;
+  return DNLMarkerError;
+}();
+
+var EOIMarkerError = function EOIMarkerErrorClosure() {
+  function EOIMarkerError(message) {
+    this.message = message;
+  }
+
+  EOIMarkerError.prototype = new Error();
+  EOIMarkerError.prototype.name = 'EOIMarkerError';
+  EOIMarkerError.constructor = EOIMarkerError;
+  return EOIMarkerError;
+}();
+
+var JpegImage = function JpegImageClosure() {
+  var dctZigZag = new Uint8Array([0, 1, 8, 16, 9, 2, 3, 10, 17, 24, 32, 25, 18, 11, 4, 5, 12, 19, 26, 33, 40, 48, 41, 34, 27, 20, 13, 6, 7, 14, 21, 28, 35, 42, 49, 56, 57, 50, 43, 36, 29, 22, 15, 23, 30, 37, 44, 51, 58, 59, 52, 45, 38, 31, 39, 46, 53, 60, 61, 54, 47, 55, 62, 63]);
+  var dctCos1 = 4017;
+  var dctSin1 = 799;
+  var dctCos3 = 3406;
+  var dctSin3 = 2276;
+  var dctCos6 = 1567;
+  var dctSin6 = 3784;
+  var dctSqrt2 = 5793;
+  var dctSqrt1d2 = 2896;
+
+  function JpegImage() {
+    var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
+        _ref$decodeTransform = _ref.decodeTransform,
+        decodeTransform = _ref$decodeTransform === void 0 ? null : _ref$decodeTransform,
+        _ref$colorTransform = _ref.colorTransform,
+        colorTransform = _ref$colorTransform === void 0 ? -1 : _ref$colorTransform;
+
+    this._decodeTransform = decodeTransform;
+    this._colorTransform = colorTransform;
+  }
+
+  function buildHuffmanTable(codeLengths, values) {
+    var k = 0,
+        code = [],
+        i,
+        j,
+        length = 16;
+
+    while (length > 0 && !codeLengths[length - 1]) {
+      length--;
+    }
+
+    code.push({
+      children: [],
+      index: 0
+    });
+    var p = code[0],
+        q;
+
+    for (i = 0; i < length; i++) {
+      for (j = 0; j < codeLengths[i]; j++) {
+        p = code.pop();
+        p.children[p.index] = values[k];
+
+        while (p.index > 0) {
+          p = code.pop();
+        }
+
+        p.index++;
+        code.push(p);
+
+        while (code.length <= i) {
+          code.push(q = {
+            children: [],
+            index: 0
+          });
+          p.children[p.index] = q.children;
+          p = q;
+        }
+
+        k++;
+      }
+
+      if (i + 1 < length) {
+        code.push(q = {
+          children: [],
+          index: 0
+        });
+        p.children[p.index] = q.children;
+        p = q;
+      }
+    }
+
+    return code[0].children;
+  }
+
+  function getBlockBufferOffset(component, row, col) {
+    return 64 * ((component.blocksPerLine + 1) * row + col);
+  }
+
+  function decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successivePrev, successive) {
+    var parseDNLMarker = arguments.length > 9 && arguments[9] !== undefined ? arguments[9] : false;
+    var mcusPerLine = frame.mcusPerLine;
+    var progressive = frame.progressive;
+    var startOffset = offset,
+        bitsData = 0,
+        bitsCount = 0;
+
+    function readBit() {
+      if (bitsCount > 0) {
+        bitsCount--;
+        return bitsData >> bitsCount & 1;
+      }
+
+      bitsData = data[offset++];
+
+      if (bitsData === 0xFF) {
+        var nextByte = data[offset++];
+
+        if (nextByte) {
+          if (nextByte === 0xDC && parseDNLMarker) {
+            offset += 2;
+            var scanLines = data[offset++] << 8 | data[offset++];
+
+            if (scanLines > 0 && scanLines !== frame.scanLines) {
+              throw new DNLMarkerError('Found DNL marker (0xFFDC) while parsing scan data', scanLines);
+            }
+          } else if (nextByte === 0xD9) {
+            throw new EOIMarkerError('Found EOI marker (0xFFD9) while parsing scan data');
+          }
+
+          throw new JpegError("unexpected marker ".concat((bitsData << 8 | nextByte).toString(16)));
+        }
+      }
+
+      bitsCount = 7;
+      return bitsData >>> 7;
+    }
+
+    function decodeHuffman(tree) {
+      var node = tree;
+
+      while (true) {
+        node = node[readBit()];
+
+        if (typeof node === 'number') {
+          return node;
+        }
+
+        if (_typeof(node) !== 'object') {
+          throw new JpegError('invalid huffman sequence');
+        }
+      }
+    }
+
+    function receive(length) {
+      var n = 0;
+
+      while (length > 0) {
+        n = n << 1 | readBit();
+        length--;
+      }
+
+      return n;
+    }
+
+    function receiveAndExtend(length) {
+      if (length === 1) {
+        return readBit() === 1 ? 1 : -1;
+      }
+
+      var n = receive(length);
+
+      if (n >= 1 << length - 1) {
+        return n;
+      }
+
+      return n + (-1 << length) + 1;
+    }
+
+    function decodeBaseline(component, offset) {
+      var t = decodeHuffman(component.huffmanTableDC);
+      var diff = t === 0 ? 0 : receiveAndExtend(t);
+      component.blockData[offset] = component.pred += diff;
+      var k = 1;
+
+      while (k < 64) {
+        var rs = decodeHuffman(component.huffmanTableAC);
+        var s = rs & 15,
+            r = rs >> 4;
+
+        if (s === 0) {
+          if (r < 15) {
+            break;
+          }
+
+          k += 16;
+          continue;
+        }
+
+        k += r;
+        var z = dctZigZag[k];
+        component.blockData[offset + z] = receiveAndExtend(s);
+        k++;
+      }
+    }
+
+    function decodeDCFirst(component, offset) {
+      var t = decodeHuffman(component.huffmanTableDC);
+      var diff = t === 0 ? 0 : receiveAndExtend(t) << successive;
+      component.blockData[offset] = component.pred += diff;
+    }
+
+    function decodeDCSuccessive(component, offset) {
+      component.blockData[offset] |= readBit() << successive;
+    }
+
+    var eobrun = 0;
+
+    function decodeACFirst(component, offset) {
+      if (eobrun > 0) {
+        eobrun--;
+        return;
+      }
+
+      var k = spectralStart,
+          e = spectralEnd;
+
+      while (k <= e) {
+        var rs = decodeHuffman(component.huffmanTableAC);
+        var s = rs & 15,
+            r = rs >> 4;
+
+        if (s === 0) {
+          if (r < 15) {
+            eobrun = receive(r) + (1 << r) - 1;
+            break;
+          }
+
+          k += 16;
+          continue;
+        }
+
+        k += r;
+        var z = dctZigZag[k];
+        component.blockData[offset + z] = receiveAndExtend(s) * (1 << successive);
+        k++;
+      }
+    }
+
+    var successiveACState = 0,
+        successiveACNextValue;
+
+    function decodeACSuccessive(component, offset) {
+      var k = spectralStart;
+      var e = spectralEnd;
+      var r = 0;
+      var s;
+      var rs;
+
+      while (k <= e) {
+        var offsetZ = offset + dctZigZag[k];
+        var sign = component.blockData[offsetZ] < 0 ? -1 : 1;
+
+        switch (successiveACState) {
+          case 0:
+            rs = decodeHuffman(component.huffmanTableAC);
+            s = rs & 15;
+            r = rs >> 4;
+
+            if (s === 0) {
+              if (r < 15) {
+                eobrun = receive(r) + (1 << r);
+                successiveACState = 4;
+              } else {
+                r = 16;
+                successiveACState = 1;
+              }
+            } else {
+              if (s !== 1) {
+                throw new JpegError('invalid ACn encoding');
+              }
+
+              successiveACNextValue = receiveAndExtend(s);
+              successiveACState = r ? 2 : 3;
+            }
+
+            continue;
+
+          case 1:
+          case 2:
+            if (component.blockData[offsetZ]) {
+              component.blockData[offsetZ] += sign * (readBit() << successive);
+            } else {
+              r--;
+
+              if (r === 0) {
+                successiveACState = successiveACState === 2 ? 3 : 0;
+              }
+            }
+
+            break;
+
+          case 3:
+            if (component.blockData[offsetZ]) {
+              component.blockData[offsetZ] += sign * (readBit() << successive);
+            } else {
+              component.blockData[offsetZ] = successiveACNextValue << successive;
+              successiveACState = 0;
+            }
+
+            break;
+
+          case 4:
+            if (component.blockData[offsetZ]) {
+              component.blockData[offsetZ] += sign * (readBit() << successive);
+            }
+
+            break;
+        }
+
+        k++;
+      }
+
+      if (successiveACState === 4) {
+        eobrun--;
+
+        if (eobrun === 0) {
+          successiveACState = 0;
+        }
+      }
+    }
+
+    function decodeMcu(component, decode, mcu, row, col) {
+      var mcuRow = mcu / mcusPerLine | 0;
+      var mcuCol = mcu % mcusPerLine;
+      var blockRow = mcuRow * component.v + row;
+      var blockCol = mcuCol * component.h + col;
+      var offset = getBlockBufferOffset(component, blockRow, blockCol);
+      decode(component, offset);
+    }
+
+    function decodeBlock(component, decode, mcu) {
+      var blockRow = mcu / component.blocksPerLine | 0;
+      var blockCol = mcu % component.blocksPerLine;
+      var offset = getBlockBufferOffset(component, blockRow, blockCol);
+      decode(component, offset);
+    }
+
+    var componentsLength = components.length;
+    var component, i, j, k, n;
+    var decodeFn;
+
+    if (progressive) {
+      if (spectralStart === 0) {
+        decodeFn = successivePrev === 0 ? decodeDCFirst : decodeDCSuccessive;
+      } else {
+        decodeFn = successivePrev === 0 ? decodeACFirst : decodeACSuccessive;
+      }
+    } else {
+      decodeFn = decodeBaseline;
+    }
+
+    var mcu = 0,
+        fileMarker;
+    var mcuExpected;
+
+    if (componentsLength === 1) {
+      mcuExpected = components[0].blocksPerLine * components[0].blocksPerColumn;
+    } else {
+      mcuExpected = mcusPerLine * frame.mcusPerColumn;
+    }
+
+    var h, v;
+
+    while (mcu < mcuExpected) {
+      var mcuToRead = resetInterval ? Math.min(mcuExpected - mcu, resetInterval) : mcuExpected;
+
+      for (i = 0; i < componentsLength; i++) {
+        components[i].pred = 0;
+      }
+
+      eobrun = 0;
+
+      if (componentsLength === 1) {
+        component = components[0];
+
+        for (n = 0; n < mcuToRead; n++) {
+          decodeBlock(component, decodeFn, mcu);
+          mcu++;
+        }
+      } else {
+        for (n = 0; n < mcuToRead; n++) {
+          for (i = 0; i < componentsLength; i++) {
+            component = components[i];
+            h = component.h;
+            v = component.v;
+
+            for (j = 0; j < v; j++) {
+              for (k = 0; k < h; k++) {
+                decodeMcu(component, decodeFn, mcu, j, k);
+              }
+            }
+          }
+
+          mcu++;
+        }
+      }
+
+      bitsCount = 0;
+      fileMarker = findNextFileMarker(data, offset);
+
+      if (fileMarker && fileMarker.invalid) {
+        (0, _util.warn)('decodeScan - unexpected MCU data, current marker is: ' + fileMarker.invalid);
+        offset = fileMarker.offset;
+      }
+
+      var marker = fileMarker && fileMarker.marker;
+
+      if (!marker || marker <= 0xFF00) {
+        throw new JpegError('marker was not found');
+      }
+
+      if (marker >= 0xFFD0 && marker <= 0xFFD7) {
+        offset += 2;
+      } else {
+        break;
+      }
+    }
+
+    fileMarker = findNextFileMarker(data, offset);
+
+    if (fileMarker && fileMarker.invalid) {
+      (0, _util.warn)('decodeScan - unexpected Scan data, current marker is: ' + fileMarker.invalid);
+      offset = fileMarker.offset;
+    }
+
+    return offset - startOffset;
+  }
+
+  function quantizeAndInverse(component, blockBufferOffset, p) {
+    var qt = component.quantizationTable,
+        blockData = component.blockData;
+    var v0, v1, v2, v3, v4, v5, v6, v7;
+    var p0, p1, p2, p3, p4, p5, p6, p7;
+    var t;
+
+    if (!qt) {
+      throw new JpegError('missing required Quantization Table.');
+    }
+
+    for (var row = 0; row < 64; row += 8) {
+      p0 = blockData[blockBufferOffset + row];
+      p1 = blockData[blockBufferOffset + row + 1];
+      p2 = blockData[blockBufferOffset + row + 2];
+      p3 = blockData[blockBufferOffset + row + 3];
+      p4 = blockData[blockBufferOffset + row + 4];
+      p5 = blockData[blockBufferOffset + row + 5];
+      p6 = blockData[blockBufferOffset + row + 6];
+      p7 = blockData[blockBufferOffset + row + 7];
+      p0 *= qt[row];
+
+      if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
+        t = dctSqrt2 * p0 + 512 >> 10;
+        p[row] = t;
+        p[row + 1] = t;
+        p[row + 2] = t;
+        p[row + 3] = t;
+        p[row + 4] = t;
+        p[row + 5] = t;
+        p[row + 6] = t;
+        p[row + 7] = t;
+        continue;
+      }
+
+      p1 *= qt[row + 1];
+      p2 *= qt[row + 2];
+      p3 *= qt[row + 3];
+      p4 *= qt[row + 4];
+      p5 *= qt[row + 5];
+      p6 *= qt[row + 6];
+      p7 *= qt[row + 7];
+      v0 = dctSqrt2 * p0 + 128 >> 8;
+      v1 = dctSqrt2 * p4 + 128 >> 8;
+      v2 = p2;
+      v3 = p6;
+      v4 = dctSqrt1d2 * (p1 - p7) + 128 >> 8;
+      v7 = dctSqrt1d2 * (p1 + p7) + 128 >> 8;
+      v5 = p3 << 4;
+      v6 = p5 << 4;
+      v0 = v0 + v1 + 1 >> 1;
+      v1 = v0 - v1;
+      t = v2 * dctSin6 + v3 * dctCos6 + 128 >> 8;
+      v2 = v2 * dctCos6 - v3 * dctSin6 + 128 >> 8;
+      v3 = t;
+      v4 = v4 + v6 + 1 >> 1;
+      v6 = v4 - v6;
+      v7 = v7 + v5 + 1 >> 1;
+      v5 = v7 - v5;
+      v0 = v0 + v3 + 1 >> 1;
+      v3 = v0 - v3;
+      v1 = v1 + v2 + 1 >> 1;
+      v2 = v1 - v2;
+      t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
+      v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
+      v7 = t;
+      t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
+      v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
+      v6 = t;
+      p[row] = v0 + v7;
+      p[row + 7] = v0 - v7;
+      p[row + 1] = v1 + v6;
+      p[row + 6] = v1 - v6;
+      p[row + 2] = v2 + v5;
+      p[row + 5] = v2 - v5;
+      p[row + 3] = v3 + v4;
+      p[row + 4] = v3 - v4;
+    }
+
+    for (var col = 0; col < 8; ++col) {
+      p0 = p[col];
+      p1 = p[col + 8];
+      p2 = p[col + 16];
+      p3 = p[col + 24];
+      p4 = p[col + 32];
+      p5 = p[col + 40];
+      p6 = p[col + 48];
+      p7 = p[col + 56];
+
+      if ((p1 | p2 | p3 | p4 | p5 | p6 | p7) === 0) {
+        t = dctSqrt2 * p0 + 8192 >> 14;
+        t = t < -2040 ? 0 : t >= 2024 ? 255 : t + 2056 >> 4;
+        blockData[blockBufferOffset + col] = t;
+        blockData[blockBufferOffset + col + 8] = t;
+        blockData[blockBufferOffset + col + 16] = t;
+        blockData[blockBufferOffset + col + 24] = t;
+        blockData[blockBufferOffset + col + 32] = t;
+        blockData[blockBufferOffset + col + 40] = t;
+        blockData[blockBufferOffset + col + 48] = t;
+        blockData[blockBufferOffset + col + 56] = t;
+        continue;
+      }
+
+      v0 = dctSqrt2 * p0 + 2048 >> 12;
+      v1 = dctSqrt2 * p4 + 2048 >> 12;
+      v2 = p2;
+      v3 = p6;
+      v4 = dctSqrt1d2 * (p1 - p7) + 2048 >> 12;
+      v7 = dctSqrt1d2 * (p1 + p7) + 2048 >> 12;
+      v5 = p3;
+      v6 = p5;
+      v0 = (v0 + v1 + 1 >> 1) + 4112;
+      v1 = v0 - v1;
+      t = v2 * dctSin6 + v3 * dctCos6 + 2048 >> 12;
+      v2 = v2 * dctCos6 - v3 * dctSin6 + 2048 >> 12;
+      v3 = t;
+      v4 = v4 + v6 + 1 >> 1;
+      v6 = v4 - v6;
+      v7 = v7 + v5 + 1 >> 1;
+      v5 = v7 - v5;
+      v0 = v0 + v3 + 1 >> 1;
+      v3 = v0 - v3;
+      v1 = v1 + v2 + 1 >> 1;
+      v2 = v1 - v2;
+      t = v4 * dctSin3 + v7 * dctCos3 + 2048 >> 12;
+      v4 = v4 * dctCos3 - v7 * dctSin3 + 2048 >> 12;
+      v7 = t;
+      t = v5 * dctSin1 + v6 * dctCos1 + 2048 >> 12;
+      v5 = v5 * dctCos1 - v6 * dctSin1 + 2048 >> 12;
+      v6 = t;
+      p0 = v0 + v7;
+      p7 = v0 - v7;
+      p1 = v1 + v6;
+      p6 = v1 - v6;
+      p2 = v2 + v5;
+      p5 = v2 - v5;
+      p3 = v3 + v4;
+      p4 = v3 - v4;
+      p0 = p0 < 16 ? 0 : p0 >= 4080 ? 255 : p0 >> 4;
+      p1 = p1 < 16 ? 0 : p1 >= 4080 ? 255 : p1 >> 4;
+      p2 = p2 < 16 ? 0 : p2 >= 4080 ? 255 : p2 >> 4;
+      p3 = p3 < 16 ? 0 : p3 >= 4080 ? 255 : p3 >> 4;
+      p4 = p4 < 16 ? 0 : p4 >= 4080 ? 255 : p4 >> 4;
+      p5 = p5 < 16 ? 0 : p5 >= 4080 ? 255 : p5 >> 4;
+      p6 = p6 < 16 ? 0 : p6 >= 4080 ? 255 : p6 >> 4;
+      p7 = p7 < 16 ? 0 : p7 >= 4080 ? 255 : p7 >> 4;
+      blockData[blockBufferOffset + col] = p0;
+      blockData[blockBufferOffset + col + 8] = p1;
+      blockData[blockBufferOffset + col + 16] = p2;
+      blockData[blockBufferOffset + col + 24] = p3;
+      blockData[blockBufferOffset + col + 32] = p4;
+      blockData[blockBufferOffset + col + 40] = p5;
+      blockData[blockBufferOffset + col + 48] = p6;
+      blockData[blockBufferOffset + col + 56] = p7;
+    }
+  }
+
+  function buildComponentData(frame, component) {
+    var blocksPerLine = component.blocksPerLine;
+    var blocksPerColumn = component.blocksPerColumn;
+    var computationBuffer = new Int16Array(64);
+
+    for (var blockRow = 0; blockRow < blocksPerColumn; blockRow++) {
+      for (var blockCol = 0; blockCol < blocksPerLine; blockCol++) {
+        var offset = getBlockBufferOffset(component, blockRow, blockCol);
+        quantizeAndInverse(component, offset, computationBuffer);
+      }
+    }
+
+    return component.blockData;
+  }
+
+  function findNextFileMarker(data, currentPos) {
+    var startPos = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : currentPos;
+
+    function peekUint16(pos) {
+      return data[pos] << 8 | data[pos + 1];
+    }
+
+    var maxPos = data.length - 1;
+    var newPos = startPos < currentPos ? startPos : currentPos;
+
+    if (currentPos >= maxPos) {
+      return null;
+    }
+
+    var currentMarker = peekUint16(currentPos);
+
+    if (currentMarker >= 0xFFC0 && currentMarker <= 0xFFFE) {
+      return {
+        invalid: null,
+        marker: currentMarker,
+        offset: currentPos
+      };
+    }
+
+    var newMarker = peekUint16(newPos);
+
+    while (!(newMarker >= 0xFFC0 && newMarker <= 0xFFFE)) {
+      if (++newPos >= maxPos) {
+        return null;
+      }
+
+      newMarker = peekUint16(newPos);
+    }
+
+    return {
+      invalid: currentMarker.toString(16),
+      marker: newMarker,
+      offset: newPos
+    };
+  }
+
+  JpegImage.prototype = {
+    parse: function parse(data) {
+      var _ref2 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {},
+          _ref2$dnlScanLines = _ref2.dnlScanLines,
+          dnlScanLines = _ref2$dnlScanLines === void 0 ? null : _ref2$dnlScanLines;
+
+      function readUint16() {
+        var value = data[offset] << 8 | data[offset + 1];
+        offset += 2;
+        return value;
+      }
+
+      function readDataBlock() {
+        var length = readUint16();
+        var endOffset = offset + length - 2;
+        var fileMarker = findNextFileMarker(data, endOffset, offset);
+
+        if (fileMarker && fileMarker.invalid) {
+          (0, _util.warn)('readDataBlock - incorrect length, current marker is: ' + fileMarker.invalid);
+          endOffset = fileMarker.offset;
+        }
+
+        var array = data.subarray(offset, endOffset);
+        offset += array.length;
+        return array;
+      }
+
+      function prepareComponents(frame) {
+        var mcusPerLine = Math.ceil(frame.samplesPerLine / 8 / frame.maxH);
+        var mcusPerColumn = Math.ceil(frame.scanLines / 8 / frame.maxV);
+
+        for (var i = 0; i < frame.components.length; i++) {
+          component = frame.components[i];
+          var blocksPerLine = Math.ceil(Math.ceil(frame.samplesPerLine / 8) * component.h / frame.maxH);
+          var blocksPerColumn = Math.ceil(Math.ceil(frame.scanLines / 8) * component.v / frame.maxV);
+          var blocksPerLineForMcu = mcusPerLine * component.h;
+          var blocksPerColumnForMcu = mcusPerColumn * component.v;
+          var blocksBufferSize = 64 * blocksPerColumnForMcu * (blocksPerLineForMcu + 1);
+          component.blockData = new Int16Array(blocksBufferSize);
+          component.blocksPerLine = blocksPerLine;
+          component.blocksPerColumn = blocksPerColumn;
+        }
+
+        frame.mcusPerLine = mcusPerLine;
+        frame.mcusPerColumn = mcusPerColumn;
+      }
+
+      var offset = 0;
+      var jfif = null;
+      var adobe = null;
+      var frame, resetInterval;
+      var numSOSMarkers = 0;
+      var quantizationTables = [];
+      var huffmanTablesAC = [],
+          huffmanTablesDC = [];
+      var fileMarker = readUint16();
+
+      if (fileMarker !== 0xFFD8) {
+        throw new JpegError('SOI not found');
+      }
+
+      fileMarker = readUint16();
+
+      markerLoop: while (fileMarker !== 0xFFD9) {
+        var i, j, l;
+
+        switch (fileMarker) {
+          case 0xFFE0:
+          case 0xFFE1:
+          case 0xFFE2:
+          case 0xFFE3:
+          case 0xFFE4:
+          case 0xFFE5:
+          case 0xFFE6:
+          case 0xFFE7:
+          case 0xFFE8:
+          case 0xFFE9:
+          case 0xFFEA:
+          case 0xFFEB:
+          case 0xFFEC:
+          case 0xFFED:
+          case 0xFFEE:
+          case 0xFFEF:
+          case 0xFFFE:
+            var appData = readDataBlock();
+
+            if (fileMarker === 0xFFE0) {
+              if (appData[0] === 0x4A && appData[1] === 0x46 && appData[2] === 0x49 && appData[3] === 0x46 && appData[4] === 0) {
+                jfif = {
+                  version: {
+                    major: appData[5],
+                    minor: appData[6]
+                  },
+                  densityUnits: appData[7],
+                  xDensity: appData[8] << 8 | appData[9],
+                  yDensity: appData[10] << 8 | appData[11],
+                  thumbWidth: appData[12],
+                  thumbHeight: appData[13],
+                  thumbData: appData.subarray(14, 14 + 3 * appData[12] * appData[13])
+                };
+              }
+            }
+
+            if (fileMarker === 0xFFEE) {
+              if (appData[0] === 0x41 && appData[1] === 0x64 && appData[2] === 0x6F && appData[3] === 0x62 && appData[4] === 0x65) {
+                adobe = {
+                  version: appData[5] << 8 | appData[6],
+                  flags0: appData[7] << 8 | appData[8],
+                  flags1: appData[9] << 8 | appData[10],
+                  transformCode: appData[11]
+                };
+              }
+            }
+
+            break;
+
+          case 0xFFDB:
+            var quantizationTablesLength = readUint16();
+            var quantizationTablesEnd = quantizationTablesLength + offset - 2;
+            var z;
+
+            while (offset < quantizationTablesEnd) {
+              var quantizationTableSpec = data[offset++];
+              var tableData = new Uint16Array(64);
+
+              if (quantizationTableSpec >> 4 === 0) {
+                for (j = 0; j < 64; j++) {
+                  z = dctZigZag[j];
+                  tableData[z] = data[offset++];
+                }
+              } else if (quantizationTableSpec >> 4 === 1) {
+                for (j = 0; j < 64; j++) {
+                  z = dctZigZag[j];
+                  tableData[z] = readUint16();
+                }
+              } else {
+                throw new JpegError('DQT - invalid table spec');
+              }
+
+              quantizationTables[quantizationTableSpec & 15] = tableData;
+            }
+
+            break;
+
+          case 0xFFC0:
+          case 0xFFC1:
+          case 0xFFC2:
+            if (frame) {
+              throw new JpegError('Only single frame JPEGs supported');
+            }
+
+            readUint16();
+            frame = {};
+            frame.extended = fileMarker === 0xFFC1;
+            frame.progressive = fileMarker === 0xFFC2;
+            frame.precision = data[offset++];
+            var sofScanLines = readUint16();
+            frame.scanLines = dnlScanLines || sofScanLines;
+            frame.samplesPerLine = readUint16();
+            frame.components = [];
+            frame.componentIds = {};
+            var componentsCount = data[offset++],
+                componentId;
+            var maxH = 0,
+                maxV = 0;
+
+            for (i = 0; i < componentsCount; i++) {
+              componentId = data[offset];
+              var h = data[offset + 1] >> 4;
+              var v = data[offset + 1] & 15;
+
+              if (maxH < h) {
+                maxH = h;
+              }
+
+              if (maxV < v) {
+                maxV = v;
+              }
+
+              var qId = data[offset + 2];
+              l = frame.components.push({
+                h: h,
+                v: v,
+                quantizationId: qId,
+                quantizationTable: null
+              });
+              frame.componentIds[componentId] = l - 1;
+              offset += 3;
+            }
+
+            frame.maxH = maxH;
+            frame.maxV = maxV;
+            prepareComponents(frame);
+            break;
+
+          case 0xFFC4:
+            var huffmanLength = readUint16();
+
+            for (i = 2; i < huffmanLength;) {
+              var huffmanTableSpec = data[offset++];
+              var codeLengths = new Uint8Array(16);
+              var codeLengthSum = 0;
+
+              for (j = 0; j < 16; j++, offset++) {
+                codeLengthSum += codeLengths[j] = data[offset];
+              }
+
+              var huffmanValues = new Uint8Array(codeLengthSum);
+
+              for (j = 0; j < codeLengthSum; j++, offset++) {
+                huffmanValues[j] = data[offset];
+              }
+
+              i += 17 + codeLengthSum;
+              (huffmanTableSpec >> 4 === 0 ? huffmanTablesDC : huffmanTablesAC)[huffmanTableSpec & 15] = buildHuffmanTable(codeLengths, huffmanValues);
+            }
+
+            break;
+
+          case 0xFFDD:
+            readUint16();
+            resetInterval = readUint16();
+            break;
+
+          case 0xFFDA:
+            var parseDNLMarker = ++numSOSMarkers === 1 && !dnlScanLines;
+            readUint16();
+            var selectorsCount = data[offset++];
+            var components = [],
+                component;
+
+            for (i = 0; i < selectorsCount; i++) {
+              var componentIndex = frame.componentIds[data[offset++]];
+              component = frame.components[componentIndex];
+              var tableSpec = data[offset++];
+              component.huffmanTableDC = huffmanTablesDC[tableSpec >> 4];
+              component.huffmanTableAC = huffmanTablesAC[tableSpec & 15];
+              components.push(component);
+            }
+
+            var spectralStart = data[offset++];
+            var spectralEnd = data[offset++];
+            var successiveApproximation = data[offset++];
+
+            try {
+              var processed = decodeScan(data, offset, frame, components, resetInterval, spectralStart, spectralEnd, successiveApproximation >> 4, successiveApproximation & 15, parseDNLMarker);
+              offset += processed;
+            } catch (ex) {
+              if (ex instanceof DNLMarkerError) {
+                (0, _util.warn)("".concat(ex.message, " -- attempting to re-parse the JPEG image."));
+                return this.parse(data, {
+                  dnlScanLines: ex.scanLines
+                });
+              } else if (ex instanceof EOIMarkerError) {
+                (0, _util.warn)("".concat(ex.message, " -- ignoring the rest of the image data."));
+                break markerLoop;
+              }
+
+              throw ex;
+            }
+
+            break;
+
+          case 0xFFDC:
+            offset += 4;
+            break;
+
+          case 0xFFFF:
+            if (data[offset] !== 0xFF) {
+              offset--;
+            }
+
+            break;
+
+          default:
+            if (data[offset - 3] === 0xFF && data[offset - 2] >= 0xC0 && data[offset - 2] <= 0xFE) {
+              offset -= 3;
+              break;
+            }
+
+            var nextFileMarker = findNextFileMarker(data, offset - 2);
+
+            if (nextFileMarker && nextFileMarker.invalid) {
+              (0, _util.warn)('JpegImage.parse - unexpected data, current marker is: ' + nextFileMarker.invalid);
+              offset = nextFileMarker.offset;
+              break;
+            }
+
+            throw new JpegError('unknown marker ' + fileMarker.toString(16));
+        }
+
+        fileMarker = readUint16();
+      }
+
+      this.width = frame.samplesPerLine;
+      this.height = frame.scanLines;
+      this.jfif = jfif;
+      this.adobe = adobe;
+      this.components = [];
+
+      for (i = 0; i < frame.components.length; i++) {
+        component = frame.components[i];
+        var quantizationTable = quantizationTables[component.quantizationId];
+
+        if (quantizationTable) {
+          component.quantizationTable = quantizationTable;
+        }
+
+        this.components.push({
+          output: buildComponentData(frame, component),
+          scaleX: component.h / frame.maxH,
+          scaleY: component.v / frame.maxV,
+          blocksPerLine: component.blocksPerLine,
+          blocksPerColumn: component.blocksPerColumn
+        });
+      }
+
+      this.numComponents = this.components.length;
+      return undefined;
+    },
+    _getLinearizedBlockData: function _getLinearizedBlockData(width, height) {
+      var isSourcePDF = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
+      var scaleX = this.width / width,
+          scaleY = this.height / height;
+      var component, componentScaleX, componentScaleY, blocksPerScanline;
+      var x, y, i, j, k;
+      var index;
+      var offset = 0;
+      var output;
+      var numComponents = this.components.length;
+      var dataLength = width * height * numComponents;
+      var data = new Uint8ClampedArray(dataLength);
+      var xScaleBlockOffset = new Uint32Array(width);
+      var mask3LSB = 0xfffffff8;
+
+      for (i = 0; i < numComponents; i++) {
+        component = this.components[i];
+        componentScaleX = component.scaleX * scaleX;
+        componentScaleY = component.scaleY * scaleY;
+        offset = i;
+        output = component.output;
+        blocksPerScanline = component.blocksPerLine + 1 << 3;
+
+        for (x = 0; x < width; x++) {
+          j = 0 | x * componentScaleX;
+          xScaleBlockOffset[x] = (j & mask3LSB) << 3 | j & 7;
+        }
+
+        for (y = 0; y < height; y++) {
+          j = 0 | y * componentScaleY;
+          index = blocksPerScanline * (j & mask3LSB) | (j & 7) << 3;
+
+          for (x = 0; x < width; x++) {
+            data[offset] = output[index + xScaleBlockOffset[x]];
+            offset += numComponents;
+          }
+        }
+      }
+
+      var transform = this._decodeTransform;
+
+      if (!isSourcePDF && numComponents === 4 && !transform) {
+        transform = new Int32Array([-256, 255, -256, 255, -256, 255, -256, 255]);
+      }
+
+      if (transform) {
+        for (i = 0; i < dataLength;) {
+          for (j = 0, k = 0; j < numComponents; j++, i++, k += 2) {
+            data[i] = (data[i] * transform[k] >> 8) + transform[k + 1];
+          }
+        }
+      }
+
+      return data;
+    },
+
+    get _isColorConversionNeeded() {
+      if (this.adobe) {
+        return !!this.adobe.transformCode;
+      }
+
+      if (this.numComponents === 3) {
+        if (this._colorTransform === 0) {
+          return false;
+        }
+
+        return true;
+      }
+
+      if (this._colorTransform === 1) {
+        return true;
+      }
+
+      return false;
+    },
+
+    _convertYccToRgb: function convertYccToRgb(data) {
+      var Y, Cb, Cr;
+
+      for (var i = 0, length = data.length; i < length; i += 3) {
+        Y = data[i];
+        Cb = data[i + 1];
+        Cr = data[i + 2];
+        data[i] = Y - 179.456 + 1.402 * Cr;
+        data[i + 1] = Y + 135.459 - 0.344 * Cb - 0.714 * Cr;
+        data[i + 2] = Y - 226.816 + 1.772 * Cb;
+      }
+
+      return data;
+    },
+    _convertYcckToRgb: function convertYcckToRgb(data) {
+      var Y, Cb, Cr, k;
+      var offset = 0;
+
+      for (var i = 0, length = data.length; i < length; i += 4) {
+        Y = data[i];
+        Cb = data[i + 1];
+        Cr = data[i + 2];
+        k = data[i + 3];
+        data[offset++] = -122.67195406894 + Cb * (-6.60635669420364e-5 * Cb + 0.000437130475926232 * Cr - 5.4080610064599e-5 * Y + 0.00048449797120281 * k - 0.154362151871126) + Cr * (-0.000957964378445773 * Cr + 0.000817076911346625 * Y - 0.00477271405408747 * k + 1.53380253221734) + Y * (0.000961250184130688 * Y - 0.00266257332283933 * k + 0.48357088451265) + k * (-0.000336197177618394 * k + 0.484791561490776);
+        data[offset++] = 107.268039397724 + Cb * (2.19927104525741e-5 * Cb - 0.000640992018297945 * Cr + 0.000659397001245577 * Y + 0.000426105652938837 * k - 0.176491792462875) + Cr * (-0.000778269941513683 * Cr + 0.00130872261408275 * Y + 0.000770482631801132 * k - 0.151051492775562) + Y * (0.00126935368114843 * Y - 0.00265090189010898 * k + 0.25802910206845) + k * (-0.000318913117588328 * k - 0.213742400323665);
+        data[offset++] = -20.810012546947 + Cb * (-0.000570115196973677 * Cb - 2.63409051004589e-5 * Cr + 0.0020741088115012 * Y - 0.00288260236853442 * k + 0.814272968359295) + Cr * (-1.53496057440975e-5 * Cr - 0.000132689043961446 * Y + 0.000560833691242812 * k - 0.195152027534049) + Y * (0.00174418132927582 * Y - 0.00255243321439347 * k + 0.116935020465145) + k * (-0.000343531996510555 * k + 0.24165260232407);
+      }
+
+      return data.subarray(0, offset);
+    },
+    _convertYcckToCmyk: function convertYcckToCmyk(data) {
+      var Y, Cb, Cr;
+
+      for (var i = 0, length = data.length; i < length; i += 4) {
+        Y = data[i];
+        Cb = data[i + 1];
+        Cr = data[i + 2];
+        data[i] = 434.456 - Y - 1.402 * Cr;
+        data[i + 1] = 119.541 - Y + 0.344 * Cb + 0.714 * Cr;
+        data[i + 2] = 481.816 - Y - 1.772 * Cb;
+      }
+
+      return data;
+    },
+    _convertCmykToRgb: function convertCmykToRgb(data) {
+      var c, m, y, k;
+      var offset = 0;
+      var scale = 1 / 255;
+
+      for (var i = 0, length = data.length; i < length; i += 4) {
+        c = data[i] * scale;
+        m = data[i + 1] * scale;
+        y = data[i + 2] * scale;
+        k = data[i + 3] * scale;
+        data[offset++] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k - 285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y - 17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) - k * (21.86122147463605 * k + 189.48180835922747);
+        data[offset++] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k - 79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) - k * (20.737325471181034 * k + 187.80453709719578);
+        data[offset++] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k - 14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k - 193.58209356861505) - k * (22.33816807309886 * k + 180.12613974708367);
+      }
+
+      return data.subarray(0, offset);
+    },
+    getData: function getData(_ref3) {
+      var width = _ref3.width,
+          height = _ref3.height,
+          _ref3$forceRGB = _ref3.forceRGB,
+          forceRGB = _ref3$forceRGB === void 0 ? false : _ref3$forceRGB,
+          _ref3$isSourcePDF = _ref3.isSourcePDF,
+          isSourcePDF = _ref3$isSourcePDF === void 0 ? false : _ref3$isSourcePDF;
+
+      if (this.numComponents > 4) {
+        throw new JpegError('Unsupported color mode');
+      }
+
+      var data = this._getLinearizedBlockData(width, height, isSourcePDF);
+
+      if (this.numComponents === 1 && forceRGB) {
+        var dataLength = data.length;
+        var rgbData = new Uint8ClampedArray(dataLength * 3);
+        var offset = 0;
+
+        for (var i = 0; i < dataLength; i++) {
+          var grayColor = data[i];
+          rgbData[offset++] = grayColor;
+          rgbData[offset++] = grayColor;
+          rgbData[offset++] = grayColor;
+        }
+
+        return rgbData;
+      } else if (this.numComponents === 3 && this._isColorConversionNeeded) {
+        return this._convertYccToRgb(data);
+      } else if (this.numComponents === 4) {
+        if (this._isColorConversionNeeded) {
+          if (forceRGB) {
+            return this._convertYcckToRgb(data);
+          }
+
+          return this._convertYcckToCmyk(data);
+        } else if (forceRGB) {
+          return this._convertCmykToRgb(data);
+        }
+      }
+
+      return data;
+    }
+  };
+  return JpegImage;
+}();
+
+exports.JpegImage = JpegImage;
+
+/***/ }),
+/* 166 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.JpxStream = void 0;
+
+var _stream = __w_pdfjs_require__(158);
+
+var _jpx = __w_pdfjs_require__(167);
+
+var _util = __w_pdfjs_require__(5);
+
+var JpxStream = function JpxStreamClosure() {
+  function JpxStream(stream, maybeLength, dict, params) {
+    this.stream = stream;
+    this.maybeLength = maybeLength;
+    this.dict = dict;
+    this.params = params;
+
+    _stream.DecodeStream.call(this, maybeLength);
+  }
+
+  JpxStream.prototype = Object.create(_stream.DecodeStream.prototype);
+  Object.defineProperty(JpxStream.prototype, 'bytes', {
+    get: function JpxStream_bytes() {
+      return (0, _util.shadow)(this, 'bytes', this.stream.getBytes(this.maybeLength));
+    },
+    configurable: true
+  });
+
+  JpxStream.prototype.ensureBuffer = function (requested) {};
+
+  JpxStream.prototype.readBlock = function () {
+    if (this.eof) {
+      return;
+    }
+
+    var jpxImage = new _jpx.JpxImage();
+    jpxImage.parse(this.bytes);
+    var width = jpxImage.width;
+    var height = jpxImage.height;
+    var componentsCount = jpxImage.componentsCount;
+    var tileCount = jpxImage.tiles.length;
+
+    if (tileCount === 1) {
+      this.buffer = jpxImage.tiles[0].items;
+    } else {
+      var data = new Uint8ClampedArray(width * height * componentsCount);
+
+      for (var k = 0; k < tileCount; k++) {
+        var tileComponents = jpxImage.tiles[k];
+        var tileWidth = tileComponents.width;
+        var tileHeight = tileComponents.height;
+        var tileLeft = tileComponents.left;
+        var tileTop = tileComponents.top;
+        var src = tileComponents.items;
+        var srcPosition = 0;
+        var dataPosition = (width * tileTop + tileLeft) * componentsCount;
+        var imgRowSize = width * componentsCount;
+        var tileRowSize = tileWidth * componentsCount;
+
+        for (var j = 0; j < tileHeight; j++) {
+          var rowBytes = src.subarray(srcPosition, srcPosition + tileRowSize);
+          data.set(rowBytes, dataPosition);
+          srcPosition += tileRowSize;
+          dataPosition += imgRowSize;
+        }
+      }
+
+      this.buffer = data;
+    }
+
+    this.bufferLength = this.buffer.length;
+    this.eof = true;
+  };
+
+  return JpxStream;
+}();
+
+exports.JpxStream = JpxStream;
+
+/***/ }),
+/* 167 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.JpxImage = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _arithmetic_decoder = __w_pdfjs_require__(163);
+
+var JpxError = function JpxErrorClosure() {
+  function JpxError(msg) {
+    this.message = 'JPX error: ' + msg;
+  }
+
+  JpxError.prototype = new Error();
+  JpxError.prototype.name = 'JpxError';
+  JpxError.constructor = JpxError;
+  return JpxError;
+}();
+
+var JpxImage = function JpxImageClosure() {
+  var SubbandsGainLog2 = {
+    'LL': 0,
+    'LH': 1,
+    'HL': 1,
+    'HH': 2
+  };
+
+  function JpxImage() {
+    this.failOnCorruptedImage = false;
+  }
+
+  JpxImage.prototype = {
+    parse: function JpxImage_parse(data) {
+      var head = (0, _util.readUint16)(data, 0);
+
+      if (head === 0xFF4F) {
+        this.parseCodestream(data, 0, data.length);
+        return;
+      }
+
+      var position = 0,
+          length = data.length;
+
+      while (position < length) {
+        var headerSize = 8;
+        var lbox = (0, _util.readUint32)(data, position);
+        var tbox = (0, _util.readUint32)(data, position + 4);
+        position += headerSize;
+
+        if (lbox === 1) {
+          lbox = (0, _util.readUint32)(data, position) * 4294967296 + (0, _util.readUint32)(data, position + 4);
+          position += 8;
+          headerSize += 8;
+        }
+
+        if (lbox === 0) {
+          lbox = length - position + headerSize;
+        }
+
+        if (lbox < headerSize) {
+          throw new JpxError('Invalid box field size');
+        }
+
+        var dataLength = lbox - headerSize;
+        var jumpDataLength = true;
+
+        switch (tbox) {
+          case 0x6A703268:
+            jumpDataLength = false;
+            break;
+
+          case 0x636F6C72:
+            var method = data[position];
+
+            if (method === 1) {
+              var colorspace = (0, _util.readUint32)(data, position + 3);
+
+              switch (colorspace) {
+                case 16:
+                case 17:
+                case 18:
+                  break;
+
+                default:
+                  (0, _util.warn)('Unknown colorspace ' + colorspace);
+                  break;
+              }
+            } else if (method === 2) {
+              (0, _util.info)('ICC profile not supported');
+            }
+
+            break;
+
+          case 0x6A703263:
+            this.parseCodestream(data, position, position + dataLength);
+            break;
+
+          case 0x6A502020:
+            if ((0, _util.readUint32)(data, position) !== 0x0d0a870a) {
+              (0, _util.warn)('Invalid JP2 signature');
+            }
+
+            break;
+
+          case 0x6A501A1A:
+          case 0x66747970:
+          case 0x72726571:
+          case 0x72657320:
+          case 0x69686472:
+            break;
+
+          default:
+            var headerType = String.fromCharCode(tbox >> 24 & 0xFF, tbox >> 16 & 0xFF, tbox >> 8 & 0xFF, tbox & 0xFF);
+            (0, _util.warn)('Unsupported header type ' + tbox + ' (' + headerType + ')');
+            break;
+        }
+
+        if (jumpDataLength) {
+          position += dataLength;
+        }
+      }
+    },
+    parseImageProperties: function JpxImage_parseImageProperties(stream) {
+      var newByte = stream.getByte();
+
+      while (newByte >= 0) {
+        var oldByte = newByte;
+        newByte = stream.getByte();
+        var code = oldByte << 8 | newByte;
+
+        if (code === 0xFF51) {
+          stream.skip(4);
+          var Xsiz = stream.getInt32() >>> 0;
+          var Ysiz = stream.getInt32() >>> 0;
+          var XOsiz = stream.getInt32() >>> 0;
+          var YOsiz = stream.getInt32() >>> 0;
+          stream.skip(16);
+          var Csiz = stream.getUint16();
+          this.width = Xsiz - XOsiz;
+          this.height = Ysiz - YOsiz;
+          this.componentsCount = Csiz;
+          this.bitsPerComponent = 8;
+          return;
+        }
+      }
+
+      throw new JpxError('No size marker found in JPX stream');
+    },
+    parseCodestream: function JpxImage_parseCodestream(data, start, end) {
+      var context = {};
+      var doNotRecover = false;
+
+      try {
+        var position = start;
+
+        while (position + 1 < end) {
+          var code = (0, _util.readUint16)(data, position);
+          position += 2;
+          var length = 0,
+              j,
+              sqcd,
+              spqcds,
+              spqcdSize,
+              scalarExpounded,
+              tile;
+
+          switch (code) {
+            case 0xFF4F:
+              context.mainHeader = true;
+              break;
+
+            case 0xFFD9:
+              break;
+
+            case 0xFF51:
+              length = (0, _util.readUint16)(data, position);
+              var siz = {};
+              siz.Xsiz = (0, _util.readUint32)(data, position + 4);
+              siz.Ysiz = (0, _util.readUint32)(data, position + 8);
+              siz.XOsiz = (0, _util.readUint32)(data, position + 12);
+              siz.YOsiz = (0, _util.readUint32)(data, position + 16);
+              siz.XTsiz = (0, _util.readUint32)(data, position + 20);
+              siz.YTsiz = (0, _util.readUint32)(data, position + 24);
+              siz.XTOsiz = (0, _util.readUint32)(data, position + 28);
+              siz.YTOsiz = (0, _util.readUint32)(data, position + 32);
+              var componentsCount = (0, _util.readUint16)(data, position + 36);
+              siz.Csiz = componentsCount;
+              var components = [];
+              j = position + 38;
+
+              for (var i = 0; i < componentsCount; i++) {
+                var component = {
+                  precision: (data[j] & 0x7F) + 1,
+                  isSigned: !!(data[j] & 0x80),
+                  XRsiz: data[j + 1],
+                  YRsiz: data[j + 2]
+                };
+                j += 3;
+                calculateComponentDimensions(component, siz);
+                components.push(component);
+              }
+
+              context.SIZ = siz;
+              context.components = components;
+              calculateTileGrids(context, components);
+              context.QCC = [];
+              context.COC = [];
+              break;
+
+            case 0xFF5C:
+              length = (0, _util.readUint16)(data, position);
+              var qcd = {};
+              j = position + 2;
+              sqcd = data[j++];
+
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+
+                default:
+                  throw new Error('Invalid SQcd value ' + sqcd);
+              }
+
+              qcd.noQuantization = spqcdSize === 8;
+              qcd.scalarExpounded = scalarExpounded;
+              qcd.guardBits = sqcd >> 5;
+              spqcds = [];
+
+              while (j < length + position) {
+                var spqcd = {};
+
+                if (spqcdSize === 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
+                  j += 2;
+                }
+
+                spqcds.push(spqcd);
+              }
+
+              qcd.SPqcds = spqcds;
+
+              if (context.mainHeader) {
+                context.QCD = qcd;
+              } else {
+                context.currentTile.QCD = qcd;
+                context.currentTile.QCC = [];
+              }
+
+              break;
+
+            case 0xFF5D:
+              length = (0, _util.readUint16)(data, position);
+              var qcc = {};
+              j = position + 2;
+              var cqcc;
+
+              if (context.SIZ.Csiz < 257) {
+                cqcc = data[j++];
+              } else {
+                cqcc = (0, _util.readUint16)(data, j);
+                j += 2;
+              }
+
+              sqcd = data[j++];
+
+              switch (sqcd & 0x1F) {
+                case 0:
+                  spqcdSize = 8;
+                  scalarExpounded = true;
+                  break;
+
+                case 1:
+                  spqcdSize = 16;
+                  scalarExpounded = false;
+                  break;
+
+                case 2:
+                  spqcdSize = 16;
+                  scalarExpounded = true;
+                  break;
+
+                default:
+                  throw new Error('Invalid SQcd value ' + sqcd);
+              }
+
+              qcc.noQuantization = spqcdSize === 8;
+              qcc.scalarExpounded = scalarExpounded;
+              qcc.guardBits = sqcd >> 5;
+              spqcds = [];
+
+              while (j < length + position) {
+                spqcd = {};
+
+                if (spqcdSize === 8) {
+                  spqcd.epsilon = data[j++] >> 3;
+                  spqcd.mu = 0;
+                } else {
+                  spqcd.epsilon = data[j] >> 3;
+                  spqcd.mu = (data[j] & 0x7) << 8 | data[j + 1];
+                  j += 2;
+                }
+
+                spqcds.push(spqcd);
+              }
+
+              qcc.SPqcds = spqcds;
+
+              if (context.mainHeader) {
+                context.QCC[cqcc] = qcc;
+              } else {
+                context.currentTile.QCC[cqcc] = qcc;
+              }
+
+              break;
+
+            case 0xFF52:
+              length = (0, _util.readUint16)(data, position);
+              var cod = {};
+              j = position + 2;
+              var scod = data[j++];
+              cod.entropyCoderWithCustomPrecincts = !!(scod & 1);
+              cod.sopMarkerUsed = !!(scod & 2);
+              cod.ephMarkerUsed = !!(scod & 4);
+              cod.progressionOrder = data[j++];
+              cod.layersCount = (0, _util.readUint16)(data, j);
+              j += 2;
+              cod.multipleComponentTransform = data[j++];
+              cod.decompositionLevelsCount = data[j++];
+              cod.xcb = (data[j++] & 0xF) + 2;
+              cod.ycb = (data[j++] & 0xF) + 2;
+              var blockStyle = data[j++];
+              cod.selectiveArithmeticCodingBypass = !!(blockStyle & 1);
+              cod.resetContextProbabilities = !!(blockStyle & 2);
+              cod.terminationOnEachCodingPass = !!(blockStyle & 4);
+              cod.verticallyStripe = !!(blockStyle & 8);
+              cod.predictableTermination = !!(blockStyle & 16);
+              cod.segmentationSymbolUsed = !!(blockStyle & 32);
+              cod.reversibleTransformation = data[j++];
+
+              if (cod.entropyCoderWithCustomPrecincts) {
+                var precinctsSizes = [];
+
+                while (j < length + position) {
+                  var precinctsSize = data[j++];
+                  precinctsSizes.push({
+                    PPx: precinctsSize & 0xF,
+                    PPy: precinctsSize >> 4
+                  });
+                }
+
+                cod.precinctsSizes = precinctsSizes;
+              }
+
+              var unsupported = [];
+
+              if (cod.selectiveArithmeticCodingBypass) {
+                unsupported.push('selectiveArithmeticCodingBypass');
+              }
+
+              if (cod.resetContextProbabilities) {
+                unsupported.push('resetContextProbabilities');
+              }
+
+              if (cod.terminationOnEachCodingPass) {
+                unsupported.push('terminationOnEachCodingPass');
+              }
+
+              if (cod.verticallyStripe) {
+                unsupported.push('verticallyStripe');
+              }
+
+              if (cod.predictableTermination) {
+                unsupported.push('predictableTermination');
+              }
+
+              if (unsupported.length > 0) {
+                doNotRecover = true;
+                throw new Error('Unsupported COD options (' + unsupported.join(', ') + ')');
+              }
+
+              if (context.mainHeader) {
+                context.COD = cod;
+              } else {
+                context.currentTile.COD = cod;
+                context.currentTile.COC = [];
+              }
+
+              break;
+
+            case 0xFF90:
+              length = (0, _util.readUint16)(data, position);
+              tile = {};
+              tile.index = (0, _util.readUint16)(data, position + 2);
+              tile.length = (0, _util.readUint32)(data, position + 4);
+              tile.dataEnd = tile.length + position - 2;
+              tile.partIndex = data[position + 8];
+              tile.partsCount = data[position + 9];
+              context.mainHeader = false;
+
+              if (tile.partIndex === 0) {
+                tile.COD = context.COD;
+                tile.COC = context.COC.slice(0);
+                tile.QCD = context.QCD;
+                tile.QCC = context.QCC.slice(0);
+              }
+
+              context.currentTile = tile;
+              break;
+
+            case 0xFF93:
+              tile = context.currentTile;
+
+              if (tile.partIndex === 0) {
+                initializeTile(context, tile.index);
+                buildPackets(context);
+              }
+
+              length = tile.dataEnd - position;
+              parseTilePackets(context, data, position, length);
+              break;
+
+            case 0xFF55:
+            case 0xFF57:
+            case 0xFF58:
+            case 0xFF64:
+              length = (0, _util.readUint16)(data, position);
+              break;
+
+            case 0xFF53:
+              throw new Error('Codestream code 0xFF53 (COC) is ' + 'not implemented');
+
+            default:
+              throw new Error('Unknown codestream code: ' + code.toString(16));
+          }
+
+          position += length;
+        }
+      } catch (e) {
+        if (doNotRecover || this.failOnCorruptedImage) {
+          throw new JpxError(e.message);
+        } else {
+          (0, _util.warn)('JPX: Trying to recover from: ' + e.message);
+        }
+      }
+
+      this.tiles = transformComponents(context);
+      this.width = context.SIZ.Xsiz - context.SIZ.XOsiz;
+      this.height = context.SIZ.Ysiz - context.SIZ.YOsiz;
+      this.componentsCount = context.SIZ.Csiz;
+    }
+  };
+
+  function calculateComponentDimensions(component, siz) {
+    component.x0 = Math.ceil(siz.XOsiz / component.XRsiz);
+    component.x1 = Math.ceil(siz.Xsiz / component.XRsiz);
+    component.y0 = Math.ceil(siz.YOsiz / component.YRsiz);
+    component.y1 = Math.ceil(siz.Ysiz / component.YRsiz);
+    component.width = component.x1 - component.x0;
+    component.height = component.y1 - component.y0;
+  }
+
+  function calculateTileGrids(context, components) {
+    var siz = context.SIZ;
+    var tile,
+        tiles = [];
+    var numXtiles = Math.ceil((siz.Xsiz - siz.XTOsiz) / siz.XTsiz);
+    var numYtiles = Math.ceil((siz.Ysiz - siz.YTOsiz) / siz.YTsiz);
+
+    for (var q = 0; q < numYtiles; q++) {
+      for (var p = 0; p < numXtiles; p++) {
+        tile = {};
+        tile.tx0 = Math.max(siz.XTOsiz + p * siz.XTsiz, siz.XOsiz);
+        tile.ty0 = Math.max(siz.YTOsiz + q * siz.YTsiz, siz.YOsiz);
+        tile.tx1 = Math.min(siz.XTOsiz + (p + 1) * siz.XTsiz, siz.Xsiz);
+        tile.ty1 = Math.min(siz.YTOsiz + (q + 1) * siz.YTsiz, siz.Ysiz);
+        tile.width = tile.tx1 - tile.tx0;
+        tile.height = tile.ty1 - tile.ty0;
+        tile.components = [];
+        tiles.push(tile);
+      }
+    }
+
+    context.tiles = tiles;
+    var componentsCount = siz.Csiz;
+
+    for (var i = 0, ii = componentsCount; i < ii; i++) {
+      var component = components[i];
+
+      for (var j = 0, jj = tiles.length; j < jj; j++) {
+        var tileComponent = {};
+        tile = tiles[j];
+        tileComponent.tcx0 = Math.ceil(tile.tx0 / component.XRsiz);
+        tileComponent.tcy0 = Math.ceil(tile.ty0 / component.YRsiz);
+        tileComponent.tcx1 = Math.ceil(tile.tx1 / component.XRsiz);
+        tileComponent.tcy1 = Math.ceil(tile.ty1 / component.YRsiz);
+        tileComponent.width = tileComponent.tcx1 - tileComponent.tcx0;
+        tileComponent.height = tileComponent.tcy1 - tileComponent.tcy0;
+        tile.components[i] = tileComponent;
+      }
+    }
+  }
+
+  function getBlocksDimensions(context, component, r) {
+    var codOrCoc = component.codingStyleParameters;
+    var result = {};
+
+    if (!codOrCoc.entropyCoderWithCustomPrecincts) {
+      result.PPx = 15;
+      result.PPy = 15;
+    } else {
+      result.PPx = codOrCoc.precinctsSizes[r].PPx;
+      result.PPy = codOrCoc.precinctsSizes[r].PPy;
+    }
+
+    result.xcb_ = r > 0 ? Math.min(codOrCoc.xcb, result.PPx - 1) : Math.min(codOrCoc.xcb, result.PPx);
+    result.ycb_ = r > 0 ? Math.min(codOrCoc.ycb, result.PPy - 1) : Math.min(codOrCoc.ycb, result.PPy);
+    return result;
+  }
+
+  function buildPrecincts(context, resolution, dimensions) {
+    var precinctWidth = 1 << dimensions.PPx;
+    var precinctHeight = 1 << dimensions.PPy;
+    var isZeroRes = resolution.resLevel === 0;
+    var precinctWidthInSubband = 1 << dimensions.PPx + (isZeroRes ? 0 : -1);
+    var precinctHeightInSubband = 1 << dimensions.PPy + (isZeroRes ? 0 : -1);
+    var numprecinctswide = resolution.trx1 > resolution.trx0 ? Math.ceil(resolution.trx1 / precinctWidth) - Math.floor(resolution.trx0 / precinctWidth) : 0;
+    var numprecinctshigh = resolution.try1 > resolution.try0 ? Math.ceil(resolution.try1 / precinctHeight) - Math.floor(resolution.try0 / precinctHeight) : 0;
+    var numprecincts = numprecinctswide * numprecinctshigh;
+    resolution.precinctParameters = {
+      precinctWidth: precinctWidth,
+      precinctHeight: precinctHeight,
+      numprecinctswide: numprecinctswide,
+      numprecinctshigh: numprecinctshigh,
+      numprecincts: numprecincts,
+      precinctWidthInSubband: precinctWidthInSubband,
+      precinctHeightInSubband: precinctHeightInSubband
+    };
+  }
+
+  function buildCodeblocks(context, subband, dimensions) {
+    var xcb_ = dimensions.xcb_;
+    var ycb_ = dimensions.ycb_;
+    var codeblockWidth = 1 << xcb_;
+    var codeblockHeight = 1 << ycb_;
+    var cbx0 = subband.tbx0 >> xcb_;
+    var cby0 = subband.tby0 >> ycb_;
+    var cbx1 = subband.tbx1 + codeblockWidth - 1 >> xcb_;
+    var cby1 = subband.tby1 + codeblockHeight - 1 >> ycb_;
+    var precinctParameters = subband.resolution.precinctParameters;
+    var codeblocks = [];
+    var precincts = [];
+    var i, j, codeblock, precinctNumber;
+
+    for (j = cby0; j < cby1; j++) {
+      for (i = cbx0; i < cbx1; i++) {
+        codeblock = {
+          cbx: i,
+          cby: j,
+          tbx0: codeblockWidth * i,
+          tby0: codeblockHeight * j,
+          tbx1: codeblockWidth * (i + 1),
+          tby1: codeblockHeight * (j + 1)
+        };
+        codeblock.tbx0_ = Math.max(subband.tbx0, codeblock.tbx0);
+        codeblock.tby0_ = Math.max(subband.tby0, codeblock.tby0);
+        codeblock.tbx1_ = Math.min(subband.tbx1, codeblock.tbx1);
+        codeblock.tby1_ = Math.min(subband.tby1, codeblock.tby1);
+        var pi = Math.floor((codeblock.tbx0_ - subband.tbx0) / precinctParameters.precinctWidthInSubband);
+        var pj = Math.floor((codeblock.tby0_ - subband.tby0) / precinctParameters.precinctHeightInSubband);
+        precinctNumber = pi + pj * precinctParameters.numprecinctswide;
+        codeblock.precinctNumber = precinctNumber;
+        codeblock.subbandType = subband.type;
+        codeblock.Lblock = 3;
+
+        if (codeblock.tbx1_ <= codeblock.tbx0_ || codeblock.tby1_ <= codeblock.tby0_) {
+          continue;
+        }
+
+        codeblocks.push(codeblock);
+        var precinct = precincts[precinctNumber];
+
+        if (precinct !== undefined) {
+          if (i < precinct.cbxMin) {
+            precinct.cbxMin = i;
+          } else if (i > precinct.cbxMax) {
+            precinct.cbxMax = i;
+          }
+
+          if (j < precinct.cbyMin) {
+            precinct.cbxMin = j;
+          } else if (j > precinct.cbyMax) {
+            precinct.cbyMax = j;
+          }
+        } else {
+          precincts[precinctNumber] = precinct = {
+            cbxMin: i,
+            cbyMin: j,
+            cbxMax: i,
+            cbyMax: j
+          };
+        }
+
+        codeblock.precinct = precinct;
+      }
+    }
+
+    subband.codeblockParameters = {
+      codeblockWidth: xcb_,
+      codeblockHeight: ycb_,
+      numcodeblockwide: cbx1 - cbx0 + 1,
+      numcodeblockhigh: cby1 - cby0 + 1
+    };
+    subband.codeblocks = codeblocks;
+    subband.precincts = precincts;
+  }
+
+  function createPacket(resolution, precinctNumber, layerNumber) {
+    var precinctCodeblocks = [];
+    var subbands = resolution.subbands;
+
+    for (var i = 0, ii = subbands.length; i < ii; i++) {
+      var subband = subbands[i];
+      var codeblocks = subband.codeblocks;
+
+      for (var j = 0, jj = codeblocks.length; j < jj; j++) {
+        var codeblock = codeblocks[j];
+
+        if (codeblock.precinctNumber !== precinctNumber) {
+          continue;
+        }
+
+        precinctCodeblocks.push(codeblock);
+      }
+    }
+
+    return {
+      layerNumber: layerNumber,
+      codeblocks: precinctCodeblocks
+    };
+  }
+
+  function LayerResolutionComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
+
+    var l = 0,
+        r = 0,
+        i = 0,
+        k = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      for (; l < layersCount; l++) {
+        for (; r <= maxDecompositionLevelsCount; r++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+
+            if (r > component.codingStyleParameters.decompositionLevelsCount) {
+              continue;
+            }
+
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+
+            k = 0;
+          }
+
+          i = 0;
+        }
+
+        r = 0;
+      }
+
+      throw new JpxError('Out of packets');
+    };
+  }
+
+  function ResolutionLayerComponentPositionIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var maxDecompositionLevelsCount = 0;
+
+    for (var q = 0; q < componentsCount; q++) {
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, tile.components[q].codingStyleParameters.decompositionLevelsCount);
+    }
+
+    var r = 0,
+        l = 0,
+        i = 0,
+        k = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      for (; r <= maxDecompositionLevelsCount; r++) {
+        for (; l < layersCount; l++) {
+          for (; i < componentsCount; i++) {
+            var component = tile.components[i];
+
+            if (r > component.codingStyleParameters.decompositionLevelsCount) {
+              continue;
+            }
+
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+
+            for (; k < numprecincts;) {
+              var packet = createPacket(resolution, k, l);
+              k++;
+              return packet;
+            }
+
+            k = 0;
+          }
+
+          i = 0;
+        }
+
+        l = 0;
+      }
+
+      throw new JpxError('Out of packets');
+    };
+  }
+
+  function ResolutionPositionComponentLayerIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var l, r, c, p;
+    var maxDecompositionLevelsCount = 0;
+
+    for (c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      maxDecompositionLevelsCount = Math.max(maxDecompositionLevelsCount, component.codingStyleParameters.decompositionLevelsCount);
+    }
+
+    var maxNumPrecinctsInLevel = new Int32Array(maxDecompositionLevelsCount + 1);
+
+    for (r = 0; r <= maxDecompositionLevelsCount; ++r) {
+      var maxNumPrecincts = 0;
+
+      for (c = 0; c < componentsCount; ++c) {
+        var resolutions = tile.components[c].resolutions;
+
+        if (r < resolutions.length) {
+          maxNumPrecincts = Math.max(maxNumPrecincts, resolutions[r].precinctParameters.numprecincts);
+        }
+      }
+
+      maxNumPrecinctsInLevel[r] = maxNumPrecincts;
+    }
+
+    l = 0;
+    r = 0;
+    c = 0;
+    p = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      for (; r <= maxDecompositionLevelsCount; r++) {
+        for (; p < maxNumPrecinctsInLevel[r]; p++) {
+          for (; c < componentsCount; c++) {
+            var component = tile.components[c];
+
+            if (r > component.codingStyleParameters.decompositionLevelsCount) {
+              continue;
+            }
+
+            var resolution = component.resolutions[r];
+            var numprecincts = resolution.precinctParameters.numprecincts;
+
+            if (p >= numprecincts) {
+              continue;
+            }
+
+            for (; l < layersCount;) {
+              var packet = createPacket(resolution, p, l);
+              l++;
+              return packet;
+            }
+
+            l = 0;
+          }
+
+          c = 0;
+        }
+
+        p = 0;
+      }
+
+      throw new JpxError('Out of packets');
+    };
+  }
+
+  function PositionComponentResolutionLayerIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var precinctsSizes = getPrecinctSizesInImageScale(tile);
+    var precinctsIterationSizes = precinctsSizes;
+    var l = 0,
+        r = 0,
+        c = 0,
+        px = 0,
+        py = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      for (; py < precinctsIterationSizes.maxNumHigh; py++) {
+        for (; px < precinctsIterationSizes.maxNumWide; px++) {
+          for (; c < componentsCount; c++) {
+            var component = tile.components[c];
+            var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+
+            for (; r <= decompositionLevelsCount; r++) {
+              var resolution = component.resolutions[r];
+              var sizeInImageScale = precinctsSizes.components[c].resolutions[r];
+              var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
+
+              if (k === null) {
+                continue;
+              }
+
+              for (; l < layersCount;) {
+                var packet = createPacket(resolution, k, l);
+                l++;
+                return packet;
+              }
+
+              l = 0;
+            }
+
+            r = 0;
+          }
+
+          c = 0;
+        }
+
+        px = 0;
+      }
+
+      throw new JpxError('Out of packets');
+    };
+  }
+
+  function ComponentPositionResolutionLayerIterator(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var layersCount = tile.codingStyleDefaultParameters.layersCount;
+    var componentsCount = siz.Csiz;
+    var precinctsSizes = getPrecinctSizesInImageScale(tile);
+    var l = 0,
+        r = 0,
+        c = 0,
+        px = 0,
+        py = 0;
+
+    this.nextPacket = function JpxImage_nextPacket() {
+      for (; c < componentsCount; ++c) {
+        var component = tile.components[c];
+        var precinctsIterationSizes = precinctsSizes.components[c];
+        var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+
+        for (; py < precinctsIterationSizes.maxNumHigh; py++) {
+          for (; px < precinctsIterationSizes.maxNumWide; px++) {
+            for (; r <= decompositionLevelsCount; r++) {
+              var resolution = component.resolutions[r];
+              var sizeInImageScale = precinctsIterationSizes.resolutions[r];
+              var k = getPrecinctIndexIfExist(px, py, sizeInImageScale, precinctsIterationSizes, resolution);
+
+              if (k === null) {
+                continue;
+              }
+
+              for (; l < layersCount;) {
+                var packet = createPacket(resolution, k, l);
+                l++;
+                return packet;
+              }
+
+              l = 0;
+            }
+
+            r = 0;
+          }
+
+          px = 0;
+        }
+
+        py = 0;
+      }
+
+      throw new JpxError('Out of packets');
+    };
+  }
+
+  function getPrecinctIndexIfExist(pxIndex, pyIndex, sizeInImageScale, precinctIterationSizes, resolution) {
+    var posX = pxIndex * precinctIterationSizes.minWidth;
+    var posY = pyIndex * precinctIterationSizes.minHeight;
+
+    if (posX % sizeInImageScale.width !== 0 || posY % sizeInImageScale.height !== 0) {
+      return null;
+    }
+
+    var startPrecinctRowIndex = posY / sizeInImageScale.width * resolution.precinctParameters.numprecinctswide;
+    return posX / sizeInImageScale.height + startPrecinctRowIndex;
+  }
+
+  function getPrecinctSizesInImageScale(tile) {
+    var componentsCount = tile.components.length;
+    var minWidth = Number.MAX_VALUE;
+    var minHeight = Number.MAX_VALUE;
+    var maxNumWide = 0;
+    var maxNumHigh = 0;
+    var sizePerComponent = new Array(componentsCount);
+
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+      var sizePerResolution = new Array(decompositionLevelsCount + 1);
+      var minWidthCurrentComponent = Number.MAX_VALUE;
+      var minHeightCurrentComponent = Number.MAX_VALUE;
+      var maxNumWideCurrentComponent = 0;
+      var maxNumHighCurrentComponent = 0;
+      var scale = 1;
+
+      for (var r = decompositionLevelsCount; r >= 0; --r) {
+        var resolution = component.resolutions[r];
+        var widthCurrentResolution = scale * resolution.precinctParameters.precinctWidth;
+        var heightCurrentResolution = scale * resolution.precinctParameters.precinctHeight;
+        minWidthCurrentComponent = Math.min(minWidthCurrentComponent, widthCurrentResolution);
+        minHeightCurrentComponent = Math.min(minHeightCurrentComponent, heightCurrentResolution);
+        maxNumWideCurrentComponent = Math.max(maxNumWideCurrentComponent, resolution.precinctParameters.numprecinctswide);
+        maxNumHighCurrentComponent = Math.max(maxNumHighCurrentComponent, resolution.precinctParameters.numprecinctshigh);
+        sizePerResolution[r] = {
+          width: widthCurrentResolution,
+          height: heightCurrentResolution
+        };
+        scale <<= 1;
+      }
+
+      minWidth = Math.min(minWidth, minWidthCurrentComponent);
+      minHeight = Math.min(minHeight, minHeightCurrentComponent);
+      maxNumWide = Math.max(maxNumWide, maxNumWideCurrentComponent);
+      maxNumHigh = Math.max(maxNumHigh, maxNumHighCurrentComponent);
+      sizePerComponent[c] = {
+        resolutions: sizePerResolution,
+        minWidth: minWidthCurrentComponent,
+        minHeight: minHeightCurrentComponent,
+        maxNumWide: maxNumWideCurrentComponent,
+        maxNumHigh: maxNumHighCurrentComponent
+      };
+    }
+
+    return {
+      components: sizePerComponent,
+      minWidth: minWidth,
+      minHeight: minHeight,
+      maxNumWide: maxNumWide,
+      maxNumHigh: maxNumHigh
+    };
+  }
+
+  function buildPackets(context) {
+    var siz = context.SIZ;
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var componentsCount = siz.Csiz;
+
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var decompositionLevelsCount = component.codingStyleParameters.decompositionLevelsCount;
+      var resolutions = [];
+      var subbands = [];
+
+      for (var r = 0; r <= decompositionLevelsCount; r++) {
+        var blocksDimensions = getBlocksDimensions(context, component, r);
+        var resolution = {};
+        var scale = 1 << decompositionLevelsCount - r;
+        resolution.trx0 = Math.ceil(component.tcx0 / scale);
+        resolution.try0 = Math.ceil(component.tcy0 / scale);
+        resolution.trx1 = Math.ceil(component.tcx1 / scale);
+        resolution.try1 = Math.ceil(component.tcy1 / scale);
+        resolution.resLevel = r;
+        buildPrecincts(context, resolution, blocksDimensions);
+        resolutions.push(resolution);
+        var subband;
+
+        if (r === 0) {
+          subband = {};
+          subband.type = 'LL';
+          subband.tbx0 = Math.ceil(component.tcx0 / scale);
+          subband.tby0 = Math.ceil(component.tcy0 / scale);
+          subband.tbx1 = Math.ceil(component.tcx1 / scale);
+          subband.tby1 = Math.ceil(component.tcy1 / scale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolution.subbands = [subband];
+        } else {
+          var bscale = 1 << decompositionLevelsCount - r + 1;
+          var resolutionSubbands = [];
+          subband = {};
+          subband.type = 'HL';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+          subband = {};
+          subband.type = 'LH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+          subband = {};
+          subband.type = 'HH';
+          subband.tbx0 = Math.ceil(component.tcx0 / bscale - 0.5);
+          subband.tby0 = Math.ceil(component.tcy0 / bscale - 0.5);
+          subband.tbx1 = Math.ceil(component.tcx1 / bscale - 0.5);
+          subband.tby1 = Math.ceil(component.tcy1 / bscale - 0.5);
+          subband.resolution = resolution;
+          buildCodeblocks(context, subband, blocksDimensions);
+          subbands.push(subband);
+          resolutionSubbands.push(subband);
+          resolution.subbands = resolutionSubbands;
+        }
+      }
+
+      component.resolutions = resolutions;
+      component.subbands = subbands;
+    }
+
+    var progressionOrder = tile.codingStyleDefaultParameters.progressionOrder;
+
+    switch (progressionOrder) {
+      case 0:
+        tile.packetsIterator = new LayerResolutionComponentPositionIterator(context);
+        break;
+
+      case 1:
+        tile.packetsIterator = new ResolutionLayerComponentPositionIterator(context);
+        break;
+
+      case 2:
+        tile.packetsIterator = new ResolutionPositionComponentLayerIterator(context);
+        break;
+
+      case 3:
+        tile.packetsIterator = new PositionComponentResolutionLayerIterator(context);
+        break;
+
+      case 4:
+        tile.packetsIterator = new ComponentPositionResolutionLayerIterator(context);
+        break;
+
+      default:
+        throw new JpxError("Unsupported progression order ".concat(progressionOrder));
+    }
+  }
+
+  function parseTilePackets(context, data, offset, dataLength) {
+    var position = 0;
+    var buffer,
+        bufferSize = 0,
+        skipNextBit = false;
+
+    function readBits(count) {
+      while (bufferSize < count) {
+        var b = data[offset + position];
+        position++;
+
+        if (skipNextBit) {
+          buffer = buffer << 7 | b;
+          bufferSize += 7;
+          skipNextBit = false;
+        } else {
+          buffer = buffer << 8 | b;
+          bufferSize += 8;
+        }
+
+        if (b === 0xFF) {
+          skipNextBit = true;
+        }
+      }
+
+      bufferSize -= count;
+      return buffer >>> bufferSize & (1 << count) - 1;
+    }
+
+    function skipMarkerIfEqual(value) {
+      if (data[offset + position - 1] === 0xFF && data[offset + position] === value) {
+        skipBytes(1);
+        return true;
+      } else if (data[offset + position] === 0xFF && data[offset + position + 1] === value) {
+        skipBytes(2);
+        return true;
+      }
+
+      return false;
+    }
+
+    function skipBytes(count) {
+      position += count;
+    }
+
+    function alignToByte() {
+      bufferSize = 0;
+
+      if (skipNextBit) {
+        position++;
+        skipNextBit = false;
+      }
+    }
+
+    function readCodingpasses() {
+      if (readBits(1) === 0) {
+        return 1;
+      }
+
+      if (readBits(1) === 0) {
+        return 2;
+      }
+
+      var value = readBits(2);
+
+      if (value < 3) {
+        return value + 3;
+      }
+
+      value = readBits(5);
+
+      if (value < 31) {
+        return value + 6;
+      }
+
+      value = readBits(7);
+      return value + 37;
+    }
+
+    var tileIndex = context.currentTile.index;
+    var tile = context.tiles[tileIndex];
+    var sopMarkerUsed = context.COD.sopMarkerUsed;
+    var ephMarkerUsed = context.COD.ephMarkerUsed;
+    var packetsIterator = tile.packetsIterator;
+
+    while (position < dataLength) {
+      alignToByte();
+
+      if (sopMarkerUsed && skipMarkerIfEqual(0x91)) {
+        skipBytes(4);
+      }
+
+      var packet = packetsIterator.nextPacket();
+
+      if (!readBits(1)) {
+        continue;
+      }
+
+      var layerNumber = packet.layerNumber;
+      var queue = [],
+          codeblock;
+
+      for (var i = 0, ii = packet.codeblocks.length; i < ii; i++) {
+        codeblock = packet.codeblocks[i];
+        var precinct = codeblock.precinct;
+        var codeblockColumn = codeblock.cbx - precinct.cbxMin;
+        var codeblockRow = codeblock.cby - precinct.cbyMin;
+        var codeblockIncluded = false;
+        var firstTimeInclusion = false;
+        var valueReady;
+
+        if (codeblock['included'] !== undefined) {
+          codeblockIncluded = !!readBits(1);
+        } else {
+          precinct = codeblock.precinct;
+          var inclusionTree, zeroBitPlanesTree;
+
+          if (precinct['inclusionTree'] !== undefined) {
+            inclusionTree = precinct.inclusionTree;
+          } else {
+            var width = precinct.cbxMax - precinct.cbxMin + 1;
+            var height = precinct.cbyMax - precinct.cbyMin + 1;
+            inclusionTree = new InclusionTree(width, height, layerNumber);
+            zeroBitPlanesTree = new TagTree(width, height);
+            precinct.inclusionTree = inclusionTree;
+            precinct.zeroBitPlanesTree = zeroBitPlanesTree;
+          }
+
+          if (inclusionTree.reset(codeblockColumn, codeblockRow, layerNumber)) {
+            while (true) {
+              if (readBits(1)) {
+                valueReady = !inclusionTree.nextLevel();
+
+                if (valueReady) {
+                  codeblock.included = true;
+                  codeblockIncluded = firstTimeInclusion = true;
+                  break;
+                }
+              } else {
+                inclusionTree.incrementValue(layerNumber);
+                break;
+              }
+            }
+          }
+        }
+
+        if (!codeblockIncluded) {
+          continue;
+        }
+
+        if (firstTimeInclusion) {
+          zeroBitPlanesTree = precinct.zeroBitPlanesTree;
+          zeroBitPlanesTree.reset(codeblockColumn, codeblockRow);
+
+          while (true) {
+            if (readBits(1)) {
+              valueReady = !zeroBitPlanesTree.nextLevel();
+
+              if (valueReady) {
+                break;
+              }
+            } else {
+              zeroBitPlanesTree.incrementValue();
+            }
+          }
+
+          codeblock.zeroBitPlanes = zeroBitPlanesTree.value;
+        }
+
+        var codingpasses = readCodingpasses();
+
+        while (readBits(1)) {
+          codeblock.Lblock++;
+        }
+
+        var codingpassesLog2 = (0, _util.log2)(codingpasses);
+        var bits = (codingpasses < 1 << codingpassesLog2 ? codingpassesLog2 - 1 : codingpassesLog2) + codeblock.Lblock;
+        var codedDataLength = readBits(bits);
+        queue.push({
+          codeblock: codeblock,
+          codingpasses: codingpasses,
+          dataLength: codedDataLength
+        });
+      }
+
+      alignToByte();
+
+      if (ephMarkerUsed) {
+        skipMarkerIfEqual(0x92);
+      }
+
+      while (queue.length > 0) {
+        var packetItem = queue.shift();
+        codeblock = packetItem.codeblock;
+
+        if (codeblock['data'] === undefined) {
+          codeblock.data = [];
+        }
+
+        codeblock.data.push({
+          data: data,
+          start: offset + position,
+          end: offset + position + packetItem.dataLength,
+          codingpasses: packetItem.codingpasses
+        });
+        position += packetItem.dataLength;
+      }
+    }
+
+    return position;
+  }
+
+  function copyCoefficients(coefficients, levelWidth, levelHeight, subband, delta, mb, reversible, segmentationSymbolUsed) {
+    var x0 = subband.tbx0;
+    var y0 = subband.tby0;
+    var width = subband.tbx1 - subband.tbx0;
+    var codeblocks = subband.codeblocks;
+    var right = subband.type.charAt(0) === 'H' ? 1 : 0;
+    var bottom = subband.type.charAt(1) === 'H' ? levelWidth : 0;
+
+    for (var i = 0, ii = codeblocks.length; i < ii; ++i) {
+      var codeblock = codeblocks[i];
+      var blockWidth = codeblock.tbx1_ - codeblock.tbx0_;
+      var blockHeight = codeblock.tby1_ - codeblock.tby0_;
+
+      if (blockWidth === 0 || blockHeight === 0) {
+        continue;
+      }
+
+      if (codeblock['data'] === undefined) {
+        continue;
+      }
+
+      var bitModel, currentCodingpassType;
+      bitModel = new BitModel(blockWidth, blockHeight, codeblock.subbandType, codeblock.zeroBitPlanes, mb);
+      currentCodingpassType = 2;
+      var data = codeblock.data,
+          totalLength = 0,
+          codingpasses = 0;
+      var j, jj, dataItem;
+
+      for (j = 0, jj = data.length; j < jj; j++) {
+        dataItem = data[j];
+        totalLength += dataItem.end - dataItem.start;
+        codingpasses += dataItem.codingpasses;
+      }
+
+      var encodedData = new Uint8Array(totalLength);
+      var position = 0;
+
+      for (j = 0, jj = data.length; j < jj; j++) {
+        dataItem = data[j];
+        var chunk = dataItem.data.subarray(dataItem.start, dataItem.end);
+        encodedData.set(chunk, position);
+        position += chunk.length;
+      }
+
+      var decoder = new _arithmetic_decoder.ArithmeticDecoder(encodedData, 0, totalLength);
+      bitModel.setDecoder(decoder);
+
+      for (j = 0; j < codingpasses; j++) {
+        switch (currentCodingpassType) {
+          case 0:
+            bitModel.runSignificancePropagationPass();
+            break;
+
+          case 1:
+            bitModel.runMagnitudeRefinementPass();
+            break;
+
+          case 2:
+            bitModel.runCleanupPass();
+
+            if (segmentationSymbolUsed) {
+              bitModel.checkSegmentationSymbol();
+            }
+
+            break;
+        }
+
+        currentCodingpassType = (currentCodingpassType + 1) % 3;
+      }
+
+      var offset = codeblock.tbx0_ - x0 + (codeblock.tby0_ - y0) * width;
+      var sign = bitModel.coefficentsSign;
+      var magnitude = bitModel.coefficentsMagnitude;
+      var bitsDecoded = bitModel.bitsDecoded;
+      var magnitudeCorrection = reversible ? 0 : 0.5;
+      var k, n, nb;
+      position = 0;
+      var interleave = subband.type !== 'LL';
+
+      for (j = 0; j < blockHeight; j++) {
+        var row = offset / width | 0;
+        var levelOffset = 2 * row * (levelWidth - width) + right + bottom;
+
+        for (k = 0; k < blockWidth; k++) {
+          n = magnitude[position];
+
+          if (n !== 0) {
+            n = (n + magnitudeCorrection) * delta;
+
+            if (sign[position] !== 0) {
+              n = -n;
+            }
+
+            nb = bitsDecoded[position];
+            var pos = interleave ? levelOffset + (offset << 1) : offset;
+
+            if (reversible && nb >= mb) {
+              coefficients[pos] = n;
+            } else {
+              coefficients[pos] = n * (1 << mb - nb);
+            }
+          }
+
+          offset++;
+          position++;
+        }
+
+        offset += width - blockWidth;
+      }
+    }
+  }
+
+  function transformTile(context, tile, c) {
+    var component = tile.components[c];
+    var codingStyleParameters = component.codingStyleParameters;
+    var quantizationParameters = component.quantizationParameters;
+    var decompositionLevelsCount = codingStyleParameters.decompositionLevelsCount;
+    var spqcds = quantizationParameters.SPqcds;
+    var scalarExpounded = quantizationParameters.scalarExpounded;
+    var guardBits = quantizationParameters.guardBits;
+    var segmentationSymbolUsed = codingStyleParameters.segmentationSymbolUsed;
+    var precision = context.components[c].precision;
+    var reversible = codingStyleParameters.reversibleTransformation;
+    var transform = reversible ? new ReversibleTransform() : new IrreversibleTransform();
+    var subbandCoefficients = [];
+    var b = 0;
+
+    for (var i = 0; i <= decompositionLevelsCount; i++) {
+      var resolution = component.resolutions[i];
+      var width = resolution.trx1 - resolution.trx0;
+      var height = resolution.try1 - resolution.try0;
+      var coefficients = new Float32Array(width * height);
+
+      for (var j = 0, jj = resolution.subbands.length; j < jj; j++) {
+        var mu, epsilon;
+
+        if (!scalarExpounded) {
+          mu = spqcds[0].mu;
+          epsilon = spqcds[0].epsilon + (i > 0 ? 1 - i : 0);
+        } else {
+          mu = spqcds[b].mu;
+          epsilon = spqcds[b].epsilon;
+          b++;
+        }
+
+        var subband = resolution.subbands[j];
+        var gainLog2 = SubbandsGainLog2[subband.type];
+        var delta = reversible ? 1 : Math.pow(2, precision + gainLog2 - epsilon) * (1 + mu / 2048);
+        var mb = guardBits + epsilon - 1;
+        copyCoefficients(coefficients, width, height, subband, delta, mb, reversible, segmentationSymbolUsed);
+      }
+
+      subbandCoefficients.push({
+        width: width,
+        height: height,
+        items: coefficients
+      });
+    }
+
+    var result = transform.calculate(subbandCoefficients, component.tcx0, component.tcy0);
+    return {
+      left: component.tcx0,
+      top: component.tcy0,
+      width: result.width,
+      height: result.height,
+      items: result.items
+    };
+  }
+
+  function transformComponents(context) {
+    var siz = context.SIZ;
+    var components = context.components;
+    var componentsCount = siz.Csiz;
+    var resultImages = [];
+
+    for (var i = 0, ii = context.tiles.length; i < ii; i++) {
+      var tile = context.tiles[i];
+      var transformedTiles = [];
+      var c;
+
+      for (c = 0; c < componentsCount; c++) {
+        transformedTiles[c] = transformTile(context, tile, c);
+      }
+
+      var tile0 = transformedTiles[0];
+      var out = new Uint8ClampedArray(tile0.items.length * componentsCount);
+      var result = {
+        left: tile0.left,
+        top: tile0.top,
+        width: tile0.width,
+        height: tile0.height,
+        items: out
+      };
+      var shift, offset;
+      var pos = 0,
+          j,
+          jj,
+          y0,
+          y1,
+          y2;
+
+      if (tile.codingStyleDefaultParameters.multipleComponentTransform) {
+        var fourComponents = componentsCount === 4;
+        var y0items = transformedTiles[0].items;
+        var y1items = transformedTiles[1].items;
+        var y2items = transformedTiles[2].items;
+        var y3items = fourComponents ? transformedTiles[3].items : null;
+        shift = components[0].precision - 8;
+        offset = (128 << shift) + 0.5;
+        var component0 = tile.components[0];
+        var alpha01 = componentsCount - 3;
+        jj = y0items.length;
+
+        if (!component0.codingStyleParameters.reversibleTransformation) {
+          for (j = 0; j < jj; j++, pos += alpha01) {
+            y0 = y0items[j] + offset;
+            y1 = y1items[j];
+            y2 = y2items[j];
+            out[pos++] = y0 + 1.402 * y2 >> shift;
+            out[pos++] = y0 - 0.34413 * y1 - 0.71414 * y2 >> shift;
+            out[pos++] = y0 + 1.772 * y1 >> shift;
+          }
+        } else {
+          for (j = 0; j < jj; j++, pos += alpha01) {
+            y0 = y0items[j] + offset;
+            y1 = y1items[j];
+            y2 = y2items[j];
+            var g = y0 - (y2 + y1 >> 2);
+            out[pos++] = g + y2 >> shift;
+            out[pos++] = g >> shift;
+            out[pos++] = g + y1 >> shift;
+          }
+        }
+
+        if (fourComponents) {
+          for (j = 0, pos = 3; j < jj; j++, pos += 4) {
+            out[pos] = y3items[j] + offset >> shift;
+          }
+        }
+      } else {
+        for (c = 0; c < componentsCount; c++) {
+          var items = transformedTiles[c].items;
+          shift = components[c].precision - 8;
+          offset = (128 << shift) + 0.5;
+
+          for (pos = c, j = 0, jj = items.length; j < jj; j++) {
+            out[pos] = items[j] + offset >> shift;
+            pos += componentsCount;
+          }
+        }
+      }
+
+      resultImages.push(result);
+    }
+
+    return resultImages;
+  }
+
+  function initializeTile(context, tileIndex) {
+    var siz = context.SIZ;
+    var componentsCount = siz.Csiz;
+    var tile = context.tiles[tileIndex];
+
+    for (var c = 0; c < componentsCount; c++) {
+      var component = tile.components[c];
+      var qcdOrQcc = context.currentTile.QCC[c] !== undefined ? context.currentTile.QCC[c] : context.currentTile.QCD;
+      component.quantizationParameters = qcdOrQcc;
+      var codOrCoc = context.currentTile.COC[c] !== undefined ? context.currentTile.COC[c] : context.currentTile.COD;
+      component.codingStyleParameters = codOrCoc;
+    }
+
+    tile.codingStyleDefaultParameters = context.currentTile.COD;
+  }
+
+  var TagTree = function TagTreeClosure() {
+    function TagTree(width, height) {
+      var levelsLength = (0, _util.log2)(Math.max(width, height)) + 1;
+      this.levels = [];
+
+      for (var i = 0; i < levelsLength; i++) {
+        var level = {
+          width: width,
+          height: height,
+          items: []
+        };
+        this.levels.push(level);
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
+    }
+
+    TagTree.prototype = {
+      reset: function TagTree_reset(i, j) {
+        var currentLevel = 0,
+            value = 0,
+            level;
+
+        while (currentLevel < this.levels.length) {
+          level = this.levels[currentLevel];
+          var index = i + j * level.width;
+
+          if (level.items[index] !== undefined) {
+            value = level.items[index];
+            break;
+          }
+
+          level.index = index;
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
+        }
+
+        currentLevel--;
+        level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        this.currentLevel = currentLevel;
+        delete this.value;
+      },
+      incrementValue: function TagTree_incrementValue() {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index]++;
+      },
+      nextLevel: function TagTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        currentLevel--;
+
+        if (currentLevel < 0) {
+          this.value = value;
+          return false;
+        }
+
+        this.currentLevel = currentLevel;
+        level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
+      }
+    };
+    return TagTree;
+  }();
+
+  var InclusionTree = function InclusionTreeClosure() {
+    function InclusionTree(width, height, defaultValue) {
+      var levelsLength = (0, _util.log2)(Math.max(width, height)) + 1;
+      this.levels = [];
+
+      for (var i = 0; i < levelsLength; i++) {
+        var items = new Uint8Array(width * height);
+
+        for (var j = 0, jj = items.length; j < jj; j++) {
+          items[j] = defaultValue;
+        }
+
+        var level = {
+          width: width,
+          height: height,
+          items: items
+        };
+        this.levels.push(level);
+        width = Math.ceil(width / 2);
+        height = Math.ceil(height / 2);
+      }
+    }
+
+    InclusionTree.prototype = {
+      reset: function InclusionTree_reset(i, j, stopValue) {
+        var currentLevel = 0;
+
+        while (currentLevel < this.levels.length) {
+          var level = this.levels[currentLevel];
+          var index = i + j * level.width;
+          level.index = index;
+          var value = level.items[index];
+
+          if (value === 0xFF) {
+            break;
+          }
+
+          if (value > stopValue) {
+            this.currentLevel = currentLevel;
+            this.propagateValues();
+            return false;
+          }
+
+          i >>= 1;
+          j >>= 1;
+          currentLevel++;
+        }
+
+        this.currentLevel = currentLevel - 1;
+        return true;
+      },
+      incrementValue: function InclusionTree_incrementValue(stopValue) {
+        var level = this.levels[this.currentLevel];
+        level.items[level.index] = stopValue + 1;
+        this.propagateValues();
+      },
+      propagateValues: function InclusionTree_propagateValues() {
+        var levelIndex = this.currentLevel;
+        var level = this.levels[levelIndex];
+        var currentValue = level.items[level.index];
+
+        while (--levelIndex >= 0) {
+          level = this.levels[levelIndex];
+          level.items[level.index] = currentValue;
+        }
+      },
+      nextLevel: function InclusionTree_nextLevel() {
+        var currentLevel = this.currentLevel;
+        var level = this.levels[currentLevel];
+        var value = level.items[level.index];
+        level.items[level.index] = 0xFF;
+        currentLevel--;
+
+        if (currentLevel < 0) {
+          return false;
+        }
+
+        this.currentLevel = currentLevel;
+        level = this.levels[currentLevel];
+        level.items[level.index] = value;
+        return true;
+      }
+    };
+    return InclusionTree;
+  }();
+
+  var BitModel = function BitModelClosure() {
+    var UNIFORM_CONTEXT = 17;
+    var RUNLENGTH_CONTEXT = 18;
+    var LLAndLHContextsLabel = new Uint8Array([0, 5, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 1, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8, 0, 0, 0, 0, 0, 2, 6, 8, 0, 3, 7, 8, 0, 4, 7, 8]);
+    var HLContextLabel = new Uint8Array([0, 3, 4, 0, 5, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 1, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8, 0, 0, 0, 0, 0, 2, 3, 4, 0, 6, 7, 7, 0, 8, 8, 8]);
+    var HHContextLabel = new Uint8Array([0, 1, 2, 0, 1, 2, 2, 0, 2, 2, 2, 0, 0, 0, 0, 0, 3, 4, 5, 0, 4, 5, 5, 0, 5, 5, 5, 0, 0, 0, 0, 0, 6, 7, 7, 0, 7, 7, 7, 0, 7, 7, 7, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8, 0, 0, 0, 0, 0, 8, 8, 8, 0, 8, 8, 8, 0, 8, 8, 8]);
+
+    function BitModel(width, height, subband, zeroBitPlanes, mb) {
+      this.width = width;
+      this.height = height;
+      this.contextLabelTable = subband === 'HH' ? HHContextLabel : subband === 'HL' ? HLContextLabel : LLAndLHContextsLabel;
+      var coefficientCount = width * height;
+      this.neighborsSignificance = new Uint8Array(coefficientCount);
+      this.coefficentsSign = new Uint8Array(coefficientCount);
+      this.coefficentsMagnitude = mb > 14 ? new Uint32Array(coefficientCount) : mb > 6 ? new Uint16Array(coefficientCount) : new Uint8Array(coefficientCount);
+      this.processingFlags = new Uint8Array(coefficientCount);
+      var bitsDecoded = new Uint8Array(coefficientCount);
+
+      if (zeroBitPlanes !== 0) {
+        for (var i = 0; i < coefficientCount; i++) {
+          bitsDecoded[i] = zeroBitPlanes;
+        }
+      }
+
+      this.bitsDecoded = bitsDecoded;
+      this.reset();
+    }
+
+    BitModel.prototype = {
+      setDecoder: function BitModel_setDecoder(decoder) {
+        this.decoder = decoder;
+      },
+      reset: function BitModel_reset() {
+        this.contexts = new Int8Array(19);
+        this.contexts[0] = 4 << 1 | 0;
+        this.contexts[UNIFORM_CONTEXT] = 46 << 1 | 0;
+        this.contexts[RUNLENGTH_CONTEXT] = 3 << 1 | 0;
+      },
+      setNeighborsSignificance: function BitModel_setNeighborsSignificance(row, column, index) {
+        var neighborsSignificance = this.neighborsSignificance;
+        var width = this.width,
+            height = this.height;
+        var left = column > 0;
+        var right = column + 1 < width;
+        var i;
+
+        if (row > 0) {
+          i = index - width;
+
+          if (left) {
+            neighborsSignificance[i - 1] += 0x10;
+          }
+
+          if (right) {
+            neighborsSignificance[i + 1] += 0x10;
+          }
+
+          neighborsSignificance[i] += 0x04;
+        }
+
+        if (row + 1 < height) {
+          i = index + width;
+
+          if (left) {
+            neighborsSignificance[i - 1] += 0x10;
+          }
+
+          if (right) {
+            neighborsSignificance[i + 1] += 0x10;
+          }
+
+          neighborsSignificance[i] += 0x04;
+        }
+
+        if (left) {
+          neighborsSignificance[index - 1] += 0x01;
+        }
+
+        if (right) {
+          neighborsSignificance[index + 1] += 0x01;
+        }
+
+        neighborsSignificance[index] |= 0x80;
+      },
+      runSignificancePropagationPass: function BitModel_runSignificancePropagationPass() {
+        var decoder = this.decoder;
+        var width = this.width,
+            height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var neighborsSignificance = this.neighborsSignificance;
+        var processingFlags = this.processingFlags;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        var processedInverseMask = ~1;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+
+        for (var i0 = 0; i0 < height; i0 += 4) {
+          for (var j = 0; j < width; j++) {
+            var index = i0 * width + j;
+
+            for (var i1 = 0; i1 < 4; i1++, index += width) {
+              var i = i0 + i1;
+
+              if (i >= height) {
+                break;
+              }
+
+              processingFlags[index] &= processedInverseMask;
+
+              if (coefficentsMagnitude[index] || !neighborsSignificance[index]) {
+                continue;
+              }
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              var decision = decoder.readBit(contexts, contextLabel);
+
+              if (decision) {
+                var sign = this.decodeSignBit(i, j, index);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j, index);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
+            }
+          }
+        }
+      },
+      decodeSignBit: function BitModel_decodeSignBit(row, column, index) {
+        var width = this.width,
+            height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contribution, sign0, sign1, significance1;
+        var contextLabel, decoded;
+        significance1 = column > 0 && coefficentsMagnitude[index - 1] !== 0;
+
+        if (column + 1 < width && coefficentsMagnitude[index + 1] !== 0) {
+          sign1 = coefficentsSign[index + 1];
+
+          if (significance1) {
+            sign0 = coefficentsSign[index - 1];
+            contribution = 1 - sign1 - sign0;
+          } else {
+            contribution = 1 - sign1 - sign1;
+          }
+        } else if (significance1) {
+          sign0 = coefficentsSign[index - 1];
+          contribution = 1 - sign0 - sign0;
+        } else {
+          contribution = 0;
+        }
+
+        var horizontalContribution = 3 * contribution;
+        significance1 = row > 0 && coefficentsMagnitude[index - width] !== 0;
+
+        if (row + 1 < height && coefficentsMagnitude[index + width] !== 0) {
+          sign1 = coefficentsSign[index + width];
+
+          if (significance1) {
+            sign0 = coefficentsSign[index - width];
+            contribution = 1 - sign1 - sign0 + horizontalContribution;
+          } else {
+            contribution = 1 - sign1 - sign1 + horizontalContribution;
+          }
+        } else if (significance1) {
+          sign0 = coefficentsSign[index - width];
+          contribution = 1 - sign0 - sign0 + horizontalContribution;
+        } else {
+          contribution = horizontalContribution;
+        }
+
+        if (contribution >= 0) {
+          contextLabel = 9 + contribution;
+          decoded = this.decoder.readBit(this.contexts, contextLabel);
+        } else {
+          contextLabel = 9 - contribution;
+          decoded = this.decoder.readBit(this.contexts, contextLabel) ^ 1;
+        }
+
+        return decoded;
+      },
+      runMagnitudeRefinementPass: function BitModel_runMagnitudeRefinementPass() {
+        var decoder = this.decoder;
+        var width = this.width,
+            height = this.height;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var neighborsSignificance = this.neighborsSignificance;
+        var contexts = this.contexts;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        var length = width * height;
+        var width4 = width * 4;
+
+        for (var index0 = 0, indexNext; index0 < length; index0 = indexNext) {
+          indexNext = Math.min(length, index0 + width4);
+
+          for (var j = 0; j < width; j++) {
+            for (var index = index0 + j; index < indexNext; index += width) {
+              if (!coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
+                continue;
+              }
+
+              var contextLabel = 16;
+
+              if ((processingFlags[index] & firstMagnitudeBitMask) !== 0) {
+                processingFlags[index] ^= firstMagnitudeBitMask;
+                var significance = neighborsSignificance[index] & 127;
+                contextLabel = significance === 0 ? 15 : 14;
+              }
+
+              var bit = decoder.readBit(contexts, contextLabel);
+              coefficentsMagnitude[index] = coefficentsMagnitude[index] << 1 | bit;
+              bitsDecoded[index]++;
+              processingFlags[index] |= processedMask;
+            }
+          }
+        }
+      },
+      runCleanupPass: function BitModel_runCleanupPass() {
+        var decoder = this.decoder;
+        var width = this.width,
+            height = this.height;
+        var neighborsSignificance = this.neighborsSignificance;
+        var coefficentsMagnitude = this.coefficentsMagnitude;
+        var coefficentsSign = this.coefficentsSign;
+        var contexts = this.contexts;
+        var labels = this.contextLabelTable;
+        var bitsDecoded = this.bitsDecoded;
+        var processingFlags = this.processingFlags;
+        var processedMask = 1;
+        var firstMagnitudeBitMask = 2;
+        var oneRowDown = width;
+        var twoRowsDown = width * 2;
+        var threeRowsDown = width * 3;
+        var iNext;
+
+        for (var i0 = 0; i0 < height; i0 = iNext) {
+          iNext = Math.min(i0 + 4, height);
+          var indexBase = i0 * width;
+          var checkAllEmpty = i0 + 3 < height;
+
+          for (var j = 0; j < width; j++) {
+            var index0 = indexBase + j;
+            var allEmpty = checkAllEmpty && processingFlags[index0] === 0 && processingFlags[index0 + oneRowDown] === 0 && processingFlags[index0 + twoRowsDown] === 0 && processingFlags[index0 + threeRowsDown] === 0 && neighborsSignificance[index0] === 0 && neighborsSignificance[index0 + oneRowDown] === 0 && neighborsSignificance[index0 + twoRowsDown] === 0 && neighborsSignificance[index0 + threeRowsDown] === 0;
+            var i1 = 0,
+                index = index0;
+            var i = i0,
+                sign;
+
+            if (allEmpty) {
+              var hasSignificantCoefficent = decoder.readBit(contexts, RUNLENGTH_CONTEXT);
+
+              if (!hasSignificantCoefficent) {
+                bitsDecoded[index0]++;
+                bitsDecoded[index0 + oneRowDown]++;
+                bitsDecoded[index0 + twoRowsDown]++;
+                bitsDecoded[index0 + threeRowsDown]++;
+                continue;
+              }
+
+              i1 = decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
+
+              if (i1 !== 0) {
+                i = i0 + i1;
+                index += i1 * width;
+              }
+
+              sign = this.decodeSignBit(i, j, index);
+              coefficentsSign[index] = sign;
+              coefficentsMagnitude[index] = 1;
+              this.setNeighborsSignificance(i, j, index);
+              processingFlags[index] |= firstMagnitudeBitMask;
+              index = index0;
+
+              for (var i2 = i0; i2 <= i; i2++, index += width) {
+                bitsDecoded[index]++;
+              }
+
+              i1++;
+            }
+
+            for (i = i0 + i1; i < iNext; i++, index += width) {
+              if (coefficentsMagnitude[index] || (processingFlags[index] & processedMask) !== 0) {
+                continue;
+              }
+
+              var contextLabel = labels[neighborsSignificance[index]];
+              var decision = decoder.readBit(contexts, contextLabel);
+
+              if (decision === 1) {
+                sign = this.decodeSignBit(i, j, index);
+                coefficentsSign[index] = sign;
+                coefficentsMagnitude[index] = 1;
+                this.setNeighborsSignificance(i, j, index);
+                processingFlags[index] |= firstMagnitudeBitMask;
+              }
+
+              bitsDecoded[index]++;
+            }
+          }
+        }
+      },
+      checkSegmentationSymbol: function BitModel_checkSegmentationSymbol() {
+        var decoder = this.decoder;
+        var contexts = this.contexts;
+        var symbol = decoder.readBit(contexts, UNIFORM_CONTEXT) << 3 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 2 | decoder.readBit(contexts, UNIFORM_CONTEXT) << 1 | decoder.readBit(contexts, UNIFORM_CONTEXT);
+
+        if (symbol !== 0xA) {
+          throw new JpxError('Invalid segmentation symbol');
+        }
+      }
+    };
+    return BitModel;
+  }();
+
+  var Transform = function TransformClosure() {
+    function Transform() {}
+
+    Transform.prototype.calculate = function transformCalculate(subbands, u0, v0) {
+      var ll = subbands[0];
+
+      for (var i = 1, ii = subbands.length; i < ii; i++) {
+        ll = this.iterate(ll, subbands[i], u0, v0);
+      }
+
+      return ll;
+    };
+
+    Transform.prototype.extend = function extend(buffer, offset, size) {
+      var i1 = offset - 1,
+          j1 = offset + 1;
+      var i2 = offset + size - 2,
+          j2 = offset + size;
+      buffer[i1--] = buffer[j1++];
+      buffer[j2++] = buffer[i2--];
+      buffer[i1--] = buffer[j1++];
+      buffer[j2++] = buffer[i2--];
+      buffer[i1--] = buffer[j1++];
+      buffer[j2++] = buffer[i2--];
+      buffer[i1] = buffer[j1];
+      buffer[j2] = buffer[i2];
+    };
+
+    Transform.prototype.iterate = function Transform_iterate(ll, hl_lh_hh, u0, v0) {
+      var llWidth = ll.width,
+          llHeight = ll.height,
+          llItems = ll.items;
+      var width = hl_lh_hh.width;
+      var height = hl_lh_hh.height;
+      var items = hl_lh_hh.items;
+      var i, j, k, l, u, v;
+
+      for (k = 0, i = 0; i < llHeight; i++) {
+        l = i * 2 * width;
+
+        for (j = 0; j < llWidth; j++, k++, l += 2) {
+          items[l] = llItems[k];
+        }
+      }
+
+      llItems = ll.items = null;
+      var bufferPadding = 4;
+      var rowBuffer = new Float32Array(width + 2 * bufferPadding);
+
+      if (width === 1) {
+        if ((u0 & 1) !== 0) {
+          for (v = 0, k = 0; v < height; v++, k += width) {
+            items[k] *= 0.5;
+          }
+        }
+      } else {
+        for (v = 0, k = 0; v < height; v++, k += width) {
+          rowBuffer.set(items.subarray(k, k + width), bufferPadding);
+          this.extend(rowBuffer, bufferPadding, width);
+          this.filter(rowBuffer, bufferPadding, width);
+          items.set(rowBuffer.subarray(bufferPadding, bufferPadding + width), k);
+        }
+      }
+
+      var numBuffers = 16;
+      var colBuffers = [];
+
+      for (i = 0; i < numBuffers; i++) {
+        colBuffers.push(new Float32Array(height + 2 * bufferPadding));
+      }
+
+      var b,
+          currentBuffer = 0;
+      ll = bufferPadding + height;
+
+      if (height === 1) {
+        if ((v0 & 1) !== 0) {
+          for (u = 0; u < width; u++) {
+            items[u] *= 0.5;
+          }
+        }
+      } else {
+        for (u = 0; u < width; u++) {
+          if (currentBuffer === 0) {
+            numBuffers = Math.min(width - u, numBuffers);
+
+            for (k = u, l = bufferPadding; l < ll; k += width, l++) {
+              for (b = 0; b < numBuffers; b++) {
+                colBuffers[b][l] = items[k + b];
+              }
+            }
+
+            currentBuffer = numBuffers;
+          }
+
+          currentBuffer--;
+          var buffer = colBuffers[currentBuffer];
+          this.extend(buffer, bufferPadding, height);
+          this.filter(buffer, bufferPadding, height);
+
+          if (currentBuffer === 0) {
+            k = u - numBuffers + 1;
+
+            for (l = bufferPadding; l < ll; k += width, l++) {
+              for (b = 0; b < numBuffers; b++) {
+                items[k + b] = colBuffers[b][l];
+              }
+            }
+          }
+        }
+      }
+
+      return {
+        width: width,
+        height: height,
+        items: items
+      };
+    };
+
+    return Transform;
+  }();
+
+  var IrreversibleTransform = function IrreversibleTransformClosure() {
+    function IrreversibleTransform() {
+      Transform.call(this);
+    }
+
+    IrreversibleTransform.prototype = Object.create(Transform.prototype);
+
+    IrreversibleTransform.prototype.filter = function irreversibleTransformFilter(x, offset, length) {
+      var len = length >> 1;
+      offset = offset | 0;
+      var j, n, current, next;
+      var alpha = -1.586134342059924;
+      var beta = -0.052980118572961;
+      var gamma = 0.882911075530934;
+      var delta = 0.443506852043971;
+      var K = 1.230174104914001;
+      var K_ = 1 / K;
+      j = offset - 3;
+
+      for (n = len + 4; n--; j += 2) {
+        x[j] *= K_;
+      }
+
+      j = offset - 2;
+      current = delta * x[j - 1];
+
+      for (n = len + 3; n--; j += 2) {
+        next = delta * x[j + 1];
+        x[j] = K * x[j] - current - next;
+
+        if (n--) {
+          j += 2;
+          current = delta * x[j + 1];
+          x[j] = K * x[j] - current - next;
+        } else {
+          break;
+        }
+      }
+
+      j = offset - 1;
+      current = gamma * x[j - 1];
+
+      for (n = len + 2; n--; j += 2) {
+        next = gamma * x[j + 1];
+        x[j] -= current + next;
+
+        if (n--) {
+          j += 2;
+          current = gamma * x[j + 1];
+          x[j] -= current + next;
+        } else {
+          break;
+        }
+      }
+
+      j = offset;
+      current = beta * x[j - 1];
+
+      for (n = len + 1; n--; j += 2) {
+        next = beta * x[j + 1];
+        x[j] -= current + next;
+
+        if (n--) {
+          j += 2;
+          current = beta * x[j + 1];
+          x[j] -= current + next;
+        } else {
+          break;
+        }
+      }
+
+      if (len !== 0) {
+        j = offset + 1;
+        current = alpha * x[j - 1];
+
+        for (n = len; n--; j += 2) {
+          next = alpha * x[j + 1];
+          x[j] -= current + next;
+
+          if (n--) {
+            j += 2;
+            current = alpha * x[j + 1];
+            x[j] -= current + next;
+          } else {
+            break;
+          }
+        }
+      }
+    };
+
+    return IrreversibleTransform;
+  }();
+
+  var ReversibleTransform = function ReversibleTransformClosure() {
+    function ReversibleTransform() {
+      Transform.call(this);
+    }
+
+    ReversibleTransform.prototype = Object.create(Transform.prototype);
+
+    ReversibleTransform.prototype.filter = function reversibleTransformFilter(x, offset, length) {
+      var len = length >> 1;
+      offset = offset | 0;
+      var j, n;
+
+      for (j = offset, n = len + 1; n--; j += 2) {
+        x[j] -= x[j - 1] + x[j + 1] + 2 >> 2;
+      }
+
+      for (j = offset + 1, n = len; n--; j += 2) {
+        x[j] += x[j - 1] + x[j + 1] >> 1;
+      }
+    };
+
+    return ReversibleTransform;
+  }();
+
+  return JpxImage;
+}();
+
+exports.JpxImage = JpxImage;
+
+/***/ }),
+/* 168 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.calculateSHA512 = exports.calculateSHA384 = exports.calculateSHA256 = exports.calculateMD5 = exports.PDF20 = exports.PDF17 = exports.CipherTransformFactory = exports.ARCFourCipher = exports.AES256Cipher = exports.AES128Cipher = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var ARCFourCipher = function ARCFourCipherClosure() {
+  function ARCFourCipher(key) {
+    this.a = 0;
+    this.b = 0;
+    var s = new Uint8Array(256);
+    var i,
+        j = 0,
+        tmp,
+        keyLength = key.length;
+
+    for (i = 0; i < 256; ++i) {
+      s[i] = i;
+    }
+
+    for (i = 0; i < 256; ++i) {
+      tmp = s[i];
+      j = j + tmp + key[i % keyLength] & 0xFF;
+      s[i] = s[j];
+      s[j] = tmp;
+    }
+
+    this.s = s;
+  }
+
+  ARCFourCipher.prototype = {
+    encryptBlock: function ARCFourCipher_encryptBlock(data) {
+      var i,
+          n = data.length,
+          tmp,
+          tmp2;
+      var a = this.a,
+          b = this.b,
+          s = this.s;
+      var output = new Uint8Array(n);
+
+      for (i = 0; i < n; ++i) {
+        a = a + 1 & 0xFF;
+        tmp = s[a];
+        b = b + tmp & 0xFF;
+        tmp2 = s[b];
+        s[a] = tmp2;
+        s[b] = tmp;
+        output[i] = data[i] ^ s[tmp + tmp2 & 0xFF];
+      }
+
+      this.a = a;
+      this.b = b;
+      return output;
+    }
+  };
+  ARCFourCipher.prototype.decryptBlock = ARCFourCipher.prototype.encryptBlock;
+  return ARCFourCipher;
+}();
+
+exports.ARCFourCipher = ARCFourCipher;
+
+var calculateMD5 = function calculateMD5Closure() {
+  var r = new Uint8Array([7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21]);
+  var k = new Int32Array([-680876936, -389564586, 606105819, -1044525330, -176418897, 1200080426, -1473231341, -45705983, 1770035416, -1958414417, -42063, -1990404162, 1804603682, -40341101, -1502002290, 1236535329, -165796510, -1069501632, 643717713, -373897302, -701558691, 38016083, -660478335, -405537848, 568446438, -1019803690, -187363961, 1163531501, -1444681467, -51403784, 1735328473, -1926607734, -378558, -2022574463, 1839030562, -35309556, -1530992060, 1272893353, -155497632, -1094730640, 681279174, -358537222, -722521979, 76029189, -640364487, -421815835, 530742520, -995338651, -198630844, 1126891415, -1416354905, -57434055, 1700485571, -1894986606, -1051523, -2054922799, 1873313359, -30611744, -1560198380, 1309151649, -145523070, -1120210379, 718787259, -343485551]);
+
+  function hash(data, offset, length) {
+    var h0 = 1732584193,
+        h1 = -271733879,
+        h2 = -1732584194,
+        h3 = 271733878;
+    var paddedLength = length + 72 & ~63;
+    var padded = new Uint8Array(paddedLength);
+    var i, j, n;
+
+    for (i = 0; i < length; ++i) {
+      padded[i] = data[offset++];
+    }
+
+    padded[i++] = 0x80;
+    n = paddedLength - 8;
+
+    while (i < n) {
+      padded[i++] = 0;
+    }
+
+    padded[i++] = length << 3 & 0xFF;
+    padded[i++] = length >> 5 & 0xFF;
+    padded[i++] = length >> 13 & 0xFF;
+    padded[i++] = length >> 21 & 0xFF;
+    padded[i++] = length >>> 29 & 0xFF;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    var w = new Int32Array(16);
+
+    for (i = 0; i < paddedLength;) {
+      for (j = 0; j < 16; ++j, i += 4) {
+        w[j] = padded[i] | padded[i + 1] << 8 | padded[i + 2] << 16 | padded[i + 3] << 24;
+      }
+
+      var a = h0,
+          b = h1,
+          c = h2,
+          d = h3,
+          f,
+          g;
+
+      for (j = 0; j < 64; ++j) {
+        if (j < 16) {
+          f = b & c | ~b & d;
+          g = j;
+        } else if (j < 32) {
+          f = d & b | ~d & c;
+          g = 5 * j + 1 & 15;
+        } else if (j < 48) {
+          f = b ^ c ^ d;
+          g = 3 * j + 5 & 15;
+        } else {
+          f = c ^ (b | ~d);
+          g = 7 * j & 15;
+        }
+
+        var tmp = d,
+            rotateArg = a + f + k[j] + w[g] | 0,
+            rotate = r[j];
+        d = c;
+        c = b;
+        b = b + (rotateArg << rotate | rotateArg >>> 32 - rotate) | 0;
+        a = tmp;
+      }
+
+      h0 = h0 + a | 0;
+      h1 = h1 + b | 0;
+      h2 = h2 + c | 0;
+      h3 = h3 + d | 0;
+    }
+
+    return new Uint8Array([h0 & 0xFF, h0 >> 8 & 0xFF, h0 >> 16 & 0xFF, h0 >>> 24 & 0xFF, h1 & 0xFF, h1 >> 8 & 0xFF, h1 >> 16 & 0xFF, h1 >>> 24 & 0xFF, h2 & 0xFF, h2 >> 8 & 0xFF, h2 >> 16 & 0xFF, h2 >>> 24 & 0xFF, h3 & 0xFF, h3 >> 8 & 0xFF, h3 >> 16 & 0xFF, h3 >>> 24 & 0xFF]);
+  }
+
+  return hash;
+}();
+
+exports.calculateMD5 = calculateMD5;
+
+var Word64 = function Word64Closure() {
+  function Word64(highInteger, lowInteger) {
+    this.high = highInteger | 0;
+    this.low = lowInteger | 0;
+  }
+
+  Word64.prototype = {
+    and: function Word64_and(word) {
+      this.high &= word.high;
+      this.low &= word.low;
+    },
+    xor: function Word64_xor(word) {
+      this.high ^= word.high;
+      this.low ^= word.low;
+    },
+    or: function Word64_or(word) {
+      this.high |= word.high;
+      this.low |= word.low;
+    },
+    shiftRight: function Word64_shiftRight(places) {
+      if (places >= 32) {
+        this.low = this.high >>> places - 32 | 0;
+        this.high = 0;
+      } else {
+        this.low = this.low >>> places | this.high << 32 - places;
+        this.high = this.high >>> places | 0;
+      }
+    },
+    shiftLeft: function Word64_shiftLeft(places) {
+      if (places >= 32) {
+        this.high = this.low << places - 32;
+        this.low = 0;
+      } else {
+        this.high = this.high << places | this.low >>> 32 - places;
+        this.low = this.low << places;
+      }
+    },
+    rotateRight: function Word64_rotateRight(places) {
+      var low, high;
+
+      if (places & 32) {
+        high = this.low;
+        low = this.high;
+      } else {
+        low = this.low;
+        high = this.high;
+      }
+
+      places &= 31;
+      this.low = low >>> places | high << 32 - places;
+      this.high = high >>> places | low << 32 - places;
+    },
+    not: function Word64_not() {
+      this.high = ~this.high;
+      this.low = ~this.low;
+    },
+    add: function Word64_add(word) {
+      var lowAdd = (this.low >>> 0) + (word.low >>> 0);
+      var highAdd = (this.high >>> 0) + (word.high >>> 0);
+
+      if (lowAdd > 0xFFFFFFFF) {
+        highAdd += 1;
+      }
+
+      this.low = lowAdd | 0;
+      this.high = highAdd | 0;
+    },
+    copyTo: function Word64_copyTo(bytes, offset) {
+      bytes[offset] = this.high >>> 24 & 0xFF;
+      bytes[offset + 1] = this.high >> 16 & 0xFF;
+      bytes[offset + 2] = this.high >> 8 & 0xFF;
+      bytes[offset + 3] = this.high & 0xFF;
+      bytes[offset + 4] = this.low >>> 24 & 0xFF;
+      bytes[offset + 5] = this.low >> 16 & 0xFF;
+      bytes[offset + 6] = this.low >> 8 & 0xFF;
+      bytes[offset + 7] = this.low & 0xFF;
+    },
+    assign: function Word64_assign(word) {
+      this.high = word.high;
+      this.low = word.low;
+    }
+  };
+  return Word64;
+}();
+
+var calculateSHA256 = function calculateSHA256Closure() {
+  function rotr(x, n) {
+    return x >>> n | x << 32 - n;
+  }
+
+  function ch(x, y, z) {
+    return x & y ^ ~x & z;
+  }
+
+  function maj(x, y, z) {
+    return x & y ^ x & z ^ y & z;
+  }
+
+  function sigma(x) {
+    return rotr(x, 2) ^ rotr(x, 13) ^ rotr(x, 22);
+  }
+
+  function sigmaPrime(x) {
+    return rotr(x, 6) ^ rotr(x, 11) ^ rotr(x, 25);
+  }
+
+  function littleSigma(x) {
+    return rotr(x, 7) ^ rotr(x, 18) ^ x >>> 3;
+  }
+
+  function littleSigmaPrime(x) {
+    return rotr(x, 17) ^ rotr(x, 19) ^ x >>> 10;
+  }
+
+  var k = [0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2];
+
+  function hash(data, offset, length) {
+    var h0 = 0x6a09e667,
+        h1 = 0xbb67ae85,
+        h2 = 0x3c6ef372,
+        h3 = 0xa54ff53a,
+        h4 = 0x510e527f,
+        h5 = 0x9b05688c,
+        h6 = 0x1f83d9ab,
+        h7 = 0x5be0cd19;
+    var paddedLength = Math.ceil((length + 9) / 64) * 64;
+    var padded = new Uint8Array(paddedLength);
+    var i, j, n;
+
+    for (i = 0; i < length; ++i) {
+      padded[i] = data[offset++];
+    }
+
+    padded[i++] = 0x80;
+    n = paddedLength - 8;
+
+    while (i < n) {
+      padded[i++] = 0;
+    }
+
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = length >>> 29 & 0xFF;
+    padded[i++] = length >> 21 & 0xFF;
+    padded[i++] = length >> 13 & 0xFF;
+    padded[i++] = length >> 5 & 0xFF;
+    padded[i++] = length << 3 & 0xFF;
+    var w = new Uint32Array(64);
+
+    for (i = 0; i < paddedLength;) {
+      for (j = 0; j < 16; ++j) {
+        w[j] = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
+        i += 4;
+      }
+
+      for (j = 16; j < 64; ++j) {
+        w[j] = littleSigmaPrime(w[j - 2]) + w[j - 7] + littleSigma(w[j - 15]) + w[j - 16] | 0;
+      }
+
+      var a = h0,
+          b = h1,
+          c = h2,
+          d = h3,
+          e = h4,
+          f = h5,
+          g = h6,
+          h = h7,
+          t1,
+          t2;
+
+      for (j = 0; j < 64; ++j) {
+        t1 = h + sigmaPrime(e) + ch(e, f, g) + k[j] + w[j];
+        t2 = sigma(a) + maj(a, b, c);
+        h = g;
+        g = f;
+        f = e;
+        e = d + t1 | 0;
+        d = c;
+        c = b;
+        b = a;
+        a = t1 + t2 | 0;
+      }
+
+      h0 = h0 + a | 0;
+      h1 = h1 + b | 0;
+      h2 = h2 + c | 0;
+      h3 = h3 + d | 0;
+      h4 = h4 + e | 0;
+      h5 = h5 + f | 0;
+      h6 = h6 + g | 0;
+      h7 = h7 + h | 0;
+    }
+
+    return new Uint8Array([h0 >> 24 & 0xFF, h0 >> 16 & 0xFF, h0 >> 8 & 0xFF, h0 & 0xFF, h1 >> 24 & 0xFF, h1 >> 16 & 0xFF, h1 >> 8 & 0xFF, h1 & 0xFF, h2 >> 24 & 0xFF, h2 >> 16 & 0xFF, h2 >> 8 & 0xFF, h2 & 0xFF, h3 >> 24 & 0xFF, h3 >> 16 & 0xFF, h3 >> 8 & 0xFF, h3 & 0xFF, h4 >> 24 & 0xFF, h4 >> 16 & 0xFF, h4 >> 8 & 0xFF, h4 & 0xFF, h5 >> 24 & 0xFF, h5 >> 16 & 0xFF, h5 >> 8 & 0xFF, h5 & 0xFF, h6 >> 24 & 0xFF, h6 >> 16 & 0xFF, h6 >> 8 & 0xFF, h6 & 0xFF, h7 >> 24 & 0xFF, h7 >> 16 & 0xFF, h7 >> 8 & 0xFF, h7 & 0xFF]);
+  }
+
+  return hash;
+}();
+
+exports.calculateSHA256 = calculateSHA256;
+
+var calculateSHA512 = function calculateSHA512Closure() {
+  function ch(result, x, y, z, tmp) {
+    result.assign(x);
+    result.and(y);
+    tmp.assign(x);
+    tmp.not();
+    tmp.and(z);
+    result.xor(tmp);
+  }
+
+  function maj(result, x, y, z, tmp) {
+    result.assign(x);
+    result.and(y);
+    tmp.assign(x);
+    tmp.and(z);
+    result.xor(tmp);
+    tmp.assign(y);
+    tmp.and(z);
+    result.xor(tmp);
+  }
+
+  function sigma(result, x, tmp) {
+    result.assign(x);
+    result.rotateRight(28);
+    tmp.assign(x);
+    tmp.rotateRight(34);
+    result.xor(tmp);
+    tmp.assign(x);
+    tmp.rotateRight(39);
+    result.xor(tmp);
+  }
+
+  function sigmaPrime(result, x, tmp) {
+    result.assign(x);
+    result.rotateRight(14);
+    tmp.assign(x);
+    tmp.rotateRight(18);
+    result.xor(tmp);
+    tmp.assign(x);
+    tmp.rotateRight(41);
+    result.xor(tmp);
+  }
+
+  function littleSigma(result, x, tmp) {
+    result.assign(x);
+    result.rotateRight(1);
+    tmp.assign(x);
+    tmp.rotateRight(8);
+    result.xor(tmp);
+    tmp.assign(x);
+    tmp.shiftRight(7);
+    result.xor(tmp);
+  }
+
+  function littleSigmaPrime(result, x, tmp) {
+    result.assign(x);
+    result.rotateRight(19);
+    tmp.assign(x);
+    tmp.rotateRight(61);
+    result.xor(tmp);
+    tmp.assign(x);
+    tmp.shiftRight(6);
+    result.xor(tmp);
+  }
+
+  var k = [new Word64(0x428a2f98, 0xd728ae22), new Word64(0x71374491, 0x23ef65cd), new Word64(0xb5c0fbcf, 0xec4d3b2f), new Word64(0xe9b5dba5, 0x8189dbbc), new Word64(0x3956c25b, 0xf348b538), new Word64(0x59f111f1, 0xb605d019), new Word64(0x923f82a4, 0xaf194f9b), new Word64(0xab1c5ed5, 0xda6d8118), new Word64(0xd807aa98, 0xa3030242), new Word64(0x12835b01, 0x45706fbe), new Word64(0x243185be, 0x4ee4b28c), new Word64(0x550c7dc3, 0xd5ffb4e2), new Word64(0x72be5d74, 0xf27b896f), new Word64(0x80deb1fe, 0x3b1696b1), new Word64(0x9bdc06a7, 0x25c71235), new Word64(0xc19bf174, 0xcf692694), new Word64(0xe49b69c1, 0x9ef14ad2), new Word64(0xefbe4786, 0x384f25e3), new Word64(0x0fc19dc6, 0x8b8cd5b5), new Word64(0x240ca1cc, 0x77ac9c65), new Word64(0x2de92c6f, 0x592b0275), new Word64(0x4a7484aa, 0x6ea6e483), new Word64(0x5cb0a9dc, 0xbd41fbd4), new Word64(0x76f988da, 0x831153b5), new Word64(0x983e5152, 0xee66dfab), new Word64(0xa831c66d, 0x2db43210), new Word64(0xb00327c8, 0x98fb213f), new Word64(0xbf597fc7, 0xbeef0ee4), new Word64(0xc6e00bf3, 0x3da88fc2), new Word64(0xd5a79147, 0x930aa725), new Word64(0x06ca6351, 0xe003826f), new Word64(0x14292967, 0x0a0e6e70), new Word64(0x27b70a85, 0x46d22ffc), new Word64(0x2e1b2138, 0x5c26c926), new Word64(0x4d2c6dfc, 0x5ac42aed), new Word64(0x53380d13, 0x9d95b3df), new Word64(0x650a7354, 0x8baf63de), new Word64(0x766a0abb, 0x3c77b2a8), new Word64(0x81c2c92e, 0x47edaee6), new Word64(0x92722c85, 0x1482353b), new Word64(0xa2bfe8a1, 0x4cf10364), new Word64(0xa81a664b, 0xbc423001), new Word64(0xc24b8b70, 0xd0f89791), new Word64(0xc76c51a3, 0x0654be30), new Word64(0xd192e819, 0xd6ef5218), new Word64(0xd6990624, 0x5565a910), new Word64(0xf40e3585, 0x5771202a), new Word64(0x106aa070, 0x32bbd1b8), new Word64(0x19a4c116, 0xb8d2d0c8), new Word64(0x1e376c08, 0x5141ab53), new Word64(0x2748774c, 0xdf8eeb99), new Word64(0x34b0bcb5, 0xe19b48a8), new Word64(0x391c0cb3, 0xc5c95a63), new Word64(0x4ed8aa4a, 0xe3418acb), new Word64(0x5b9cca4f, 0x7763e373), new Word64(0x682e6ff3, 0xd6b2b8a3), new Word64(0x748f82ee, 0x5defb2fc), new Word64(0x78a5636f, 0x43172f60), new Word64(0x84c87814, 0xa1f0ab72), new Word64(0x8cc70208, 0x1a6439ec), new Word64(0x90befffa, 0x23631e28), new Word64(0xa4506ceb, 0xde82bde9), new Word64(0xbef9a3f7, 0xb2c67915), new Word64(0xc67178f2, 0xe372532b), new Word64(0xca273ece, 0xea26619c), new Word64(0xd186b8c7, 0x21c0c207), new Word64(0xeada7dd6, 0xcde0eb1e), new Word64(0xf57d4f7f, 0xee6ed178), new Word64(0x06f067aa, 0x72176fba), new Word64(0x0a637dc5, 0xa2c898a6), new Word64(0x113f9804, 0xbef90dae), new Word64(0x1b710b35, 0x131c471b), new Word64(0x28db77f5, 0x23047d84), new Word64(0x32caab7b, 0x40c72493), new Word64(0x3c9ebe0a, 0x15c9bebc), new Word64(0x431d67c4, 0x9c100d4c), new Word64(0x4cc5d4be, 0xcb3e42b6), new Word64(0x597f299c, 0xfc657e2a), new Word64(0x5fcb6fab, 0x3ad6faec), new Word64(0x6c44198c, 0x4a475817)];
+
+  function hash(data, offset, length, mode384) {
+    mode384 = !!mode384;
+    var h0, h1, h2, h3, h4, h5, h6, h7;
+
+    if (!mode384) {
+      h0 = new Word64(0x6a09e667, 0xf3bcc908);
+      h1 = new Word64(0xbb67ae85, 0x84caa73b);
+      h2 = new Word64(0x3c6ef372, 0xfe94f82b);
+      h3 = new Word64(0xa54ff53a, 0x5f1d36f1);
+      h4 = new Word64(0x510e527f, 0xade682d1);
+      h5 = new Word64(0x9b05688c, 0x2b3e6c1f);
+      h6 = new Word64(0x1f83d9ab, 0xfb41bd6b);
+      h7 = new Word64(0x5be0cd19, 0x137e2179);
+    } else {
+      h0 = new Word64(0xcbbb9d5d, 0xc1059ed8);
+      h1 = new Word64(0x629a292a, 0x367cd507);
+      h2 = new Word64(0x9159015a, 0x3070dd17);
+      h3 = new Word64(0x152fecd8, 0xf70e5939);
+      h4 = new Word64(0x67332667, 0xffc00b31);
+      h5 = new Word64(0x8eb44a87, 0x68581511);
+      h6 = new Word64(0xdb0c2e0d, 0x64f98fa7);
+      h7 = new Word64(0x47b5481d, 0xbefa4fa4);
+    }
+
+    var paddedLength = Math.ceil((length + 17) / 128) * 128;
+    var padded = new Uint8Array(paddedLength);
+    var i, j, n;
+
+    for (i = 0; i < length; ++i) {
+      padded[i] = data[offset++];
+    }
+
+    padded[i++] = 0x80;
+    n = paddedLength - 16;
+
+    while (i < n) {
+      padded[i++] = 0;
+    }
+
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = 0;
+    padded[i++] = length >>> 29 & 0xFF;
+    padded[i++] = length >> 21 & 0xFF;
+    padded[i++] = length >> 13 & 0xFF;
+    padded[i++] = length >> 5 & 0xFF;
+    padded[i++] = length << 3 & 0xFF;
+    var w = new Array(80);
+
+    for (i = 0; i < 80; i++) {
+      w[i] = new Word64(0, 0);
+    }
+
+    var a = new Word64(0, 0),
+        b = new Word64(0, 0),
+        c = new Word64(0, 0);
+    var d = new Word64(0, 0),
+        e = new Word64(0, 0),
+        f = new Word64(0, 0);
+    var g = new Word64(0, 0),
+        h = new Word64(0, 0);
+    var t1 = new Word64(0, 0),
+        t2 = new Word64(0, 0);
+    var tmp1 = new Word64(0, 0),
+        tmp2 = new Word64(0, 0),
+        tmp3;
+
+    for (i = 0; i < paddedLength;) {
+      for (j = 0; j < 16; ++j) {
+        w[j].high = padded[i] << 24 | padded[i + 1] << 16 | padded[i + 2] << 8 | padded[i + 3];
+        w[j].low = padded[i + 4] << 24 | padded[i + 5] << 16 | padded[i + 6] << 8 | padded[i + 7];
+        i += 8;
+      }
+
+      for (j = 16; j < 80; ++j) {
+        tmp3 = w[j];
+        littleSigmaPrime(tmp3, w[j - 2], tmp2);
+        tmp3.add(w[j - 7]);
+        littleSigma(tmp1, w[j - 15], tmp2);
+        tmp3.add(tmp1);
+        tmp3.add(w[j - 16]);
+      }
+
+      a.assign(h0);
+      b.assign(h1);
+      c.assign(h2);
+      d.assign(h3);
+      e.assign(h4);
+      f.assign(h5);
+      g.assign(h6);
+      h.assign(h7);
+
+      for (j = 0; j < 80; ++j) {
+        t1.assign(h);
+        sigmaPrime(tmp1, e, tmp2);
+        t1.add(tmp1);
+        ch(tmp1, e, f, g, tmp2);
+        t1.add(tmp1);
+        t1.add(k[j]);
+        t1.add(w[j]);
+        sigma(t2, a, tmp2);
+        maj(tmp1, a, b, c, tmp2);
+        t2.add(tmp1);
+        tmp3 = h;
+        h = g;
+        g = f;
+        f = e;
+        d.add(t1);
+        e = d;
+        d = c;
+        c = b;
+        b = a;
+        tmp3.assign(t1);
+        tmp3.add(t2);
+        a = tmp3;
+      }
+
+      h0.add(a);
+      h1.add(b);
+      h2.add(c);
+      h3.add(d);
+      h4.add(e);
+      h5.add(f);
+      h6.add(g);
+      h7.add(h);
+    }
+
+    var result;
+
+    if (!mode384) {
+      result = new Uint8Array(64);
+      h0.copyTo(result, 0);
+      h1.copyTo(result, 8);
+      h2.copyTo(result, 16);
+      h3.copyTo(result, 24);
+      h4.copyTo(result, 32);
+      h5.copyTo(result, 40);
+      h6.copyTo(result, 48);
+      h7.copyTo(result, 56);
+    } else {
+      result = new Uint8Array(48);
+      h0.copyTo(result, 0);
+      h1.copyTo(result, 8);
+      h2.copyTo(result, 16);
+      h3.copyTo(result, 24);
+      h4.copyTo(result, 32);
+      h5.copyTo(result, 40);
+    }
+
+    return result;
+  }
+
+  return hash;
+}();
+
+exports.calculateSHA512 = calculateSHA512;
+
+var calculateSHA384 = function calculateSHA384Closure() {
+  function hash(data, offset, length) {
+    return calculateSHA512(data, offset, length, true);
+  }
+
+  return hash;
+}();
+
+exports.calculateSHA384 = calculateSHA384;
+
+var NullCipher = function NullCipherClosure() {
+  function NullCipher() {}
+
+  NullCipher.prototype = {
+    decryptBlock: function NullCipher_decryptBlock(data) {
+      return data;
+    }
+  };
+  return NullCipher;
+}();
+
+var AESBaseCipher =
+/*#__PURE__*/
+function () {
+  function AESBaseCipher() {
+    _classCallCheck(this, AESBaseCipher);
+
+    if (this.constructor === AESBaseCipher) {
+      (0, _util.unreachable)('Cannot initialize AESBaseCipher.');
+    }
+
+    this._s = new Uint8Array([0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15, 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf, 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73, 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08, 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf, 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16]);
+    this._inv_s = new Uint8Array([0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e, 0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84, 0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73, 0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4, 0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61, 0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d]);
+    this._mix = new Uint32Array([0x00000000, 0x0e090d0b, 0x1c121a16, 0x121b171d, 0x3824342c, 0x362d3927, 0x24362e3a, 0x2a3f2331, 0x70486858, 0x7e416553, 0x6c5a724e, 0x62537f45, 0x486c5c74, 0x4665517f, 0x547e4662, 0x5a774b69, 0xe090d0b0, 0xee99ddbb, 0xfc82caa6, 0xf28bc7ad, 0xd8b4e49c, 0xd6bde997, 0xc4a6fe8a, 0xcaaff381, 0x90d8b8e8, 0x9ed1b5e3, 0x8ccaa2fe, 0x82c3aff5, 0xa8fc8cc4, 0xa6f581cf, 0xb4ee96d2, 0xbae79bd9, 0xdb3bbb7b, 0xd532b670, 0xc729a16d, 0xc920ac66, 0xe31f8f57, 0xed16825c, 0xff0d9541, 0xf104984a, 0xab73d323, 0xa57ade28, 0xb761c935, 0xb968c43e, 0x9357e70f, 0x9d5eea04, 0x8f45fd19, 0x814cf012, 0x3bab6bcb, 0x35a266c0, 0x27b971dd, 0x29b07cd6, 0x038f5fe7, 0x0d8652ec, 0x1f9d45f1, 0x119448fa, 0x4be30393, 0x45ea0e98, 0x57f11985, 0x59f8148e, 0x73c737bf, 0x7dce3ab4, 0x6fd52da9, 0x61dc20a2, 0xad766df6, 0xa37f60fd, 0xb16477e0, 0xbf6d7aeb, 0x955259da, 0x9b5b54d1, 0x894043cc, 0x87494ec7, 0xdd3e05ae, 0xd33708a5, 0xc12c1fb8, 0xcf2512b3, 0xe51a3182, 0xeb133c89, 0xf9082b94, 0xf701269f, 0x4de6bd46, 0x43efb04d, 0x51f4a750, 0x5ffdaa5b, 0x75c2896a, 0x7bcb8461, 0x69d0937c, 0x67d99e77, 0x3daed51e, 0x33a7d815, 0x21bccf08, 0x2fb5c203, 0x058ae132, 0x0b83ec39, 0x1998fb24, 0x1791f62f, 0x764dd68d, 0x7844db86, 0x6a5fcc9b, 0x6456c190, 0x4e69e2a1, 0x4060efaa, 0x527bf8b7, 0x5c72f5bc, 0x0605bed5, 0x080cb3de, 0x1a17a4c3, 0x141ea9c8, 0x3e218af9, 0x302887f2, 0x223390ef, 0x2c3a9de4, 0x96dd063d, 0x98d40b36, 0x8acf1c2b, 0x84c61120, 0xaef93211, 0xa0f03f1a, 0xb2eb2807, 0xbce2250c, 0xe6956e65, 0xe89c636e, 0xfa877473, 0xf48e7978, 0xdeb15a49, 0xd0b85742, 0xc2a3405f, 0xccaa4d54, 0x41ecdaf7, 0x4fe5d7fc, 0x5dfec0e1, 0x53f7cdea, 0x79c8eedb, 0x77c1e3d0, 0x65daf4cd, 0x6bd3f9c6, 0x31a4b2af, 0x3fadbfa4, 0x2db6a8b9, 0x23bfa5b2, 0x09808683, 0x07898b88, 0x15929c95, 0x1b9b919e, 0xa17c0a47, 0xaf75074c, 0xbd6e1051, 0xb3671d5a, 0x99583e6b, 0x97513360, 0x854a247d, 0x8b432976, 0xd134621f, 0xdf3d6f14, 0xcd267809, 0xc32f7502, 0xe9105633, 0xe7195b38, 0xf5024c25, 0xfb0b412e, 0x9ad7618c, 0x94de6c87, 0x86c57b9a, 0x88cc7691, 0xa2f355a0, 0xacfa58ab, 0xbee14fb6, 0xb0e842bd, 0xea9f09d4, 0xe49604df, 0xf68d13c2, 0xf8841ec9, 0xd2bb3df8, 0xdcb230f3, 0xcea927ee, 0xc0a02ae5, 0x7a47b13c, 0x744ebc37, 0x6655ab2a, 0x685ca621, 0x42638510, 0x4c6a881b, 0x5e719f06, 0x5078920d, 0x0a0fd964, 0x0406d46f, 0x161dc372, 0x1814ce79, 0x322bed48, 0x3c22e043, 0x2e39f75e, 0x2030fa55, 0xec9ab701, 0xe293ba0a, 0xf088ad17, 0xfe81a01c, 0xd4be832d, 0xdab78e26, 0xc8ac993b, 0xc6a59430, 0x9cd2df59, 0x92dbd252, 0x80c0c54f, 0x8ec9c844, 0xa4f6eb75, 0xaaffe67e, 0xb8e4f163, 0xb6edfc68, 0x0c0a67b1, 0x02036aba, 0x10187da7, 0x1e1170ac, 0x342e539d, 0x3a275e96, 0x283c498b, 0x26354480, 0x7c420fe9, 0x724b02e2, 0x605015ff, 0x6e5918f4, 0x44663bc5, 0x4a6f36ce, 0x587421d3, 0x567d2cd8, 0x37a10c7a, 0x39a80171, 0x2bb3166c, 0x25ba1b67, 0x0f853856, 0x018c355d, 0x13972240, 0x1d9e2f4b, 0x47e96422, 0x49e06929, 0x5bfb7e34, 0x55f2733f, 0x7fcd500e, 0x71c45d05, 0x63df4a18, 0x6dd64713, 0xd731dcca, 0xd938d1c1, 0xcb23c6dc, 0xc52acbd7, 0xef15e8e6, 0xe11ce5ed, 0xf307f2f0, 0xfd0efffb, 0xa779b492, 0xa970b999, 0xbb6bae84, 0xb562a38f, 0x9f5d80be, 0x91548db5, 0x834f9aa8, 0x8d4697a3]);
+    this._mixCol = new Uint8Array(256);
+
+    for (var i = 0; i < 256; i++) {
+      if (i < 128) {
+        this._mixCol[i] = i << 1;
+      } else {
+        this._mixCol[i] = i << 1 ^ 0x1b;
+      }
+    }
+
+    this.buffer = new Uint8Array(16);
+    this.bufferPosition = 0;
+  }
+
+  _createClass(AESBaseCipher, [{
+    key: "_expandKey",
+    value: function _expandKey(cipherKey) {
+      (0, _util.unreachable)('Cannot call `_expandKey` on the base class');
+    }
+  }, {
+    key: "_decrypt",
+    value: function _decrypt(input, key) {
+      var t, u, v;
+      var state = new Uint8Array(16);
+      state.set(input);
+
+      for (var j = 0, k = this._keySize; j < 16; ++j, ++k) {
+        state[j] ^= key[k];
+      }
+
+      for (var i = this._cyclesOfRepetition - 1; i >= 1; --i) {
+        t = state[13];
+        state[13] = state[9];
+        state[9] = state[5];
+        state[5] = state[1];
+        state[1] = t;
+        t = state[14];
+        u = state[10];
+        state[14] = state[6];
+        state[10] = state[2];
+        state[6] = t;
+        state[2] = u;
+        t = state[15];
+        u = state[11];
+        v = state[7];
+        state[15] = state[3];
+        state[11] = t;
+        state[7] = u;
+        state[3] = v;
+
+        for (var _j = 0; _j < 16; ++_j) {
+          state[_j] = this._inv_s[state[_j]];
+        }
+
+        for (var _j2 = 0, _k = i * 16; _j2 < 16; ++_j2, ++_k) {
+          state[_j2] ^= key[_k];
+        }
+
+        for (var _j3 = 0; _j3 < 16; _j3 += 4) {
+          var s0 = this._mix[state[_j3]];
+          var s1 = this._mix[state[_j3 + 1]];
+          var s2 = this._mix[state[_j3 + 2]];
+          var s3 = this._mix[state[_j3 + 3]];
+          t = s0 ^ s1 >>> 8 ^ s1 << 24 ^ s2 >>> 16 ^ s2 << 16 ^ s3 >>> 24 ^ s3 << 8;
+          state[_j3] = t >>> 24 & 0xFF;
+          state[_j3 + 1] = t >> 16 & 0xFF;
+          state[_j3 + 2] = t >> 8 & 0xFF;
+          state[_j3 + 3] = t & 0xFF;
+        }
+      }
+
+      t = state[13];
+      state[13] = state[9];
+      state[9] = state[5];
+      state[5] = state[1];
+      state[1] = t;
+      t = state[14];
+      u = state[10];
+      state[14] = state[6];
+      state[10] = state[2];
+      state[6] = t;
+      state[2] = u;
+      t = state[15];
+      u = state[11];
+      v = state[7];
+      state[15] = state[3];
+      state[11] = t;
+      state[7] = u;
+      state[3] = v;
+
+      for (var _j4 = 0; _j4 < 16; ++_j4) {
+        state[_j4] = this._inv_s[state[_j4]];
+        state[_j4] ^= key[_j4];
+      }
+
+      return state;
+    }
+  }, {
+    key: "_encrypt",
+    value: function _encrypt(input, key) {
+      var s = this._s;
+      var t, u, v;
+      var state = new Uint8Array(16);
+      state.set(input);
+
+      for (var j = 0; j < 16; ++j) {
+        state[j] ^= key[j];
+      }
+
+      for (var i = 1; i < this._cyclesOfRepetition; i++) {
+        for (var _j5 = 0; _j5 < 16; ++_j5) {
+          state[_j5] = s[state[_j5]];
+        }
+
+        v = state[1];
+        state[1] = state[5];
+        state[5] = state[9];
+        state[9] = state[13];
+        state[13] = v;
+        v = state[2];
+        u = state[6];
+        state[2] = state[10];
+        state[6] = state[14];
+        state[10] = v;
+        state[14] = u;
+        v = state[3];
+        u = state[7];
+        t = state[11];
+        state[3] = state[15];
+        state[7] = v;
+        state[11] = u;
+        state[15] = t;
+
+        for (var _j6 = 0; _j6 < 16; _j6 += 4) {
+          var s0 = state[_j6 + 0];
+          var s1 = state[_j6 + 1];
+          var s2 = state[_j6 + 2];
+          var s3 = state[_j6 + 3];
+          t = s0 ^ s1 ^ s2 ^ s3;
+          state[_j6 + 0] ^= t ^ this._mixCol[s0 ^ s1];
+          state[_j6 + 1] ^= t ^ this._mixCol[s1 ^ s2];
+          state[_j6 + 2] ^= t ^ this._mixCol[s2 ^ s3];
+          state[_j6 + 3] ^= t ^ this._mixCol[s3 ^ s0];
+        }
+
+        for (var _j7 = 0, k = i * 16; _j7 < 16; ++_j7, ++k) {
+          state[_j7] ^= key[k];
+        }
+      }
+
+      for (var _j8 = 0; _j8 < 16; ++_j8) {
+        state[_j8] = s[state[_j8]];
+      }
+
+      v = state[1];
+      state[1] = state[5];
+      state[5] = state[9];
+      state[9] = state[13];
+      state[13] = v;
+      v = state[2];
+      u = state[6];
+      state[2] = state[10];
+      state[6] = state[14];
+      state[10] = v;
+      state[14] = u;
+      v = state[3];
+      u = state[7];
+      t = state[11];
+      state[3] = state[15];
+      state[7] = v;
+      state[11] = u;
+      state[15] = t;
+
+      for (var _j9 = 0, _k2 = this._keySize; _j9 < 16; ++_j9, ++_k2) {
+        state[_j9] ^= key[_k2];
+      }
+
+      return state;
+    }
+  }, {
+    key: "_decryptBlock2",
+    value: function _decryptBlock2(data, finalize) {
+      var sourceLength = data.length;
+      var buffer = this.buffer,
+          bufferLength = this.bufferPosition;
+      var result = [],
+          iv = this.iv;
+
+      for (var i = 0; i < sourceLength; ++i) {
+        buffer[bufferLength] = data[i];
+        ++bufferLength;
+
+        if (bufferLength < 16) {
+          continue;
+        }
+
+        var plain = this._decrypt(buffer, this._key);
+
+        for (var j = 0; j < 16; ++j) {
+          plain[j] ^= iv[j];
+        }
+
+        iv = buffer;
+        result.push(plain);
+        buffer = new Uint8Array(16);
+        bufferLength = 0;
+      }
+
+      this.buffer = buffer;
+      this.bufferLength = bufferLength;
+      this.iv = iv;
+
+      if (result.length === 0) {
+        return new Uint8Array(0);
+      }
+
+      var outputLength = 16 * result.length;
+
+      if (finalize) {
+        var lastBlock = result[result.length - 1];
+        var psLen = lastBlock[15];
+
+        if (psLen <= 16) {
+          for (var _i = 15, ii = 16 - psLen; _i >= ii; --_i) {
+            if (lastBlock[_i] !== psLen) {
+              psLen = 0;
+              break;
+            }
+          }
+
+          outputLength -= psLen;
+          result[result.length - 1] = lastBlock.subarray(0, 16 - psLen);
+        }
+      }
+
+      var output = new Uint8Array(outputLength);
+
+      for (var _i2 = 0, _j10 = 0, _ii = result.length; _i2 < _ii; ++_i2, _j10 += 16) {
+        output.set(result[_i2], _j10);
+      }
+
+      return output;
+    }
+  }, {
+    key: "decryptBlock",
+    value: function decryptBlock(data, finalize) {
+      var iv = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
+      var sourceLength = data.length;
+      var buffer = this.buffer,
+          bufferLength = this.bufferPosition;
+
+      if (iv) {
+        this.iv = iv;
+      } else {
+        for (var i = 0; bufferLength < 16 && i < sourceLength; ++i, ++bufferLength) {
+          buffer[bufferLength] = data[i];
+        }
+
+        if (bufferLength < 16) {
+          this.bufferLength = bufferLength;
+          return new Uint8Array(0);
+        }
+
+        this.iv = buffer;
+        data = data.subarray(16);
+      }
+
+      this.buffer = new Uint8Array(16);
+      this.bufferLength = 0;
+      this.decryptBlock = this._decryptBlock2;
+      return this.decryptBlock(data, finalize);
+    }
+  }, {
+    key: "encrypt",
+    value: function encrypt(data, iv) {
+      var sourceLength = data.length;
+      var buffer = this.buffer,
+          bufferLength = this.bufferPosition;
+      var result = [];
+
+      if (!iv) {
+        iv = new Uint8Array(16);
+      }
+
+      for (var i = 0; i < sourceLength; ++i) {
+        buffer[bufferLength] = data[i];
+        ++bufferLength;
+
+        if (bufferLength < 16) {
+          continue;
+        }
+
+        for (var j = 0; j < 16; ++j) {
+          buffer[j] ^= iv[j];
+        }
+
+        var cipher = this._encrypt(buffer, this._key);
+
+        iv = cipher;
+        result.push(cipher);
+        buffer = new Uint8Array(16);
+        bufferLength = 0;
+      }
+
+      this.buffer = buffer;
+      this.bufferLength = bufferLength;
+      this.iv = iv;
+
+      if (result.length === 0) {
+        return new Uint8Array(0);
+      }
+
+      var outputLength = 16 * result.length;
+      var output = new Uint8Array(outputLength);
+
+      for (var _i3 = 0, _j11 = 0, ii = result.length; _i3 < ii; ++_i3, _j11 += 16) {
+        output.set(result[_i3], _j11);
+      }
+
+      return output;
+    }
+  }]);
+
+  return AESBaseCipher;
+}();
+
+var AES128Cipher =
+/*#__PURE__*/
+function (_AESBaseCipher) {
+  _inherits(AES128Cipher, _AESBaseCipher);
+
+  function AES128Cipher(key) {
+    var _this;
+
+    _classCallCheck(this, AES128Cipher);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(AES128Cipher).call(this));
+    _this._cyclesOfRepetition = 10;
+    _this._keySize = 160;
+    _this._rcon = new Uint8Array([0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36, 0x6c, 0xd8, 0xab, 0x4d, 0x9a, 0x2f, 0x5e, 0xbc, 0x63, 0xc6, 0x97, 0x35, 0x6a, 0xd4, 0xb3, 0x7d, 0xfa, 0xef, 0xc5, 0x91, 0x39, 0x72, 0xe4, 0xd3, 0xbd, 0x61, 0xc2, 0x9f, 0x25, 0x4a, 0x94, 0x33, 0x66, 0xcc, 0x83, 0x1d, 0x3a, 0x74, 0xe8, 0xcb, 0x8d]);
+    _this._key = _this._expandKey(key);
+    return _this;
+  }
+
+  _createClass(AES128Cipher, [{
+    key: "_expandKey",
+    value: function _expandKey(cipherKey) {
+      var b = 176;
+      var s = this._s;
+      var rcon = this._rcon;
+      var result = new Uint8Array(b);
+      result.set(cipherKey);
+
+      for (var j = 16, i = 1; j < b; ++i) {
+        var t1 = result[j - 3];
+        var t2 = result[j - 2];
+        var t3 = result[j - 1];
+        var t4 = result[j - 4];
+        t1 = s[t1];
+        t2 = s[t2];
+        t3 = s[t3];
+        t4 = s[t4];
+        t1 = t1 ^ rcon[i];
+
+        for (var n = 0; n < 4; ++n) {
+          result[j] = t1 ^= result[j - 16];
+          j++;
+          result[j] = t2 ^= result[j - 16];
+          j++;
+          result[j] = t3 ^= result[j - 16];
+          j++;
+          result[j] = t4 ^= result[j - 16];
+          j++;
+        }
+      }
+
+      return result;
+    }
+  }]);
+
+  return AES128Cipher;
+}(AESBaseCipher);
+
+exports.AES128Cipher = AES128Cipher;
+
+var AES256Cipher =
+/*#__PURE__*/
+function (_AESBaseCipher2) {
+  _inherits(AES256Cipher, _AESBaseCipher2);
+
+  function AES256Cipher(key) {
+    var _this2;
+
+    _classCallCheck(this, AES256Cipher);
+
+    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(AES256Cipher).call(this));
+    _this2._cyclesOfRepetition = 14;
+    _this2._keySize = 224;
+    _this2._key = _this2._expandKey(key);
+    return _this2;
+  }
+
+  _createClass(AES256Cipher, [{
+    key: "_expandKey",
+    value: function _expandKey(cipherKey) {
+      var b = 240;
+      var s = this._s;
+      var result = new Uint8Array(b);
+      result.set(cipherKey);
+      var r = 1;
+      var t1, t2, t3, t4;
+
+      for (var j = 32, i = 1; j < b; ++i) {
+        if (j % 32 === 16) {
+          t1 = s[t1];
+          t2 = s[t2];
+          t3 = s[t3];
+          t4 = s[t4];
+        } else if (j % 32 === 0) {
+          t1 = result[j - 3];
+          t2 = result[j - 2];
+          t3 = result[j - 1];
+          t4 = result[j - 4];
+          t1 = s[t1];
+          t2 = s[t2];
+          t3 = s[t3];
+          t4 = s[t4];
+          t1 = t1 ^ r;
+
+          if ((r <<= 1) >= 256) {
+            r = (r ^ 0x1b) & 0xFF;
+          }
+        }
+
+        for (var n = 0; n < 4; ++n) {
+          result[j] = t1 ^= result[j - 32];
+          j++;
+          result[j] = t2 ^= result[j - 32];
+          j++;
+          result[j] = t3 ^= result[j - 32];
+          j++;
+          result[j] = t4 ^= result[j - 32];
+          j++;
+        }
+      }
+
+      return result;
+    }
+  }]);
+
+  return AES256Cipher;
+}(AESBaseCipher);
+
+exports.AES256Cipher = AES256Cipher;
+
+var PDF17 = function PDF17Closure() {
+  function compareByteArrays(array1, array2) {
+    if (array1.length !== array2.length) {
+      return false;
+    }
+
+    for (var i = 0; i < array1.length; i++) {
+      if (array1[i] !== array2[i]) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  function PDF17() {}
+
+  PDF17.prototype = {
+    checkOwnerPassword: function PDF17_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
+      var hashData = new Uint8Array(password.length + 56);
+      hashData.set(password, 0);
+      hashData.set(ownerValidationSalt, password.length);
+      hashData.set(userBytes, password.length + ownerValidationSalt.length);
+      var result = calculateSHA256(hashData, 0, hashData.length);
+      return compareByteArrays(result, ownerPassword);
+    },
+    checkUserPassword: function PDF17_checkUserPassword(password, userValidationSalt, userPassword) {
+      var hashData = new Uint8Array(password.length + 8);
+      hashData.set(password, 0);
+      hashData.set(userValidationSalt, password.length);
+      var result = calculateSHA256(hashData, 0, hashData.length);
+      return compareByteArrays(result, userPassword);
+    },
+    getOwnerKey: function PDF17_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
+      var hashData = new Uint8Array(password.length + 56);
+      hashData.set(password, 0);
+      hashData.set(ownerKeySalt, password.length);
+      hashData.set(userBytes, password.length + ownerKeySalt.length);
+      var key = calculateSHA256(hashData, 0, hashData.length);
+      var cipher = new AES256Cipher(key);
+      return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
+    },
+    getUserKey: function PDF17_getUserKey(password, userKeySalt, userEncryption) {
+      var hashData = new Uint8Array(password.length + 8);
+      hashData.set(password, 0);
+      hashData.set(userKeySalt, password.length);
+      var key = calculateSHA256(hashData, 0, hashData.length);
+      var cipher = new AES256Cipher(key);
+      return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
+    }
+  };
+  return PDF17;
+}();
+
+exports.PDF17 = PDF17;
+
+var PDF20 = function PDF20Closure() {
+  function concatArrays(array1, array2) {
+    var t = new Uint8Array(array1.length + array2.length);
+    t.set(array1, 0);
+    t.set(array2, array1.length);
+    return t;
+  }
+
+  function calculatePDF20Hash(password, input, userBytes) {
+    var k = calculateSHA256(input, 0, input.length).subarray(0, 32);
+    var e = [0];
+    var i = 0;
+
+    while (i < 64 || e[e.length - 1] > i - 32) {
+      var arrayLength = password.length + k.length + userBytes.length;
+      var k1 = new Uint8Array(arrayLength * 64);
+      var array = concatArrays(password, k);
+      array = concatArrays(array, userBytes);
+
+      for (var j = 0, pos = 0; j < 64; j++, pos += arrayLength) {
+        k1.set(array, pos);
+      }
+
+      var cipher = new AES128Cipher(k.subarray(0, 16));
+      e = cipher.encrypt(k1, k.subarray(16, 32));
+      var remainder = 0;
+
+      for (var z = 0; z < 16; z++) {
+        remainder *= 256 % 3;
+        remainder %= 3;
+        remainder += (e[z] >>> 0) % 3;
+        remainder %= 3;
+      }
+
+      if (remainder === 0) {
+        k = calculateSHA256(e, 0, e.length);
+      } else if (remainder === 1) {
+        k = calculateSHA384(e, 0, e.length);
+      } else if (remainder === 2) {
+        k = calculateSHA512(e, 0, e.length);
+      }
+
+      i++;
+    }
+
+    return k.subarray(0, 32);
+  }
+
+  function PDF20() {}
+
+  function compareByteArrays(array1, array2) {
+    if (array1.length !== array2.length) {
+      return false;
+    }
+
+    for (var i = 0; i < array1.length; i++) {
+      if (array1[i] !== array2[i]) {
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  PDF20.prototype = {
+    hash: function PDF20_hash(password, concatBytes, userBytes) {
+      return calculatePDF20Hash(password, concatBytes, userBytes);
+    },
+    checkOwnerPassword: function PDF20_checkOwnerPassword(password, ownerValidationSalt, userBytes, ownerPassword) {
+      var hashData = new Uint8Array(password.length + 56);
+      hashData.set(password, 0);
+      hashData.set(ownerValidationSalt, password.length);
+      hashData.set(userBytes, password.length + ownerValidationSalt.length);
+      var result = calculatePDF20Hash(password, hashData, userBytes);
+      return compareByteArrays(result, ownerPassword);
+    },
+    checkUserPassword: function PDF20_checkUserPassword(password, userValidationSalt, userPassword) {
+      var hashData = new Uint8Array(password.length + 8);
+      hashData.set(password, 0);
+      hashData.set(userValidationSalt, password.length);
+      var result = calculatePDF20Hash(password, hashData, []);
+      return compareByteArrays(result, userPassword);
+    },
+    getOwnerKey: function PDF20_getOwnerKey(password, ownerKeySalt, userBytes, ownerEncryption) {
+      var hashData = new Uint8Array(password.length + 56);
+      hashData.set(password, 0);
+      hashData.set(ownerKeySalt, password.length);
+      hashData.set(userBytes, password.length + ownerKeySalt.length);
+      var key = calculatePDF20Hash(password, hashData, userBytes);
+      var cipher = new AES256Cipher(key);
+      return cipher.decryptBlock(ownerEncryption, false, new Uint8Array(16));
+    },
+    getUserKey: function PDF20_getUserKey(password, userKeySalt, userEncryption) {
+      var hashData = new Uint8Array(password.length + 8);
+      hashData.set(password, 0);
+      hashData.set(userKeySalt, password.length);
+      var key = calculatePDF20Hash(password, hashData, []);
+      var cipher = new AES256Cipher(key);
+      return cipher.decryptBlock(userEncryption, false, new Uint8Array(16));
+    }
+  };
+  return PDF20;
+}();
+
+exports.PDF20 = PDF20;
+
+var CipherTransform = function CipherTransformClosure() {
+  function CipherTransform(stringCipherConstructor, streamCipherConstructor) {
+    this.StringCipherConstructor = stringCipherConstructor;
+    this.StreamCipherConstructor = streamCipherConstructor;
+  }
+
+  CipherTransform.prototype = {
+    createStream: function CipherTransform_createStream(stream, length) {
+      var cipher = new this.StreamCipherConstructor();
+      return new _stream.DecryptStream(stream, length, function cipherTransformDecryptStream(data, finalize) {
+        return cipher.decryptBlock(data, finalize);
+      });
+    },
+    decryptString: function CipherTransform_decryptString(s) {
+      var cipher = new this.StringCipherConstructor();
+      var data = (0, _util.stringToBytes)(s);
+      data = cipher.decryptBlock(data, true);
+      return (0, _util.bytesToString)(data);
+    }
+  };
+  return CipherTransform;
+}();
+
+var CipherTransformFactory = function CipherTransformFactoryClosure() {
+  var defaultPasswordBytes = new Uint8Array([0x28, 0xBF, 0x4E, 0x5E, 0x4E, 0x75, 0x8A, 0x41, 0x64, 0x00, 0x4E, 0x56, 0xFF, 0xFA, 0x01, 0x08, 0x2E, 0x2E, 0x00, 0xB6, 0xD0, 0x68, 0x3E, 0x80, 0x2F, 0x0C, 0xA9, 0xFE, 0x64, 0x53, 0x69, 0x7A]);
+
+  function createEncryptionKey20(revision, password, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms) {
+    if (password) {
+      var passwordLength = Math.min(127, password.length);
+      password = password.subarray(0, passwordLength);
+    } else {
+      password = [];
+    }
+
+    var pdfAlgorithm;
+
+    if (revision === 6) {
+      pdfAlgorithm = new PDF20();
+    } else {
+      pdfAlgorithm = new PDF17();
+    }
+
+    if (pdfAlgorithm.checkUserPassword(password, userValidationSalt, userPassword)) {
+      return pdfAlgorithm.getUserKey(password, userKeySalt, userEncryption);
+    } else if (password.length && pdfAlgorithm.checkOwnerPassword(password, ownerValidationSalt, uBytes, ownerPassword)) {
+      return pdfAlgorithm.getOwnerKey(password, ownerKeySalt, uBytes, ownerEncryption);
+    }
+
+    return null;
+  }
+
+  function prepareKeyData(fileId, password, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata) {
+    var hashDataSize = 40 + ownerPassword.length + fileId.length;
+    var hashData = new Uint8Array(hashDataSize),
+        i = 0,
+        j,
+        n;
+
+    if (password) {
+      n = Math.min(32, password.length);
+
+      for (; i < n; ++i) {
+        hashData[i] = password[i];
+      }
+    }
+
+    j = 0;
+
+    while (i < 32) {
+      hashData[i++] = defaultPasswordBytes[j++];
+    }
+
+    for (j = 0, n = ownerPassword.length; j < n; ++j) {
+      hashData[i++] = ownerPassword[j];
+    }
+
+    hashData[i++] = flags & 0xFF;
+    hashData[i++] = flags >> 8 & 0xFF;
+    hashData[i++] = flags >> 16 & 0xFF;
+    hashData[i++] = flags >>> 24 & 0xFF;
+
+    for (j = 0, n = fileId.length; j < n; ++j) {
+      hashData[i++] = fileId[j];
+    }
+
+    if (revision >= 4 && !encryptMetadata) {
+      hashData[i++] = 0xFF;
+      hashData[i++] = 0xFF;
+      hashData[i++] = 0xFF;
+      hashData[i++] = 0xFF;
+    }
+
+    var hash = calculateMD5(hashData, 0, i);
+    var keyLengthInBytes = keyLength >> 3;
+
+    if (revision >= 3) {
+      for (j = 0; j < 50; ++j) {
+        hash = calculateMD5(hash, 0, keyLengthInBytes);
+      }
+    }
+
+    var encryptionKey = hash.subarray(0, keyLengthInBytes);
+    var cipher, checkData;
+
+    if (revision >= 3) {
+      for (i = 0; i < 32; ++i) {
+        hashData[i] = defaultPasswordBytes[i];
+      }
+
+      for (j = 0, n = fileId.length; j < n; ++j) {
+        hashData[i++] = fileId[j];
+      }
+
+      cipher = new ARCFourCipher(encryptionKey);
+      checkData = cipher.encryptBlock(calculateMD5(hashData, 0, i));
+      n = encryptionKey.length;
+      var derivedKey = new Uint8Array(n),
+          k;
+
+      for (j = 1; j <= 19; ++j) {
+        for (k = 0; k < n; ++k) {
+          derivedKey[k] = encryptionKey[k] ^ j;
+        }
+
+        cipher = new ARCFourCipher(derivedKey);
+        checkData = cipher.encryptBlock(checkData);
+      }
+
+      for (j = 0, n = checkData.length; j < n; ++j) {
+        if (userPassword[j] !== checkData[j]) {
+          return null;
+        }
+      }
+    } else {
+      cipher = new ARCFourCipher(encryptionKey);
+      checkData = cipher.encryptBlock(defaultPasswordBytes);
+
+      for (j = 0, n = checkData.length; j < n; ++j) {
+        if (userPassword[j] !== checkData[j]) {
+          return null;
+        }
+      }
+    }
+
+    return encryptionKey;
+  }
+
+  function decodeUserPassword(password, ownerPassword, revision, keyLength) {
+    var hashData = new Uint8Array(32),
+        i = 0,
+        j,
+        n;
+    n = Math.min(32, password.length);
+
+    for (; i < n; ++i) {
+      hashData[i] = password[i];
+    }
+
+    j = 0;
+
+    while (i < 32) {
+      hashData[i++] = defaultPasswordBytes[j++];
+    }
+
+    var hash = calculateMD5(hashData, 0, i);
+    var keyLengthInBytes = keyLength >> 3;
+
+    if (revision >= 3) {
+      for (j = 0; j < 50; ++j) {
+        hash = calculateMD5(hash, 0, hash.length);
+      }
+    }
+
+    var cipher, userPassword;
+
+    if (revision >= 3) {
+      userPassword = ownerPassword;
+      var derivedKey = new Uint8Array(keyLengthInBytes),
+          k;
+
+      for (j = 19; j >= 0; j--) {
+        for (k = 0; k < keyLengthInBytes; ++k) {
+          derivedKey[k] = hash[k] ^ j;
+        }
+
+        cipher = new ARCFourCipher(derivedKey);
+        userPassword = cipher.encryptBlock(userPassword);
+      }
+    } else {
+      cipher = new ARCFourCipher(hash.subarray(0, keyLengthInBytes));
+      userPassword = cipher.encryptBlock(ownerPassword);
+    }
+
+    return userPassword;
+  }
+
+  var identityName = _primitives.Name.get('Identity');
+
+  function CipherTransformFactory(dict, fileId, password) {
+    var filter = dict.get('Filter');
+
+    if (!(0, _primitives.isName)(filter, 'Standard')) {
+      throw new _util.FormatError('unknown encryption method');
+    }
+
+    this.dict = dict;
+    var algorithm = dict.get('V');
+
+    if (!Number.isInteger(algorithm) || algorithm !== 1 && algorithm !== 2 && algorithm !== 4 && algorithm !== 5) {
+      throw new _util.FormatError('unsupported encryption algorithm');
+    }
+
+    this.algorithm = algorithm;
+    var keyLength = dict.get('Length');
+
+    if (!keyLength) {
+      if (algorithm <= 3) {
+        keyLength = 40;
+      } else {
+        var cfDict = dict.get('CF');
+        var streamCryptoName = dict.get('StmF');
+
+        if ((0, _primitives.isDict)(cfDict) && (0, _primitives.isName)(streamCryptoName)) {
+          cfDict.suppressEncryption = true;
+          var handlerDict = cfDict.get(streamCryptoName.name);
+          keyLength = handlerDict && handlerDict.get('Length') || 128;
+
+          if (keyLength < 40) {
+            keyLength <<= 3;
+          }
+        }
+      }
+    }
+
+    if (!Number.isInteger(keyLength) || keyLength < 40 || keyLength % 8 !== 0) {
+      throw new _util.FormatError('invalid key length');
+    }
+
+    var ownerPassword = (0, _util.stringToBytes)(dict.get('O')).subarray(0, 32);
+    var userPassword = (0, _util.stringToBytes)(dict.get('U')).subarray(0, 32);
+    var flags = dict.get('P');
+    var revision = dict.get('R');
+    var encryptMetadata = (algorithm === 4 || algorithm === 5) && dict.get('EncryptMetadata') !== false;
+    this.encryptMetadata = encryptMetadata;
+    var fileIdBytes = (0, _util.stringToBytes)(fileId);
+    var passwordBytes;
+
+    if (password) {
+      if (revision === 6) {
+        try {
+          password = (0, _util.utf8StringToString)(password);
+        } catch (ex) {
+          (0, _util.warn)('CipherTransformFactory: ' + 'Unable to convert UTF8 encoded password.');
+        }
+      }
+
+      passwordBytes = (0, _util.stringToBytes)(password);
+    }
+
+    var encryptionKey;
+
+    if (algorithm !== 5) {
+      encryptionKey = prepareKeyData(fileIdBytes, passwordBytes, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
+    } else {
+      var ownerValidationSalt = (0, _util.stringToBytes)(dict.get('O')).subarray(32, 40);
+      var ownerKeySalt = (0, _util.stringToBytes)(dict.get('O')).subarray(40, 48);
+      var uBytes = (0, _util.stringToBytes)(dict.get('U')).subarray(0, 48);
+      var userValidationSalt = (0, _util.stringToBytes)(dict.get('U')).subarray(32, 40);
+      var userKeySalt = (0, _util.stringToBytes)(dict.get('U')).subarray(40, 48);
+      var ownerEncryption = (0, _util.stringToBytes)(dict.get('OE'));
+      var userEncryption = (0, _util.stringToBytes)(dict.get('UE'));
+      var perms = (0, _util.stringToBytes)(dict.get('Perms'));
+      encryptionKey = createEncryptionKey20(revision, passwordBytes, ownerPassword, ownerValidationSalt, ownerKeySalt, uBytes, userPassword, userValidationSalt, userKeySalt, ownerEncryption, userEncryption, perms);
+    }
+
+    if (!encryptionKey && !password) {
+      throw new _util.PasswordException('No password given', _util.PasswordResponses.NEED_PASSWORD);
+    } else if (!encryptionKey && password) {
+      var decodedPassword = decodeUserPassword(passwordBytes, ownerPassword, revision, keyLength);
+      encryptionKey = prepareKeyData(fileIdBytes, decodedPassword, ownerPassword, userPassword, flags, revision, keyLength, encryptMetadata);
+    }
+
+    if (!encryptionKey) {
+      throw new _util.PasswordException('Incorrect Password', _util.PasswordResponses.INCORRECT_PASSWORD);
+    }
+
+    this.encryptionKey = encryptionKey;
+
+    if (algorithm >= 4) {
+      var cf = dict.get('CF');
+
+      if ((0, _primitives.isDict)(cf)) {
+        cf.suppressEncryption = true;
+      }
+
+      this.cf = cf;
+      this.stmf = dict.get('StmF') || identityName;
+      this.strf = dict.get('StrF') || identityName;
+      this.eff = dict.get('EFF') || this.stmf;
+    }
+  }
+
+  function buildObjectKey(num, gen, encryptionKey, isAes) {
+    var key = new Uint8Array(encryptionKey.length + 9),
+        i,
+        n;
+
+    for (i = 0, n = encryptionKey.length; i < n; ++i) {
+      key[i] = encryptionKey[i];
+    }
+
+    key[i++] = num & 0xFF;
+    key[i++] = num >> 8 & 0xFF;
+    key[i++] = num >> 16 & 0xFF;
+    key[i++] = gen & 0xFF;
+    key[i++] = gen >> 8 & 0xFF;
+
+    if (isAes) {
+      key[i++] = 0x73;
+      key[i++] = 0x41;
+      key[i++] = 0x6C;
+      key[i++] = 0x54;
+    }
+
+    var hash = calculateMD5(key, 0, i);
+    return hash.subarray(0, Math.min(encryptionKey.length + 5, 16));
+  }
+
+  function buildCipherConstructor(cf, name, num, gen, key) {
+    if (!(0, _primitives.isName)(name)) {
+      throw new _util.FormatError('Invalid crypt filter name.');
+    }
+
+    var cryptFilter = cf.get(name.name);
+    var cfm;
+
+    if (cryptFilter !== null && cryptFilter !== undefined) {
+      cfm = cryptFilter.get('CFM');
+    }
+
+    if (!cfm || cfm.name === 'None') {
+      return function cipherTransformFactoryBuildCipherConstructorNone() {
+        return new NullCipher();
+      };
+    }
+
+    if (cfm.name === 'V2') {
+      return function cipherTransformFactoryBuildCipherConstructorV2() {
+        return new ARCFourCipher(buildObjectKey(num, gen, key, false));
+      };
+    }
+
+    if (cfm.name === 'AESV2') {
+      return function cipherTransformFactoryBuildCipherConstructorAESV2() {
+        return new AES128Cipher(buildObjectKey(num, gen, key, true));
+      };
+    }
+
+    if (cfm.name === 'AESV3') {
+      return function cipherTransformFactoryBuildCipherConstructorAESV3() {
+        return new AES256Cipher(key);
+      };
+    }
+
+    throw new _util.FormatError('Unknown crypto method');
+  }
+
+  CipherTransformFactory.prototype = {
+    createCipherTransform: function CipherTransformFactory_createCipherTransform(num, gen) {
+      if (this.algorithm === 4 || this.algorithm === 5) {
+        return new CipherTransform(buildCipherConstructor(this.cf, this.stmf, num, gen, this.encryptionKey), buildCipherConstructor(this.cf, this.strf, num, gen, this.encryptionKey));
+      }
+
+      var key = buildObjectKey(num, gen, this.encryptionKey, false);
+
+      var cipherConstructor = function buildCipherCipherConstructor() {
+        return new ARCFourCipher(key);
+      };
+
+      return new CipherTransform(cipherConstructor, cipherConstructor);
+    }
+  };
+  return CipherTransformFactory;
+}();
+
+exports.CipherTransformFactory = CipherTransformFactory;
+
+/***/ }),
+/* 169 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ColorSpace = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+function resizeRgbImage(src, dest, w1, h1, w2, h2, alpha01) {
+  var COMPONENTS = 3;
+  alpha01 = alpha01 !== 1 ? 0 : alpha01;
+  var xRatio = w1 / w2;
+  var yRatio = h1 / h2;
+  var newIndex = 0,
+      oldIndex;
+  var xScaled = new Uint16Array(w2);
+  var w1Scanline = w1 * COMPONENTS;
+
+  for (var i = 0; i < w2; i++) {
+    xScaled[i] = Math.floor(i * xRatio) * COMPONENTS;
+  }
+
+  for (var _i = 0; _i < h2; _i++) {
+    var py = Math.floor(_i * yRatio) * w1Scanline;
+
+    for (var j = 0; j < w2; j++) {
+      oldIndex = py + xScaled[j];
+      dest[newIndex++] = src[oldIndex++];
+      dest[newIndex++] = src[oldIndex++];
+      dest[newIndex++] = src[oldIndex++];
+      newIndex += alpha01;
+    }
+  }
+}
+
+var ColorSpace =
+/*#__PURE__*/
+function () {
+  function ColorSpace(name, numComps) {
+    _classCallCheck(this, ColorSpace);
+
+    if (this.constructor === ColorSpace) {
+      (0, _util.unreachable)('Cannot initialize ColorSpace.');
+    }
+
+    this.name = name;
+    this.numComps = numComps;
+  }
+
+  _createClass(ColorSpace, [{
+    key: "getRgb",
+    value: function getRgb(src, srcOffset) {
+      var rgb = new Uint8ClampedArray(3);
+      this.getRgbItem(src, srcOffset, rgb, 0);
+      return rgb;
+    }
+  }, {
+    key: "getRgbItem",
+    value: function getRgbItem(src, srcOffset, dest, destOffset) {
+      (0, _util.unreachable)('Should not call ColorSpace.getRgbItem');
+    }
+  }, {
+    key: "getRgbBuffer",
+    value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+      (0, _util.unreachable)('Should not call ColorSpace.getRgbBuffer');
+    }
+  }, {
+    key: "getOutputLength",
+    value: function getOutputLength(inputLength, alpha01) {
+      (0, _util.unreachable)('Should not call ColorSpace.getOutputLength');
+    }
+  }, {
+    key: "isPassthrough",
+    value: function isPassthrough(bits) {
+      return false;
+    }
+  }, {
+    key: "isDefaultDecode",
+    value: function isDefaultDecode(decodeMap, bpc) {
+      return ColorSpace.isDefaultDecode(decodeMap, this.numComps);
+    }
+  }, {
+    key: "fillRgb",
+    value: function fillRgb(dest, originalWidth, originalHeight, width, height, actualHeight, bpc, comps, alpha01) {
+      var count = originalWidth * originalHeight;
+      var rgbBuf = null;
+      var numComponentColors = 1 << bpc;
+      var needsResizing = originalHeight !== height || originalWidth !== width;
+
+      if (this.isPassthrough(bpc)) {
+        rgbBuf = comps;
+      } else if (this.numComps === 1 && count > numComponentColors && this.name !== 'DeviceGray' && this.name !== 'DeviceRGB') {
+        var allColors = bpc <= 8 ? new Uint8Array(numComponentColors) : new Uint16Array(numComponentColors);
+
+        for (var i = 0; i < numComponentColors; i++) {
+          allColors[i] = i;
+        }
+
+        var colorMap = new Uint8ClampedArray(numComponentColors * 3);
+        this.getRgbBuffer(allColors, 0, numComponentColors, colorMap, 0, bpc, 0);
+
+        if (!needsResizing) {
+          var destPos = 0;
+
+          for (var _i2 = 0; _i2 < count; ++_i2) {
+            var key = comps[_i2] * 3;
+            dest[destPos++] = colorMap[key];
+            dest[destPos++] = colorMap[key + 1];
+            dest[destPos++] = colorMap[key + 2];
+            destPos += alpha01;
+          }
+        } else {
+          rgbBuf = new Uint8Array(count * 3);
+          var rgbPos = 0;
+
+          for (var _i3 = 0; _i3 < count; ++_i3) {
+            var _key = comps[_i3] * 3;
+
+            rgbBuf[rgbPos++] = colorMap[_key];
+            rgbBuf[rgbPos++] = colorMap[_key + 1];
+            rgbBuf[rgbPos++] = colorMap[_key + 2];
+          }
+        }
+      } else {
+        if (!needsResizing) {
+          this.getRgbBuffer(comps, 0, width * actualHeight, dest, 0, bpc, alpha01);
+        } else {
+          rgbBuf = new Uint8ClampedArray(count * 3);
+          this.getRgbBuffer(comps, 0, count, rgbBuf, 0, bpc, 0);
+        }
+      }
+
+      if (rgbBuf) {
+        if (needsResizing) {
+          resizeRgbImage(rgbBuf, dest, originalWidth, originalHeight, width, height, alpha01);
+        } else {
+          var _destPos = 0,
+              _rgbPos = 0;
+
+          for (var _i4 = 0, ii = width * actualHeight; _i4 < ii; _i4++) {
+            dest[_destPos++] = rgbBuf[_rgbPos++];
+            dest[_destPos++] = rgbBuf[_rgbPos++];
+            dest[_destPos++] = rgbBuf[_rgbPos++];
+            _destPos += alpha01;
+          }
+        }
+      }
+    }
+  }, {
+    key: "usesZeroToOneRange",
+    get: function get() {
+      return (0, _util.shadow)(this, 'usesZeroToOneRange', true);
+    }
+  }], [{
+    key: "parse",
+    value: function parse(cs, xref, res, pdfFunctionFactory) {
+      var IR = this.parseToIR(cs, xref, res, pdfFunctionFactory);
+      return this.fromIR(IR);
+    }
+  }, {
+    key: "fromIR",
+    value: function fromIR(IR) {
+      var name = Array.isArray(IR) ? IR[0] : IR;
+      var whitePoint, blackPoint, gamma;
+
+      switch (name) {
+        case 'DeviceGrayCS':
+          return this.singletons.gray;
+
+        case 'DeviceRgbCS':
+          return this.singletons.rgb;
+
+        case 'DeviceCmykCS':
+          return this.singletons.cmyk;
+
+        case 'CalGrayCS':
+          whitePoint = IR[1];
+          blackPoint = IR[2];
+          gamma = IR[3];
+          return new CalGrayCS(whitePoint, blackPoint, gamma);
+
+        case 'CalRGBCS':
+          whitePoint = IR[1];
+          blackPoint = IR[2];
+          gamma = IR[3];
+          var matrix = IR[4];
+          return new CalRGBCS(whitePoint, blackPoint, gamma, matrix);
+
+        case 'PatternCS':
+          var basePatternCS = IR[1];
+
+          if (basePatternCS) {
+            basePatternCS = this.fromIR(basePatternCS);
+          }
+
+          return new PatternCS(basePatternCS);
+
+        case 'IndexedCS':
+          var baseIndexedCS = IR[1];
+          var hiVal = IR[2];
+          var lookup = IR[3];
+          return new IndexedCS(this.fromIR(baseIndexedCS), hiVal, lookup);
+
+        case 'AlternateCS':
+          var numComps = IR[1];
+          var alt = IR[2];
+          var tintFn = IR[3];
+          return new AlternateCS(numComps, this.fromIR(alt), tintFn);
+
+        case 'LabCS':
+          whitePoint = IR[1];
+          blackPoint = IR[2];
+          var range = IR[3];
+          return new LabCS(whitePoint, blackPoint, range);
+
+        default:
+          throw new _util.FormatError("Unknown colorspace name: ".concat(name));
+      }
+    }
+  }, {
+    key: "parseToIR",
+    value: function parseToIR(cs, xref) {
+      var res = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;
+      var pdfFunctionFactory = arguments.length > 3 ? arguments[3] : undefined;
+      cs = xref.fetchIfRef(cs);
+
+      if ((0, _primitives.isName)(cs)) {
+        switch (cs.name) {
+          case 'DeviceGray':
+          case 'G':
+            return 'DeviceGrayCS';
+
+          case 'DeviceRGB':
+          case 'RGB':
+            return 'DeviceRgbCS';
+
+          case 'DeviceCMYK':
+          case 'CMYK':
+            return 'DeviceCmykCS';
+
+          case 'Pattern':
+            return ['PatternCS', null];
+
+          default:
+            if ((0, _primitives.isDict)(res)) {
+              var colorSpaces = res.get('ColorSpace');
+
+              if ((0, _primitives.isDict)(colorSpaces)) {
+                var resCS = colorSpaces.get(cs.name);
+
+                if (resCS) {
+                  if ((0, _primitives.isName)(resCS)) {
+                    return this.parseToIR(resCS, xref, res, pdfFunctionFactory);
+                  }
+
+                  cs = resCS;
+                  break;
+                }
+              }
+            }
+
+            throw new _util.FormatError("unrecognized colorspace ".concat(cs.name));
+        }
+      }
+
+      if (Array.isArray(cs)) {
+        var mode = xref.fetchIfRef(cs[0]).name;
+        var numComps, params, alt, whitePoint, blackPoint, gamma;
+
+        switch (mode) {
+          case 'DeviceGray':
+          case 'G':
+            return 'DeviceGrayCS';
+
+          case 'DeviceRGB':
+          case 'RGB':
+            return 'DeviceRgbCS';
+
+          case 'DeviceCMYK':
+          case 'CMYK':
+            return 'DeviceCmykCS';
+
+          case 'CalGray':
+            params = xref.fetchIfRef(cs[1]);
+            whitePoint = params.getArray('WhitePoint');
+            blackPoint = params.getArray('BlackPoint');
+            gamma = params.get('Gamma');
+            return ['CalGrayCS', whitePoint, blackPoint, gamma];
+
+          case 'CalRGB':
+            params = xref.fetchIfRef(cs[1]);
+            whitePoint = params.getArray('WhitePoint');
+            blackPoint = params.getArray('BlackPoint');
+            gamma = params.getArray('Gamma');
+            var matrix = params.getArray('Matrix');
+            return ['CalRGBCS', whitePoint, blackPoint, gamma, matrix];
+
+          case 'ICCBased':
+            var stream = xref.fetchIfRef(cs[1]);
+            var dict = stream.dict;
+            numComps = dict.get('N');
+            alt = dict.get('Alternate');
+
+            if (alt) {
+              var altIR = this.parseToIR(alt, xref, res, pdfFunctionFactory);
+              var altCS = this.fromIR(altIR, pdfFunctionFactory);
+
+              if (altCS.numComps === numComps) {
+                return altIR;
+              }
+
+              (0, _util.warn)('ICCBased color space: Ignoring incorrect /Alternate entry.');
+            }
+
+            if (numComps === 1) {
+              return 'DeviceGrayCS';
+            } else if (numComps === 3) {
+              return 'DeviceRgbCS';
+            } else if (numComps === 4) {
+              return 'DeviceCmykCS';
+            }
+
+            break;
+
+          case 'Pattern':
+            var basePatternCS = cs[1] || null;
+
+            if (basePatternCS) {
+              basePatternCS = this.parseToIR(basePatternCS, xref, res, pdfFunctionFactory);
+            }
+
+            return ['PatternCS', basePatternCS];
+
+          case 'Indexed':
+          case 'I':
+            var baseIndexedCS = this.parseToIR(cs[1], xref, res, pdfFunctionFactory);
+            var hiVal = xref.fetchIfRef(cs[2]) + 1;
+            var lookup = xref.fetchIfRef(cs[3]);
+
+            if ((0, _primitives.isStream)(lookup)) {
+              lookup = lookup.getBytes();
+            }
+
+            return ['IndexedCS', baseIndexedCS, hiVal, lookup];
+
+          case 'Separation':
+          case 'DeviceN':
+            var name = xref.fetchIfRef(cs[1]);
+            numComps = Array.isArray(name) ? name.length : 1;
+            alt = this.parseToIR(cs[2], xref, res, pdfFunctionFactory);
+            var tintFn = pdfFunctionFactory.create(xref.fetchIfRef(cs[3]));
+            return ['AlternateCS', numComps, alt, tintFn];
+
+          case 'Lab':
+            params = xref.fetchIfRef(cs[1]);
+            whitePoint = params.getArray('WhitePoint');
+            blackPoint = params.getArray('BlackPoint');
+            var range = params.getArray('Range');
+            return ['LabCS', whitePoint, blackPoint, range];
+
+          default:
+            throw new _util.FormatError("unimplemented color space object \"".concat(mode, "\""));
+        }
+      }
+
+      throw new _util.FormatError("unrecognized color space object: \"".concat(cs, "\""));
+    }
+  }, {
+    key: "isDefaultDecode",
+    value: function isDefaultDecode(decode, numComps) {
+      if (!Array.isArray(decode)) {
+        return true;
+      }
+
+      if (numComps * 2 !== decode.length) {
+        (0, _util.warn)('The decode map is not the correct length');
+        return true;
+      }
+
+      for (var i = 0, ii = decode.length; i < ii; i += 2) {
+        if (decode[i] !== 0 || decode[i + 1] !== 1) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+  }, {
+    key: "singletons",
+    get: function get() {
+      return (0, _util.shadow)(this, 'singletons', {
+        get gray() {
+          return (0, _util.shadow)(this, 'gray', new DeviceGrayCS());
+        },
+
+        get rgb() {
+          return (0, _util.shadow)(this, 'rgb', new DeviceRgbCS());
+        },
+
+        get cmyk() {
+          return (0, _util.shadow)(this, 'cmyk', new DeviceCmykCS());
+        }
+
+      });
+    }
+  }]);
+
+  return ColorSpace;
+}();
+
+exports.ColorSpace = ColorSpace;
+
+var AlternateCS =
+/*#__PURE__*/
+function (_ColorSpace) {
+  _inherits(AlternateCS, _ColorSpace);
+
+  function AlternateCS(numComps, base, tintFn) {
+    var _this;
+
+    _classCallCheck(this, AlternateCS);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(AlternateCS).call(this, 'Alternate', numComps));
+    _this.base = base;
+    _this.tintFn = tintFn;
+    _this.tmpBuf = new Float32Array(base.numComps);
+    return _this;
+  }
+
+  _createClass(AlternateCS, [{
+    key: "getRgbItem",
+    value: function getRgbItem(src, srcOffset, dest, destOffset) {
+      var tmpBuf = this.tmpBuf;
+      this.tintFn(src, srcOffset, tmpBuf, 0);
+      this.base.getRgbItem(tmpBuf, 0, dest, destOffset);
+    }
+  }, {
+    key: "getRgbBuffer",
+    value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+      var tintFn = this.tintFn;
+      var base = this.base;
+      var scale = 1 / ((1 << bits) - 1);
+      var baseNumComps = base.numComps;
+      var usesZeroToOneRange = base.usesZeroToOneRange;
+      var isPassthrough = (base.isPassthrough(8) || !usesZeroToOneRange) && alpha01 === 0;
+      var pos = isPassthrough ? destOffset : 0;
+      var baseBuf = isPassthrough ? dest : new Uint8ClampedArray(baseNumComps * count);
+      var numComps = this.numComps;
+      var scaled = new Float32Array(numComps);
+      var tinted = new Float32Array(baseNumComps);
+      var i, j;
+
+      for (i = 0; i < count; i++) {
+        for (j = 0; j < numComps; j++) {
+          scaled[j] = src[srcOffset++] * scale;
+        }
+
+        tintFn(scaled, 0, tinted, 0);
+
+        if (usesZeroToOneRange) {
+          for (j = 0; j < baseNumComps; j++) {
+            baseBuf[pos++] = tinted[j] * 255;
+          }
+        } else {
+          base.getRgbItem(tinted, 0, baseBuf, pos);
+          pos += baseNumComps;
+        }
+      }
+
+      if (!isPassthrough) {
+        base.getRgbBuffer(baseBuf, 0, count, dest, destOffset, 8, alpha01);
+      }
+    }
+  }, {
+    key: "getOutputLength",
+    value: function getOutputLength(inputLength, alpha01) {
+      return this.base.getOutputLength(inputLength * this.base.numComps / this.numComps, alpha01);
+    }
+  }]);
+
+  return AlternateCS;
+}(ColorSpace);
+
+var PatternCS =
+/*#__PURE__*/
+function (_ColorSpace2) {
+  _inherits(PatternCS, _ColorSpace2);
+
+  function PatternCS(baseCS) {
+    var _this2;
+
+    _classCallCheck(this, PatternCS);
+
+    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(PatternCS).call(this, 'Pattern', null));
+    _this2.base = baseCS;
+    return _this2;
+  }
+
+  _createClass(PatternCS, [{
+    key: "isDefaultDecode",
+    value: function isDefaultDecode(decodeMap, bpc) {
+      (0, _util.unreachable)('Should not call PatternCS.isDefaultDecode');
+    }
+  }]);
+
+  return PatternCS;
+}(ColorSpace);
+
+var IndexedCS =
+/*#__PURE__*/
+function (_ColorSpace3) {
+  _inherits(IndexedCS, _ColorSpace3);
+
+  function IndexedCS(base, highVal, lookup) {
+    var _this3;
+
+    _classCallCheck(this, IndexedCS);
+
+    _this3 = _possibleConstructorReturn(this, _getPrototypeOf(IndexedCS).call(this, 'Indexed', 1));
+    _this3.base = base;
+    _this3.highVal = highVal;
+    var baseNumComps = base.numComps;
+    var length = baseNumComps * highVal;
+
+    if ((0, _primitives.isStream)(lookup)) {
+      _this3.lookup = new Uint8Array(length);
+      var bytes = lookup.getBytes(length);
+
+      _this3.lookup.set(bytes);
+    } else if ((0, _util.isString)(lookup)) {
+      _this3.lookup = new Uint8Array(length);
+
+      for (var i = 0; i < length; ++i) {
+        _this3.lookup[i] = lookup.charCodeAt(i);
+      }
+    } else if (lookup instanceof Uint8Array) {
+      _this3.lookup = lookup;
+    } else {
+      throw new _util.FormatError("Unrecognized lookup table: ".concat(lookup));
+    }
+
+    return _this3;
+  }
+
+  _createClass(IndexedCS, [{
+    key: "getRgbItem",
+    value: function getRgbItem(src, srcOffset, dest, destOffset) {
+      var numComps = this.base.numComps;
+      var start = src[srcOffset] * numComps;
+      this.base.getRgbBuffer(this.lookup, start, 1, dest, destOffset, 8, 0);
+    }
+  }, {
+    key: "getRgbBuffer",
+    value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+      var base = this.base;
+      var numComps = base.numComps;
+      var outputDelta = base.getOutputLength(numComps, alpha01);
+      var lookup = this.lookup;
+
+      for (var i = 0; i < count; ++i) {
+        var lookupPos = src[srcOffset++] * numComps;
+        base.getRgbBuffer(lookup, lookupPos, 1, dest, destOffset, 8, alpha01);
+        destOffset += outputDelta;
+      }
+    }
+  }, {
+    key: "getOutputLength",
+    value: function getOutputLength(inputLength, alpha01) {
+      return this.base.getOutputLength(inputLength * this.base.numComps, alpha01);
+    }
+  }, {
+    key: "isDefaultDecode",
+    value: function isDefaultDecode(decodeMap, bpc) {
+      if (!Array.isArray(decodeMap)) {
+        return true;
+      }
+
+      if (decodeMap.length !== 2) {
+        (0, _util.warn)('Decode map length is not correct');
+        return true;
+      }
+
+      if (!Number.isInteger(bpc) || bpc < 1) {
+        (0, _util.warn)('Bits per component is not correct');
+        return true;
+      }
+
+      return decodeMap[0] === 0 && decodeMap[1] === (1 << bpc) - 1;
+    }
+  }]);
+
+  return IndexedCS;
+}(ColorSpace);
+
+var DeviceGrayCS =
+/*#__PURE__*/
+function (_ColorSpace4) {
+  _inherits(DeviceGrayCS, _ColorSpace4);
+
+  function DeviceGrayCS() {
+    _classCallCheck(this, DeviceGrayCS);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(DeviceGrayCS).call(this, 'DeviceGray', 1));
+  }
+
+  _createClass(DeviceGrayCS, [{
+    key: "getRgbItem",
+    value: function getRgbItem(src, srcOffset, dest, destOffset) {
+      var c = src[srcOffset] * 255;
+      dest[destOffset] = dest[destOffset + 1] = dest[destOffset + 2] = c;
+    }
+  }, {
+    key: "getRgbBuffer",
+    value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+      var scale = 255 / ((1 << bits) - 1);
+      var j = srcOffset,
+          q = destOffset;
+
+      for (var i = 0; i < count; ++i) {
+        var c = scale * src[j++];
+        dest[q++] = c;
+        dest[q++] = c;
+        dest[q++] = c;
+        q += alpha01;
+      }
+    }
+  }, {
+    key: "getOutputLength",
+    value: function getOutputLength(inputLength, alpha01) {
+      return inputLength * (3 + alpha01);
+    }
+  }]);
+
+  return DeviceGrayCS;
+}(ColorSpace);
+
+var DeviceRgbCS =
+/*#__PURE__*/
+function (_ColorSpace5) {
+  _inherits(DeviceRgbCS, _ColorSpace5);
+
+  function DeviceRgbCS() {
+    _classCallCheck(this, DeviceRgbCS);
+
+    return _possibleConstructorReturn(this, _getPrototypeOf(DeviceRgbCS).call(this, 'DeviceRGB', 3));
+  }
+
+  _createClass(DeviceRgbCS, [{
+    key: "getRgbItem",
+    value: function getRgbItem(src, srcOffset, dest, destOffset) {
+      dest[destOffset] = src[srcOffset] * 255;
+      dest[destOffset + 1] = src[srcOffset + 1] * 255;
+      dest[destOffset + 2] = src[srcOffset + 2] * 255;
+    }
+  }, {
+    key: "getRgbBuffer",
+    value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+      if (bits === 8 && alpha01 === 0) {
+        dest.set(src.subarray(srcOffset, srcOffset + count * 3), destOffset);
+        return;
+      }
+
+      var scale = 255 / ((1 << bits) - 1);
+      var j = srcOffset,
+          q = destOffset;
+
+      for (var i = 0; i < count; ++i) {
+        dest[q++] = scale * src[j++];
+        dest[q++] = scale * src[j++];
+        dest[q++] = scale * src[j++];
+        q += alpha01;
+      }
+    }
+  }, {
+    key: "getOutputLength",
+    value: function getOutputLength(inputLength, alpha01) {
+      return inputLength * (3 + alpha01) / 3 | 0;
+    }
+  }, {
+    key: "isPassthrough",
+    value: function isPassthrough(bits) {
+      return bits === 8;
+    }
+  }]);
+
+  return DeviceRgbCS;
+}(ColorSpace);
+
+var DeviceCmykCS = function DeviceCmykCSClosure() {
+  function convertToRgb(src, srcOffset, srcScale, dest, destOffset) {
+    var c = src[srcOffset] * srcScale;
+    var m = src[srcOffset + 1] * srcScale;
+    var y = src[srcOffset + 2] * srcScale;
+    var k = src[srcOffset + 3] * srcScale;
+    dest[destOffset] = 255 + c * (-4.387332384609988 * c + 54.48615194189176 * m + 18.82290502165302 * y + 212.25662451639585 * k + -285.2331026137004) + m * (1.7149763477362134 * m - 5.6096736904047315 * y + -17.873870861415444 * k - 5.497006427196366) + y * (-2.5217340131683033 * y - 21.248923337353073 * k + 17.5119270841813) + k * (-21.86122147463605 * k - 189.48180835922747);
+    dest[destOffset + 1] = 255 + c * (8.841041422036149 * c + 60.118027045597366 * m + 6.871425592049007 * y + 31.159100130055922 * k + -79.2970844816548) + m * (-15.310361306967817 * m + 17.575251261109482 * y + 131.35250912493976 * k - 190.9453302588951) + y * (4.444339102852739 * y + 9.8632861493405 * k - 24.86741582555878) + k * (-20.737325471181034 * k - 187.80453709719578);
+    dest[destOffset + 2] = 255 + c * (0.8842522430003296 * c + 8.078677503112928 * m + 30.89978309703729 * y - 0.23883238689178934 * k + -14.183576799673286) + m * (10.49593273432072 * m + 63.02378494754052 * y + 50.606957656360734 * k - 112.23884253719248) + y * (0.03296041114873217 * y + 115.60384449646641 * k + -193.58209356861505) + k * (-22.33816807309886 * k - 180.12613974708367);
+  }
+
+  var DeviceCmykCS =
+  /*#__PURE__*/
+  function (_ColorSpace6) {
+    _inherits(DeviceCmykCS, _ColorSpace6);
+
+    function DeviceCmykCS() {
+      _classCallCheck(this, DeviceCmykCS);
+
+      return _possibleConstructorReturn(this, _getPrototypeOf(DeviceCmykCS).call(this, 'DeviceCMYK', 4));
+    }
+
+    _createClass(DeviceCmykCS, [{
+      key: "getRgbItem",
+      value: function getRgbItem(src, srcOffset, dest, destOffset) {
+        convertToRgb(src, srcOffset, 1, dest, destOffset);
+      }
+    }, {
+      key: "getRgbBuffer",
+      value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+        var scale = 1 / ((1 << bits) - 1);
+
+        for (var i = 0; i < count; i++) {
+          convertToRgb(src, srcOffset, scale, dest, destOffset);
+          srcOffset += 4;
+          destOffset += 3 + alpha01;
+        }
+      }
+    }, {
+      key: "getOutputLength",
+      value: function getOutputLength(inputLength, alpha01) {
+        return inputLength / 4 * (3 + alpha01) | 0;
+      }
+    }]);
+
+    return DeviceCmykCS;
+  }(ColorSpace);
+
+  return DeviceCmykCS;
+}();
+
+var CalGrayCS = function CalGrayCSClosure() {
+  function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
+    var A = src[srcOffset] * scale;
+    var AG = Math.pow(A, cs.G);
+    var L = cs.YW * AG;
+    var val = Math.max(295.8 * Math.pow(L, 0.333333333333333333) - 40.8, 0);
+    dest[destOffset] = val;
+    dest[destOffset + 1] = val;
+    dest[destOffset + 2] = val;
+  }
+
+  var CalGrayCS =
+  /*#__PURE__*/
+  function (_ColorSpace7) {
+    _inherits(CalGrayCS, _ColorSpace7);
+
+    function CalGrayCS(whitePoint, blackPoint, gamma) {
+      var _this4;
+
+      _classCallCheck(this, CalGrayCS);
+
+      _this4 = _possibleConstructorReturn(this, _getPrototypeOf(CalGrayCS).call(this, 'CalGray', 1));
+
+      if (!whitePoint) {
+        throw new _util.FormatError('WhitePoint missing - required for color space CalGray');
+      }
+
+      blackPoint = blackPoint || [0, 0, 0];
+      gamma = gamma || 1;
+      _this4.XW = whitePoint[0];
+      _this4.YW = whitePoint[1];
+      _this4.ZW = whitePoint[2];
+      _this4.XB = blackPoint[0];
+      _this4.YB = blackPoint[1];
+      _this4.ZB = blackPoint[2];
+      _this4.G = gamma;
+
+      if (_this4.XW < 0 || _this4.ZW < 0 || _this4.YW !== 1) {
+        throw new _util.FormatError("Invalid WhitePoint components for ".concat(_this4.name) + ', no fallback available');
+      }
+
+      if (_this4.XB < 0 || _this4.YB < 0 || _this4.ZB < 0) {
+        (0, _util.info)("Invalid BlackPoint for ".concat(_this4.name, ", falling back to default."));
+        _this4.XB = _this4.YB = _this4.ZB = 0;
+      }
+
+      if (_this4.XB !== 0 || _this4.YB !== 0 || _this4.ZB !== 0) {
+        (0, _util.warn)("".concat(_this4.name, ", BlackPoint: XB: ").concat(_this4.XB, ", YB: ").concat(_this4.YB, ", ") + "ZB: ".concat(_this4.ZB, ", only default values are supported."));
+      }
+
+      if (_this4.G < 1) {
+        (0, _util.info)("Invalid Gamma: ".concat(_this4.G, " for ").concat(_this4.name, ", ") + 'falling back to default.');
+        _this4.G = 1;
+      }
+
+      return _this4;
+    }
+
+    _createClass(CalGrayCS, [{
+      key: "getRgbItem",
+      value: function getRgbItem(src, srcOffset, dest, destOffset) {
+        convertToRgb(this, src, srcOffset, dest, destOffset, 1);
+      }
+    }, {
+      key: "getRgbBuffer",
+      value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+        var scale = 1 / ((1 << bits) - 1);
+
+        for (var i = 0; i < count; ++i) {
+          convertToRgb(this, src, srcOffset, dest, destOffset, scale);
+          srcOffset += 1;
+          destOffset += 3 + alpha01;
+        }
+      }
+    }, {
+      key: "getOutputLength",
+      value: function getOutputLength(inputLength, alpha01) {
+        return inputLength * (3 + alpha01);
+      }
+    }]);
+
+    return CalGrayCS;
+  }(ColorSpace);
+
+  return CalGrayCS;
+}();
+
+var CalRGBCS = function CalRGBCSClosure() {
+  var BRADFORD_SCALE_MATRIX = new Float32Array([0.8951, 0.2664, -0.1614, -0.7502, 1.7135, 0.0367, 0.0389, -0.0685, 1.0296]);
+  var BRADFORD_SCALE_INVERSE_MATRIX = new Float32Array([0.9869929, -0.1470543, 0.1599627, 0.4323053, 0.5183603, 0.0492912, -0.0085287, 0.0400428, 0.9684867]);
+  var SRGB_D65_XYZ_TO_RGB_MATRIX = new Float32Array([3.2404542, -1.5371385, -0.4985314, -0.9692660, 1.8760108, 0.0415560, 0.0556434, -0.2040259, 1.0572252]);
+  var FLAT_WHITEPOINT_MATRIX = new Float32Array([1, 1, 1]);
+  var tempNormalizeMatrix = new Float32Array(3);
+  var tempConvertMatrix1 = new Float32Array(3);
+  var tempConvertMatrix2 = new Float32Array(3);
+  var DECODE_L_CONSTANT = Math.pow((8 + 16) / 116, 3) / 8.0;
+
+  function matrixProduct(a, b, result) {
+    result[0] = a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
+    result[1] = a[3] * b[0] + a[4] * b[1] + a[5] * b[2];
+    result[2] = a[6] * b[0] + a[7] * b[1] + a[8] * b[2];
+  }
+
+  function convertToFlat(sourceWhitePoint, LMS, result) {
+    result[0] = LMS[0] * 1 / sourceWhitePoint[0];
+    result[1] = LMS[1] * 1 / sourceWhitePoint[1];
+    result[2] = LMS[2] * 1 / sourceWhitePoint[2];
+  }
+
+  function convertToD65(sourceWhitePoint, LMS, result) {
+    var D65X = 0.95047;
+    var D65Y = 1;
+    var D65Z = 1.08883;
+    result[0] = LMS[0] * D65X / sourceWhitePoint[0];
+    result[1] = LMS[1] * D65Y / sourceWhitePoint[1];
+    result[2] = LMS[2] * D65Z / sourceWhitePoint[2];
+  }
+
+  function sRGBTransferFunction(color) {
+    if (color <= 0.0031308) {
+      return adjustToRange(0, 1, 12.92 * color);
+    }
+
+    return adjustToRange(0, 1, (1 + 0.055) * Math.pow(color, 1 / 2.4) - 0.055);
+  }
+
+  function adjustToRange(min, max, value) {
+    return Math.max(min, Math.min(max, value));
+  }
+
+  function decodeL(L) {
+    if (L < 0) {
+      return -decodeL(-L);
+    }
+
+    if (L > 8.0) {
+      return Math.pow((L + 16) / 116, 3);
+    }
+
+    return L * DECODE_L_CONSTANT;
+  }
+
+  function compensateBlackPoint(sourceBlackPoint, XYZ_Flat, result) {
+    if (sourceBlackPoint[0] === 0 && sourceBlackPoint[1] === 0 && sourceBlackPoint[2] === 0) {
+      result[0] = XYZ_Flat[0];
+      result[1] = XYZ_Flat[1];
+      result[2] = XYZ_Flat[2];
+      return;
+    }
+
+    var zeroDecodeL = decodeL(0);
+    var X_DST = zeroDecodeL;
+    var X_SRC = decodeL(sourceBlackPoint[0]);
+    var Y_DST = zeroDecodeL;
+    var Y_SRC = decodeL(sourceBlackPoint[1]);
+    var Z_DST = zeroDecodeL;
+    var Z_SRC = decodeL(sourceBlackPoint[2]);
+    var X_Scale = (1 - X_DST) / (1 - X_SRC);
+    var X_Offset = 1 - X_Scale;
+    var Y_Scale = (1 - Y_DST) / (1 - Y_SRC);
+    var Y_Offset = 1 - Y_Scale;
+    var Z_Scale = (1 - Z_DST) / (1 - Z_SRC);
+    var Z_Offset = 1 - Z_Scale;
+    result[0] = XYZ_Flat[0] * X_Scale + X_Offset;
+    result[1] = XYZ_Flat[1] * Y_Scale + Y_Offset;
+    result[2] = XYZ_Flat[2] * Z_Scale + Z_Offset;
+  }
+
+  function normalizeWhitePointToFlat(sourceWhitePoint, XYZ_In, result) {
+    if (sourceWhitePoint[0] === 1 && sourceWhitePoint[2] === 1) {
+      result[0] = XYZ_In[0];
+      result[1] = XYZ_In[1];
+      result[2] = XYZ_In[2];
+      return;
+    }
+
+    var LMS = result;
+    matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
+    var LMS_Flat = tempNormalizeMatrix;
+    convertToFlat(sourceWhitePoint, LMS, LMS_Flat);
+    matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_Flat, result);
+  }
+
+  function normalizeWhitePointToD65(sourceWhitePoint, XYZ_In, result) {
+    var LMS = result;
+    matrixProduct(BRADFORD_SCALE_MATRIX, XYZ_In, LMS);
+    var LMS_D65 = tempNormalizeMatrix;
+    convertToD65(sourceWhitePoint, LMS, LMS_D65);
+    matrixProduct(BRADFORD_SCALE_INVERSE_MATRIX, LMS_D65, result);
+  }
+
+  function convertToRgb(cs, src, srcOffset, dest, destOffset, scale) {
+    var A = adjustToRange(0, 1, src[srcOffset] * scale);
+    var B = adjustToRange(0, 1, src[srcOffset + 1] * scale);
+    var C = adjustToRange(0, 1, src[srcOffset + 2] * scale);
+    var AGR = Math.pow(A, cs.GR);
+    var BGG = Math.pow(B, cs.GG);
+    var CGB = Math.pow(C, cs.GB);
+    var X = cs.MXA * AGR + cs.MXB * BGG + cs.MXC * CGB;
+    var Y = cs.MYA * AGR + cs.MYB * BGG + cs.MYC * CGB;
+    var Z = cs.MZA * AGR + cs.MZB * BGG + cs.MZC * CGB;
+    var XYZ = tempConvertMatrix1;
+    XYZ[0] = X;
+    XYZ[1] = Y;
+    XYZ[2] = Z;
+    var XYZ_Flat = tempConvertMatrix2;
+    normalizeWhitePointToFlat(cs.whitePoint, XYZ, XYZ_Flat);
+    var XYZ_Black = tempConvertMatrix1;
+    compensateBlackPoint(cs.blackPoint, XYZ_Flat, XYZ_Black);
+    var XYZ_D65 = tempConvertMatrix2;
+    normalizeWhitePointToD65(FLAT_WHITEPOINT_MATRIX, XYZ_Black, XYZ_D65);
+    var SRGB = tempConvertMatrix1;
+    matrixProduct(SRGB_D65_XYZ_TO_RGB_MATRIX, XYZ_D65, SRGB);
+    dest[destOffset] = sRGBTransferFunction(SRGB[0]) * 255;
+    dest[destOffset + 1] = sRGBTransferFunction(SRGB[1]) * 255;
+    dest[destOffset + 2] = sRGBTransferFunction(SRGB[2]) * 255;
+  }
+
+  var CalRGBCS =
+  /*#__PURE__*/
+  function (_ColorSpace8) {
+    _inherits(CalRGBCS, _ColorSpace8);
+
+    function CalRGBCS(whitePoint, blackPoint, gamma, matrix) {
+      var _this5;
+
+      _classCallCheck(this, CalRGBCS);
+
+      _this5 = _possibleConstructorReturn(this, _getPrototypeOf(CalRGBCS).call(this, 'CalRGB', 3));
+
+      if (!whitePoint) {
+        throw new _util.FormatError('WhitePoint missing - required for color space CalRGB');
+      }
+
+      blackPoint = blackPoint || new Float32Array(3);
+      gamma = gamma || new Float32Array([1, 1, 1]);
+      matrix = matrix || new Float32Array([1, 0, 0, 0, 1, 0, 0, 0, 1]);
+      var XW = whitePoint[0];
+      var YW = whitePoint[1];
+      var ZW = whitePoint[2];
+      _this5.whitePoint = whitePoint;
+      var XB = blackPoint[0];
+      var YB = blackPoint[1];
+      var ZB = blackPoint[2];
+      _this5.blackPoint = blackPoint;
+      _this5.GR = gamma[0];
+      _this5.GG = gamma[1];
+      _this5.GB = gamma[2];
+      _this5.MXA = matrix[0];
+      _this5.MYA = matrix[1];
+      _this5.MZA = matrix[2];
+      _this5.MXB = matrix[3];
+      _this5.MYB = matrix[4];
+      _this5.MZB = matrix[5];
+      _this5.MXC = matrix[6];
+      _this5.MYC = matrix[7];
+      _this5.MZC = matrix[8];
+
+      if (XW < 0 || ZW < 0 || YW !== 1) {
+        throw new _util.FormatError("Invalid WhitePoint components for ".concat(_this5.name) + ', no fallback available');
+      }
+
+      if (XB < 0 || YB < 0 || ZB < 0) {
+        (0, _util.info)("Invalid BlackPoint for ".concat(_this5.name, " [").concat(XB, ", ").concat(YB, ", ").concat(ZB, "], ") + 'falling back to default.');
+        _this5.blackPoint = new Float32Array(3);
+      }
+
+      if (_this5.GR < 0 || _this5.GG < 0 || _this5.GB < 0) {
+        (0, _util.info)("Invalid Gamma [".concat(_this5.GR, ", ").concat(_this5.GG, ", ").concat(_this5.GB, "] for ") + "".concat(_this5.name, ", falling back to default."));
+        _this5.GR = _this5.GG = _this5.GB = 1;
+      }
+
+      return _this5;
+    }
+
+    _createClass(CalRGBCS, [{
+      key: "getRgbItem",
+      value: function getRgbItem(src, srcOffset, dest, destOffset) {
+        convertToRgb(this, src, srcOffset, dest, destOffset, 1);
+      }
+    }, {
+      key: "getRgbBuffer",
+      value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+        var scale = 1 / ((1 << bits) - 1);
+
+        for (var i = 0; i < count; ++i) {
+          convertToRgb(this, src, srcOffset, dest, destOffset, scale);
+          srcOffset += 3;
+          destOffset += 3 + alpha01;
+        }
+      }
+    }, {
+      key: "getOutputLength",
+      value: function getOutputLength(inputLength, alpha01) {
+        return inputLength * (3 + alpha01) / 3 | 0;
+      }
+    }]);
+
+    return CalRGBCS;
+  }(ColorSpace);
+
+  return CalRGBCS;
+}();
+
+var LabCS = function LabCSClosure() {
+  function fn_g(x) {
+    var result;
+
+    if (x >= 6 / 29) {
+      result = x * x * x;
+    } else {
+      result = 108 / 841 * (x - 4 / 29);
+    }
+
+    return result;
+  }
+
+  function decode(value, high1, low2, high2) {
+    return low2 + value * (high2 - low2) / high1;
+  }
+
+  function convertToRgb(cs, src, srcOffset, maxVal, dest, destOffset) {
+    var Ls = src[srcOffset];
+    var as = src[srcOffset + 1];
+    var bs = src[srcOffset + 2];
+
+    if (maxVal !== false) {
+      Ls = decode(Ls, maxVal, 0, 100);
+      as = decode(as, maxVal, cs.amin, cs.amax);
+      bs = decode(bs, maxVal, cs.bmin, cs.bmax);
+    }
+
+    as = as > cs.amax ? cs.amax : as < cs.amin ? cs.amin : as;
+    bs = bs > cs.bmax ? cs.bmax : bs < cs.bmin ? cs.bmin : bs;
+    var M = (Ls + 16) / 116;
+    var L = M + as / 500;
+    var N = M - bs / 200;
+    var X = cs.XW * fn_g(L);
+    var Y = cs.YW * fn_g(M);
+    var Z = cs.ZW * fn_g(N);
+    var r, g, b;
+
+    if (cs.ZW < 1) {
+      r = X * 3.1339 + Y * -1.6170 + Z * -0.4906;
+      g = X * -0.9785 + Y * 1.9160 + Z * 0.0333;
+      b = X * 0.0720 + Y * -0.2290 + Z * 1.4057;
+    } else {
+      r = X * 3.2406 + Y * -1.5372 + Z * -0.4986;
+      g = X * -0.9689 + Y * 1.8758 + Z * 0.0415;
+      b = X * 0.0557 + Y * -0.2040 + Z * 1.0570;
+    }
+
+    dest[destOffset] = Math.sqrt(r) * 255;
+    dest[destOffset + 1] = Math.sqrt(g) * 255;
+    dest[destOffset + 2] = Math.sqrt(b) * 255;
+  }
+
+  var LabCS =
+  /*#__PURE__*/
+  function (_ColorSpace9) {
+    _inherits(LabCS, _ColorSpace9);
+
+    function LabCS(whitePoint, blackPoint, range) {
+      var _this6;
+
+      _classCallCheck(this, LabCS);
+
+      _this6 = _possibleConstructorReturn(this, _getPrototypeOf(LabCS).call(this, 'Lab', 3));
+
+      if (!whitePoint) {
+        throw new _util.FormatError('WhitePoint missing - required for color space Lab');
+      }
+
+      blackPoint = blackPoint || [0, 0, 0];
+      range = range || [-100, 100, -100, 100];
+      _this6.XW = whitePoint[0];
+      _this6.YW = whitePoint[1];
+      _this6.ZW = whitePoint[2];
+      _this6.amin = range[0];
+      _this6.amax = range[1];
+      _this6.bmin = range[2];
+      _this6.bmax = range[3];
+      _this6.XB = blackPoint[0];
+      _this6.YB = blackPoint[1];
+      _this6.ZB = blackPoint[2];
+
+      if (_this6.XW < 0 || _this6.ZW < 0 || _this6.YW !== 1) {
+        throw new _util.FormatError('Invalid WhitePoint components, no fallback available');
+      }
+
+      if (_this6.XB < 0 || _this6.YB < 0 || _this6.ZB < 0) {
+        (0, _util.info)('Invalid BlackPoint, falling back to default');
+        _this6.XB = _this6.YB = _this6.ZB = 0;
+      }
+
+      if (_this6.amin > _this6.amax || _this6.bmin > _this6.bmax) {
+        (0, _util.info)('Invalid Range, falling back to defaults');
+        _this6.amin = -100;
+        _this6.amax = 100;
+        _this6.bmin = -100;
+        _this6.bmax = 100;
+      }
+
+      return _this6;
+    }
+
+    _createClass(LabCS, [{
+      key: "getRgbItem",
+      value: function getRgbItem(src, srcOffset, dest, destOffset) {
+        convertToRgb(this, src, srcOffset, false, dest, destOffset);
+      }
+    }, {
+      key: "getRgbBuffer",
+      value: function getRgbBuffer(src, srcOffset, count, dest, destOffset, bits, alpha01) {
+        var maxVal = (1 << bits) - 1;
+
+        for (var i = 0; i < count; i++) {
+          convertToRgb(this, src, srcOffset, maxVal, dest, destOffset);
+          srcOffset += 3;
+          destOffset += 3 + alpha01;
+        }
+      }
+    }, {
+      key: "getOutputLength",
+      value: function getOutputLength(inputLength, alpha01) {
+        return inputLength * (3 + alpha01) / 3 | 0;
+      }
+    }, {
+      key: "isDefaultDecode",
+      value: function isDefaultDecode(decodeMap, bpc) {
+        return true;
+      }
+    }, {
+      key: "usesZeroToOneRange",
+      get: function get() {
+        return (0, _util.shadow)(this, 'usesZeroToOneRange', false);
+      }
+    }]);
+
+    return LabCS;
+  }(ColorSpace);
+
+  return LabCS;
+}();
+
+/***/ }),
+/* 170 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.MarkupAnnotation = exports.AnnotationFactory = exports.AnnotationBorderStyle = exports.Annotation = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _obj = __w_pdfjs_require__(156);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _colorspace = __w_pdfjs_require__(169);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _operator_list = __w_pdfjs_require__(171);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _get(target, property, receiver) { if (typeof Reflect !== "undefined" && Reflect.get) { _get = Reflect.get; } else { _get = function _get(target, property, receiver) { var base = _superPropBase(target, property); if (!base) return; var desc = Object.getOwnPropertyDescriptor(base, property); if (desc.get) { return desc.get.call(receiver); } return desc.value; }; } return _get(target, property, receiver || target); }
+
+function _superPropBase(object, property) { while (!Object.prototype.hasOwnProperty.call(object, property)) { object = _getPrototypeOf(object); if (object === null) break; } return object; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var AnnotationFactory =
+/*#__PURE__*/
+function () {
+  function AnnotationFactory() {
+    _classCallCheck(this, AnnotationFactory);
+  }
+
+  _createClass(AnnotationFactory, null, [{
+    key: "create",
+    value: function create(xref, ref, pdfManager, idFactory) {
+      return pdfManager.ensure(this, '_create', [xref, ref, pdfManager, idFactory]);
+    }
+  }, {
+    key: "_create",
+    value: function _create(xref, ref, pdfManager, idFactory) {
+      var dict = xref.fetchIfRef(ref);
+
+      if (!(0, _primitives.isDict)(dict)) {
+        return undefined;
+      }
+
+      var id = (0, _primitives.isRef)(ref) ? ref.toString() : "annot_".concat(idFactory.createObjId());
+      var subtype = dict.get('Subtype');
+      subtype = (0, _primitives.isName)(subtype) ? subtype.name : null;
+      var parameters = {
+        xref: xref,
+        dict: dict,
+        subtype: subtype,
+        id: id,
+        pdfManager: pdfManager
+      };
+
+      switch (subtype) {
+        case 'Link':
+          return new LinkAnnotation(parameters);
+
+        case 'Text':
+          return new TextAnnotation(parameters);
+
+        case 'Widget':
+          var fieldType = (0, _core_utils.getInheritableProperty)({
+            dict: dict,
+            key: 'FT'
+          });
+          fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
+
+          switch (fieldType) {
+            case 'Tx':
+              return new TextWidgetAnnotation(parameters);
+
+            case 'Btn':
+              return new ButtonWidgetAnnotation(parameters);
+
+            case 'Ch':
+              return new ChoiceWidgetAnnotation(parameters);
+          }
+
+          (0, _util.warn)('Unimplemented widget field type "' + fieldType + '", ' + 'falling back to base field type.');
+          return new WidgetAnnotation(parameters);
+
+        case 'Popup':
+          return new PopupAnnotation(parameters);
+
+        case 'FreeText':
+          return new FreeTextAnnotation(parameters);
+
+        case 'Line':
+          return new LineAnnotation(parameters);
+
+        case 'Square':
+          return new SquareAnnotation(parameters);
+
+        case 'Circle':
+          return new CircleAnnotation(parameters);
+
+        case 'PolyLine':
+          return new PolylineAnnotation(parameters);
+
+        case 'Polygon':
+          return new PolygonAnnotation(parameters);
+
+        case 'Caret':
+          return new CaretAnnotation(parameters);
+
+        case 'Ink':
+          return new InkAnnotation(parameters);
+
+        case 'Highlight':
+          return new HighlightAnnotation(parameters);
+
+        case 'Underline':
+          return new UnderlineAnnotation(parameters);
+
+        case 'Squiggly':
+          return new SquigglyAnnotation(parameters);
+
+        case 'StrikeOut':
+          return new StrikeOutAnnotation(parameters);
+
+        case 'Stamp':
+          return new StampAnnotation(parameters);
+
+        case 'FileAttachment':
+          return new FileAttachmentAnnotation(parameters);
+
+        default:
+          if (!subtype) {
+            (0, _util.warn)('Annotation is missing the required /Subtype.');
+          } else {
+            (0, _util.warn)('Unimplemented annotation type "' + subtype + '", ' + 'falling back to base annotation.');
+          }
+
+          return new Annotation(parameters);
+      }
+    }
+  }]);
+
+  return AnnotationFactory;
+}();
+
+exports.AnnotationFactory = AnnotationFactory;
+
+function getTransformMatrix(rect, bbox, matrix) {
+  var bounds = _util.Util.getAxialAlignedBoundingBox(bbox, matrix);
+
+  var minX = bounds[0];
+  var minY = bounds[1];
+  var maxX = bounds[2];
+  var maxY = bounds[3];
+
+  if (minX === maxX || minY === maxY) {
+    return [1, 0, 0, 1, rect[0], rect[1]];
+  }
+
+  var xRatio = (rect[2] - rect[0]) / (maxX - minX);
+  var yRatio = (rect[3] - rect[1]) / (maxY - minY);
+  return [xRatio, 0, 0, yRatio, rect[0] - minX * xRatio, rect[1] - minY * yRatio];
+}
+
+var Annotation =
+/*#__PURE__*/
+function () {
+  function Annotation(params) {
+    _classCallCheck(this, Annotation);
+
+    var dict = params.dict;
+    this.setContents(dict.get('Contents'));
+    this.setModificationDate(dict.get('M'));
+    this.setFlags(dict.get('F'));
+    this.setRectangle(dict.getArray('Rect'));
+    this.setColor(dict.getArray('C'));
+    this.setBorderStyle(dict);
+    this.setAppearance(dict);
+    this.data = {
+      annotationFlags: this.flags,
+      borderStyle: this.borderStyle,
+      color: this.color,
+      contents: this.contents,
+      hasAppearance: !!this.appearance,
+      id: params.id,
+      modificationDate: this.modificationDate,
+      rect: this.rectangle,
+      subtype: params.subtype
+    };
+  }
+
+  _createClass(Annotation, [{
+    key: "_hasFlag",
+    value: function _hasFlag(flags, flag) {
+      return !!(flags & flag);
+    }
+  }, {
+    key: "_isViewable",
+    value: function _isViewable(flags) {
+      return !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN) && !this._hasFlag(flags, _util.AnnotationFlag.NOVIEW);
+    }
+  }, {
+    key: "_isPrintable",
+    value: function _isPrintable(flags) {
+      return this._hasFlag(flags, _util.AnnotationFlag.PRINT) && !this._hasFlag(flags, _util.AnnotationFlag.INVISIBLE) && !this._hasFlag(flags, _util.AnnotationFlag.HIDDEN);
+    }
+  }, {
+    key: "setContents",
+    value: function setContents(contents) {
+      this.contents = (0, _util.stringToPDFString)(contents || '');
+    }
+  }, {
+    key: "setModificationDate",
+    value: function setModificationDate(modificationDate) {
+      this.modificationDate = (0, _util.isString)(modificationDate) ? modificationDate : null;
+    }
+  }, {
+    key: "setFlags",
+    value: function setFlags(flags) {
+      this.flags = Number.isInteger(flags) && flags > 0 ? flags : 0;
+    }
+  }, {
+    key: "hasFlag",
+    value: function hasFlag(flag) {
+      return this._hasFlag(this.flags, flag);
+    }
+  }, {
+    key: "setRectangle",
+    value: function setRectangle(rectangle) {
+      if (Array.isArray(rectangle) && rectangle.length === 4) {
+        this.rectangle = _util.Util.normalizeRect(rectangle);
+      } else {
+        this.rectangle = [0, 0, 0, 0];
+      }
+    }
+  }, {
+    key: "setColor",
+    value: function setColor(color) {
+      var rgbColor = new Uint8ClampedArray(3);
+
+      if (!Array.isArray(color)) {
+        this.color = rgbColor;
+        return;
+      }
+
+      switch (color.length) {
+        case 0:
+          this.color = null;
+          break;
+
+        case 1:
+          _colorspace.ColorSpace.singletons.gray.getRgbItem(color, 0, rgbColor, 0);
+
+          this.color = rgbColor;
+          break;
+
+        case 3:
+          _colorspace.ColorSpace.singletons.rgb.getRgbItem(color, 0, rgbColor, 0);
+
+          this.color = rgbColor;
+          break;
+
+        case 4:
+          _colorspace.ColorSpace.singletons.cmyk.getRgbItem(color, 0, rgbColor, 0);
+
+          this.color = rgbColor;
+          break;
+
+        default:
+          this.color = rgbColor;
+          break;
+      }
+    }
+  }, {
+    key: "setBorderStyle",
+    value: function setBorderStyle(borderStyle) {
+      this.borderStyle = new AnnotationBorderStyle();
+
+      if (!(0, _primitives.isDict)(borderStyle)) {
+        return;
+      }
+
+      if (borderStyle.has('BS')) {
+        var dict = borderStyle.get('BS');
+        var dictType = dict.get('Type');
+
+        if (!dictType || (0, _primitives.isName)(dictType, 'Border')) {
+          this.borderStyle.setWidth(dict.get('W'), this.rectangle);
+          this.borderStyle.setStyle(dict.get('S'));
+          this.borderStyle.setDashArray(dict.getArray('D'));
+        }
+      } else if (borderStyle.has('Border')) {
+        var array = borderStyle.getArray('Border');
+
+        if (Array.isArray(array) && array.length >= 3) {
+          this.borderStyle.setHorizontalCornerRadius(array[0]);
+          this.borderStyle.setVerticalCornerRadius(array[1]);
+          this.borderStyle.setWidth(array[2], this.rectangle);
+
+          if (array.length === 4) {
+            this.borderStyle.setDashArray(array[3]);
+          }
+        }
+      } else {
+        this.borderStyle.setWidth(0);
+      }
+    }
+  }, {
+    key: "setAppearance",
+    value: function setAppearance(dict) {
+      this.appearance = null;
+      var appearanceStates = dict.get('AP');
+
+      if (!(0, _primitives.isDict)(appearanceStates)) {
+        return;
+      }
+
+      var normalAppearanceState = appearanceStates.get('N');
+
+      if ((0, _primitives.isStream)(normalAppearanceState)) {
+        this.appearance = normalAppearanceState;
+        return;
+      }
+
+      if (!(0, _primitives.isDict)(normalAppearanceState)) {
+        return;
+      }
+
+      var as = dict.get('AS');
+
+      if (!(0, _primitives.isName)(as) || !normalAppearanceState.has(as.name)) {
+        return;
+      }
+
+      this.appearance = normalAppearanceState.get(as.name);
+    }
+  }, {
+    key: "loadResources",
+    value: function loadResources(keys) {
+      return this.appearance.dict.getAsync('Resources').then(function (resources) {
+        if (!resources) {
+          return undefined;
+        }
+
+        var objectLoader = new _obj.ObjectLoader(resources, keys, resources.xref);
+        return objectLoader.load().then(function () {
+          return resources;
+        });
+      });
+    }
+  }, {
+    key: "getOperatorList",
+    value: function getOperatorList(evaluator, task, renderForms) {
+      var _this = this;
+
+      if (!this.appearance) {
+        return Promise.resolve(new _operator_list.OperatorList());
+      }
+
+      var data = this.data;
+      var appearanceDict = this.appearance.dict;
+      var resourcesPromise = this.loadResources(['ExtGState', 'ColorSpace', 'Pattern', 'Shading', 'XObject', 'Font']);
+      var bbox = appearanceDict.getArray('BBox') || [0, 0, 1, 1];
+      var matrix = appearanceDict.getArray('Matrix') || [1, 0, 0, 1, 0, 0];
+      var transform = getTransformMatrix(data.rect, bbox, matrix);
+      return resourcesPromise.then(function (resources) {
+        var opList = new _operator_list.OperatorList();
+        opList.addOp(_util.OPS.beginAnnotation, [data.rect, transform, matrix]);
+        return evaluator.getOperatorList({
+          stream: _this.appearance,
+          task: task,
+          resources: resources,
+          operatorList: opList
+        }).then(function () {
+          opList.addOp(_util.OPS.endAnnotation, []);
+
+          _this.appearance.reset();
+
+          return opList;
+        });
+      });
+    }
+  }, {
+    key: "viewable",
+    get: function get() {
+      if (this.flags === 0) {
+        return true;
+      }
+
+      return this._isViewable(this.flags);
+    }
+  }, {
+    key: "printable",
+    get: function get() {
+      if (this.flags === 0) {
+        return false;
+      }
+
+      return this._isPrintable(this.flags);
+    }
+  }]);
+
+  return Annotation;
+}();
+
+exports.Annotation = Annotation;
+
+var AnnotationBorderStyle =
+/*#__PURE__*/
+function () {
+  function AnnotationBorderStyle() {
+    _classCallCheck(this, AnnotationBorderStyle);
+
+    this.width = 1;
+    this.style = _util.AnnotationBorderStyleType.SOLID;
+    this.dashArray = [3];
+    this.horizontalCornerRadius = 0;
+    this.verticalCornerRadius = 0;
+  }
+
+  _createClass(AnnotationBorderStyle, [{
+    key: "setWidth",
+    value: function setWidth(width) {
+      var rect = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [0, 0, 0, 0];
+
+      if ((0, _primitives.isName)(width)) {
+        this.width = 0;
+        return;
+      }
+
+      if (Number.isInteger(width)) {
+        if (width > 0) {
+          var maxWidth = (rect[2] - rect[0]) / 2;
+          var maxHeight = (rect[3] - rect[1]) / 2;
+
+          if (maxWidth > 0 && maxHeight > 0 && (width > maxWidth || width > maxHeight)) {
+            (0, _util.warn)("AnnotationBorderStyle.setWidth - ignoring width: ".concat(width));
+            width = 1;
+          }
+        }
+
+        this.width = width;
+      }
+    }
+  }, {
+    key: "setStyle",
+    value: function setStyle(style) {
+      if (!(0, _primitives.isName)(style)) {
+        return;
+      }
+
+      switch (style.name) {
+        case 'S':
+          this.style = _util.AnnotationBorderStyleType.SOLID;
+          break;
+
+        case 'D':
+          this.style = _util.AnnotationBorderStyleType.DASHED;
+          break;
+
+        case 'B':
+          this.style = _util.AnnotationBorderStyleType.BEVELED;
+          break;
+
+        case 'I':
+          this.style = _util.AnnotationBorderStyleType.INSET;
+          break;
+
+        case 'U':
+          this.style = _util.AnnotationBorderStyleType.UNDERLINE;
+          break;
+
+        default:
+          break;
+      }
+    }
+  }, {
+    key: "setDashArray",
+    value: function setDashArray(dashArray) {
+      if (Array.isArray(dashArray) && dashArray.length > 0) {
+        var isValid = true;
+        var allZeros = true;
+
+        for (var i = 0, len = dashArray.length; i < len; i++) {
+          var element = dashArray[i];
+          var validNumber = +element >= 0;
+
+          if (!validNumber) {
+            isValid = false;
+            break;
+          } else if (element > 0) {
+            allZeros = false;
+          }
+        }
+
+        if (isValid && !allZeros) {
+          this.dashArray = dashArray;
+        } else {
+          this.width = 0;
+        }
+      } else if (dashArray) {
+        this.width = 0;
+      }
+    }
+  }, {
+    key: "setHorizontalCornerRadius",
+    value: function setHorizontalCornerRadius(radius) {
+      if (Number.isInteger(radius)) {
+        this.horizontalCornerRadius = radius;
+      }
+    }
+  }, {
+    key: "setVerticalCornerRadius",
+    value: function setVerticalCornerRadius(radius) {
+      if (Number.isInteger(radius)) {
+        this.verticalCornerRadius = radius;
+      }
+    }
+  }]);
+
+  return AnnotationBorderStyle;
+}();
+
+exports.AnnotationBorderStyle = AnnotationBorderStyle;
+
+var MarkupAnnotation =
+/*#__PURE__*/
+function (_Annotation) {
+  _inherits(MarkupAnnotation, _Annotation);
+
+  function MarkupAnnotation(parameters) {
+    var _this2;
+
+    _classCallCheck(this, MarkupAnnotation);
+
+    _this2 = _possibleConstructorReturn(this, _getPrototypeOf(MarkupAnnotation).call(this, parameters));
+    var dict = parameters.dict;
+
+    if (!dict.has('C')) {
+      _this2.data.color = null;
+    }
+
+    _this2.setCreationDate(dict.get('CreationDate'));
+
+    _this2.data.creationDate = _this2.creationDate;
+    _this2.data.hasPopup = dict.has('Popup');
+    _this2.data.title = (0, _util.stringToPDFString)(dict.get('T') || '');
+    return _this2;
+  }
+
+  _createClass(MarkupAnnotation, [{
+    key: "setCreationDate",
+    value: function setCreationDate(creationDate) {
+      this.creationDate = (0, _util.isString)(creationDate) ? creationDate : null;
+    }
+  }]);
+
+  return MarkupAnnotation;
+}(Annotation);
+
+exports.MarkupAnnotation = MarkupAnnotation;
+
+var WidgetAnnotation =
+/*#__PURE__*/
+function (_Annotation2) {
+  _inherits(WidgetAnnotation, _Annotation2);
+
+  function WidgetAnnotation(params) {
+    var _this3;
+
+    _classCallCheck(this, WidgetAnnotation);
+
+    _this3 = _possibleConstructorReturn(this, _getPrototypeOf(WidgetAnnotation).call(this, params));
+    var dict = params.dict;
+    var data = _this3.data;
+    data.annotationType = _util.AnnotationType.WIDGET;
+    data.fieldName = _this3._constructFieldName(dict);
+    data.fieldValue = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'V',
+      getArray: true
+    });
+    data.alternativeText = (0, _util.stringToPDFString)(dict.get('TU') || '');
+    data.defaultAppearance = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'DA'
+    }) || '';
+    var fieldType = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'FT'
+    });
+    data.fieldType = (0, _primitives.isName)(fieldType) ? fieldType.name : null;
+    _this3.fieldResources = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'DR'
+    }) || _primitives.Dict.empty;
+    data.fieldFlags = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'Ff'
+    });
+
+    if (!Number.isInteger(data.fieldFlags) || data.fieldFlags < 0) {
+      data.fieldFlags = 0;
+    }
+
+    data.readOnly = _this3.hasFieldFlag(_util.AnnotationFieldFlag.READONLY);
+
+    if (data.fieldType === 'Sig') {
+      data.fieldValue = null;
+
+      _this3.setFlags(_util.AnnotationFlag.HIDDEN);
+    }
+
+    return _this3;
+  }
+
+  _createClass(WidgetAnnotation, [{
+    key: "_constructFieldName",
+    value: function _constructFieldName(dict) {
+      if (!dict.has('T') && !dict.has('Parent')) {
+        (0, _util.warn)('Unknown field name, falling back to empty field name.');
+        return '';
+      }
+
+      if (!dict.has('Parent')) {
+        return (0, _util.stringToPDFString)(dict.get('T'));
+      }
+
+      var fieldName = [];
+
+      if (dict.has('T')) {
+        fieldName.unshift((0, _util.stringToPDFString)(dict.get('T')));
+      }
+
+      var loopDict = dict;
+
+      while (loopDict.has('Parent')) {
+        loopDict = loopDict.get('Parent');
+
+        if (!(0, _primitives.isDict)(loopDict)) {
+          break;
+        }
+
+        if (loopDict.has('T')) {
+          fieldName.unshift((0, _util.stringToPDFString)(loopDict.get('T')));
+        }
+      }
+
+      return fieldName.join('.');
+    }
+  }, {
+    key: "hasFieldFlag",
+    value: function hasFieldFlag(flag) {
+      return !!(this.data.fieldFlags & flag);
+    }
+  }, {
+    key: "getOperatorList",
+    value: function getOperatorList(evaluator, task, renderForms) {
+      if (renderForms) {
+        return Promise.resolve(new _operator_list.OperatorList());
+      }
+
+      return _get(_getPrototypeOf(WidgetAnnotation.prototype), "getOperatorList", this).call(this, evaluator, task, renderForms);
+    }
+  }]);
+
+  return WidgetAnnotation;
+}(Annotation);
+
+var TextWidgetAnnotation =
+/*#__PURE__*/
+function (_WidgetAnnotation) {
+  _inherits(TextWidgetAnnotation, _WidgetAnnotation);
+
+  function TextWidgetAnnotation(params) {
+    var _this4;
+
+    _classCallCheck(this, TextWidgetAnnotation);
+
+    _this4 = _possibleConstructorReturn(this, _getPrototypeOf(TextWidgetAnnotation).call(this, params));
+    var dict = params.dict;
+    _this4.data.fieldValue = (0, _util.stringToPDFString)(_this4.data.fieldValue || '');
+    var alignment = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'Q'
+    });
+
+    if (!Number.isInteger(alignment) || alignment < 0 || alignment > 2) {
+      alignment = null;
+    }
+
+    _this4.data.textAlignment = alignment;
+    var maximumLength = (0, _core_utils.getInheritableProperty)({
+      dict: dict,
+      key: 'MaxLen'
+    });
+
+    if (!Number.isInteger(maximumLength) || maximumLength < 0) {
+      maximumLength = null;
+    }
+
+    _this4.data.maxLen = maximumLength;
+    _this4.data.multiLine = _this4.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE);
+    _this4.data.comb = _this4.hasFieldFlag(_util.AnnotationFieldFlag.COMB) && !_this4.hasFieldFlag(_util.AnnotationFieldFlag.MULTILINE) && !_this4.hasFieldFlag(_util.AnnotationFieldFlag.PASSWORD) && !_this4.hasFieldFlag(_util.AnnotationFieldFlag.FILESELECT) && _this4.data.maxLen !== null;
+    return _this4;
+  }
+
+  _createClass(TextWidgetAnnotation, [{
+    key: "getOperatorList",
+    value: function getOperatorList(evaluator, task, renderForms) {
+      if (renderForms || this.appearance) {
+        return _get(_getPrototypeOf(TextWidgetAnnotation.prototype), "getOperatorList", this).call(this, evaluator, task, renderForms);
+      }
+
+      var operatorList = new _operator_list.OperatorList();
+
+      if (!this.data.defaultAppearance) {
+        return Promise.resolve(operatorList);
+      }
+
+      var stream = new _stream.Stream((0, _util.stringToBytes)(this.data.defaultAppearance));
+      return evaluator.getOperatorList({
+        stream: stream,
+        task: task,
+        resources: this.fieldResources,
+        operatorList: operatorList
+      }).then(function () {
+        return operatorList;
+      });
+    }
+  }]);
+
+  return TextWidgetAnnotation;
+}(WidgetAnnotation);
+
+var ButtonWidgetAnnotation =
+/*#__PURE__*/
+function (_WidgetAnnotation2) {
+  _inherits(ButtonWidgetAnnotation, _WidgetAnnotation2);
+
+  function ButtonWidgetAnnotation(params) {
+    var _this5;
+
+    _classCallCheck(this, ButtonWidgetAnnotation);
+
+    _this5 = _possibleConstructorReturn(this, _getPrototypeOf(ButtonWidgetAnnotation).call(this, params));
+    _this5.data.checkBox = !_this5.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !_this5.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
+    _this5.data.radioButton = _this5.hasFieldFlag(_util.AnnotationFieldFlag.RADIO) && !_this5.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
+    _this5.data.pushButton = _this5.hasFieldFlag(_util.AnnotationFieldFlag.PUSHBUTTON);
+
+    if (_this5.data.checkBox) {
+      _this5._processCheckBox(params);
+    } else if (_this5.data.radioButton) {
+      _this5._processRadioButton(params);
+    } else if (_this5.data.pushButton) {
+      _this5._processPushButton(params);
+    } else {
+      (0, _util.warn)('Invalid field flags for button widget annotation');
+    }
+
+    return _this5;
+  }
+
+  _createClass(ButtonWidgetAnnotation, [{
+    key: "_processCheckBox",
+    value: function _processCheckBox(params) {
+      if ((0, _primitives.isName)(this.data.fieldValue)) {
+        this.data.fieldValue = this.data.fieldValue.name;
+      }
+
+      var customAppearance = params.dict.get('AP');
+
+      if (!(0, _primitives.isDict)(customAppearance)) {
+        return;
+      }
+
+      var exportValueOptionsDict = customAppearance.get('D');
+
+      if (!(0, _primitives.isDict)(exportValueOptionsDict)) {
+        return;
+      }
+
+      var exportValues = exportValueOptionsDict.getKeys();
+      var hasCorrectOptionCount = exportValues.length === 2;
+
+      if (!hasCorrectOptionCount) {
+        return;
+      }
+
+      this.data.exportValue = exportValues[0] === 'Off' ? exportValues[1] : exportValues[0];
+    }
+  }, {
+    key: "_processRadioButton",
+    value: function _processRadioButton(params) {
+      this.data.fieldValue = this.data.buttonValue = null;
+      var fieldParent = params.dict.get('Parent');
+
+      if ((0, _primitives.isDict)(fieldParent) && fieldParent.has('V')) {
+        var fieldParentValue = fieldParent.get('V');
+
+        if ((0, _primitives.isName)(fieldParentValue)) {
+          this.data.fieldValue = fieldParentValue.name;
+        }
+      }
+
+      var appearanceStates = params.dict.get('AP');
+
+      if (!(0, _primitives.isDict)(appearanceStates)) {
+        return;
+      }
+
+      var normalAppearanceState = appearanceStates.get('N');
+
+      if (!(0, _primitives.isDict)(normalAppearanceState)) {
+        return;
+      }
+
+      var keys = normalAppearanceState.getKeys();
+
+      for (var i = 0, ii = keys.length; i < ii; i++) {
+        if (keys[i] !== 'Off') {
+          this.data.buttonValue = keys[i];
+          break;
+        }
+      }
+    }
+  }, {
+    key: "_processPushButton",
+    value: function _processPushButton(params) {
+      if (!params.dict.has('A')) {
+        (0, _util.warn)('Push buttons without action dictionaries are not supported');
+        return;
+      }
+
+      _obj.Catalog.parseDestDictionary({
+        destDict: params.dict,
+        resultObj: this.data,
+        docBaseUrl: params.pdfManager.docBaseUrl
+      });
+    }
+  }]);
+
+  return ButtonWidgetAnnotation;
+}(WidgetAnnotation);
+
+var ChoiceWidgetAnnotation =
+/*#__PURE__*/
+function (_WidgetAnnotation3) {
+  _inherits(ChoiceWidgetAnnotation, _WidgetAnnotation3);
+
+  function ChoiceWidgetAnnotation(params) {
+    var _this6;
+
+    _classCallCheck(this, ChoiceWidgetAnnotation);
+
+    _this6 = _possibleConstructorReturn(this, _getPrototypeOf(ChoiceWidgetAnnotation).call(this, params));
+    _this6.data.options = [];
+    var options = (0, _core_utils.getInheritableProperty)({
+      dict: params.dict,
+      key: 'Opt'
+    });
+
+    if (Array.isArray(options)) {
+      var xref = params.xref;
+
+      for (var i = 0, ii = options.length; i < ii; i++) {
+        var option = xref.fetchIfRef(options[i]);
+        var isOptionArray = Array.isArray(option);
+        _this6.data.options[i] = {
+          exportValue: isOptionArray ? xref.fetchIfRef(option[0]) : option,
+          displayValue: (0, _util.stringToPDFString)(isOptionArray ? xref.fetchIfRef(option[1]) : option)
+        };
+      }
+    }
+
+    if (!Array.isArray(_this6.data.fieldValue)) {
+      _this6.data.fieldValue = [_this6.data.fieldValue];
+    }
+
+    _this6.data.combo = _this6.hasFieldFlag(_util.AnnotationFieldFlag.COMBO);
+    _this6.data.multiSelect = _this6.hasFieldFlag(_util.AnnotationFieldFlag.MULTISELECT);
+    return _this6;
+  }
+
+  return ChoiceWidgetAnnotation;
+}(WidgetAnnotation);
+
+var TextAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation) {
+  _inherits(TextAnnotation, _MarkupAnnotation);
+
+  function TextAnnotation(parameters) {
+    var _this7;
+
+    _classCallCheck(this, TextAnnotation);
+
+    var DEFAULT_ICON_SIZE = 22;
+    _this7 = _possibleConstructorReturn(this, _getPrototypeOf(TextAnnotation).call(this, parameters));
+    _this7.data.annotationType = _util.AnnotationType.TEXT;
+
+    if (_this7.data.hasAppearance) {
+      _this7.data.name = 'NoIcon';
+    } else {
+      _this7.data.rect[1] = _this7.data.rect[3] - DEFAULT_ICON_SIZE;
+      _this7.data.rect[2] = _this7.data.rect[0] + DEFAULT_ICON_SIZE;
+      _this7.data.name = parameters.dict.has('Name') ? parameters.dict.get('Name').name : 'Note';
+    }
+
+    return _this7;
+  }
+
+  return TextAnnotation;
+}(MarkupAnnotation);
+
+var LinkAnnotation =
+/*#__PURE__*/
+function (_Annotation3) {
+  _inherits(LinkAnnotation, _Annotation3);
+
+  function LinkAnnotation(params) {
+    var _this8;
+
+    _classCallCheck(this, LinkAnnotation);
+
+    _this8 = _possibleConstructorReturn(this, _getPrototypeOf(LinkAnnotation).call(this, params));
+    _this8.data.annotationType = _util.AnnotationType.LINK;
+
+    _obj.Catalog.parseDestDictionary({
+      destDict: params.dict,
+      resultObj: _this8.data,
+      docBaseUrl: params.pdfManager.docBaseUrl
+    });
+
+    return _this8;
+  }
+
+  return LinkAnnotation;
+}(Annotation);
+
+var PopupAnnotation =
+/*#__PURE__*/
+function (_Annotation4) {
+  _inherits(PopupAnnotation, _Annotation4);
+
+  function PopupAnnotation(parameters) {
+    var _this9;
+
+    _classCallCheck(this, PopupAnnotation);
+
+    _this9 = _possibleConstructorReturn(this, _getPrototypeOf(PopupAnnotation).call(this, parameters));
+    _this9.data.annotationType = _util.AnnotationType.POPUP;
+    var dict = parameters.dict;
+    var parentItem = dict.get('Parent');
+
+    if (!parentItem) {
+      (0, _util.warn)('Popup annotation has a missing or invalid parent annotation.');
+      return _possibleConstructorReturn(_this9);
+    }
+
+    var parentSubtype = parentItem.get('Subtype');
+    _this9.data.parentType = (0, _primitives.isName)(parentSubtype) ? parentSubtype.name : null;
+    _this9.data.parentId = dict.getRaw('Parent').toString();
+    _this9.data.title = (0, _util.stringToPDFString)(parentItem.get('T') || '');
+    _this9.data.contents = (0, _util.stringToPDFString)(parentItem.get('Contents') || '');
+
+    if (!parentItem.has('M')) {
+      _this9.data.modificationDate = null;
+    } else {
+      _this9.setModificationDate(parentItem.get('M'));
+
+      _this9.data.modificationDate = _this9.modificationDate;
+    }
+
+    if (!parentItem.has('C')) {
+      _this9.data.color = null;
+    } else {
+      _this9.setColor(parentItem.getArray('C'));
+
+      _this9.data.color = _this9.color;
+    }
+
+    if (!_this9.viewable) {
+      var parentFlags = parentItem.get('F');
+
+      if (_this9._isViewable(parentFlags)) {
+        _this9.setFlags(parentFlags);
+      }
+    }
+
+    return _this9;
+  }
+
+  return PopupAnnotation;
+}(Annotation);
+
+var FreeTextAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation2) {
+  _inherits(FreeTextAnnotation, _MarkupAnnotation2);
+
+  function FreeTextAnnotation(parameters) {
+    var _this10;
+
+    _classCallCheck(this, FreeTextAnnotation);
+
+    _this10 = _possibleConstructorReturn(this, _getPrototypeOf(FreeTextAnnotation).call(this, parameters));
+    _this10.data.annotationType = _util.AnnotationType.FREETEXT;
+    return _this10;
+  }
+
+  return FreeTextAnnotation;
+}(MarkupAnnotation);
+
+var LineAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation3) {
+  _inherits(LineAnnotation, _MarkupAnnotation3);
+
+  function LineAnnotation(parameters) {
+    var _this11;
+
+    _classCallCheck(this, LineAnnotation);
+
+    _this11 = _possibleConstructorReturn(this, _getPrototypeOf(LineAnnotation).call(this, parameters));
+    _this11.data.annotationType = _util.AnnotationType.LINE;
+    var dict = parameters.dict;
+    _this11.data.lineCoordinates = _util.Util.normalizeRect(dict.getArray('L'));
+    return _this11;
+  }
+
+  return LineAnnotation;
+}(MarkupAnnotation);
+
+var SquareAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation4) {
+  _inherits(SquareAnnotation, _MarkupAnnotation4);
+
+  function SquareAnnotation(parameters) {
+    var _this12;
+
+    _classCallCheck(this, SquareAnnotation);
+
+    _this12 = _possibleConstructorReturn(this, _getPrototypeOf(SquareAnnotation).call(this, parameters));
+    _this12.data.annotationType = _util.AnnotationType.SQUARE;
+    return _this12;
+  }
+
+  return SquareAnnotation;
+}(MarkupAnnotation);
+
+var CircleAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation5) {
+  _inherits(CircleAnnotation, _MarkupAnnotation5);
+
+  function CircleAnnotation(parameters) {
+    var _this13;
+
+    _classCallCheck(this, CircleAnnotation);
+
+    _this13 = _possibleConstructorReturn(this, _getPrototypeOf(CircleAnnotation).call(this, parameters));
+    _this13.data.annotationType = _util.AnnotationType.CIRCLE;
+    return _this13;
+  }
+
+  return CircleAnnotation;
+}(MarkupAnnotation);
+
+var PolylineAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation6) {
+  _inherits(PolylineAnnotation, _MarkupAnnotation6);
+
+  function PolylineAnnotation(parameters) {
+    var _this14;
+
+    _classCallCheck(this, PolylineAnnotation);
+
+    _this14 = _possibleConstructorReturn(this, _getPrototypeOf(PolylineAnnotation).call(this, parameters));
+    _this14.data.annotationType = _util.AnnotationType.POLYLINE;
+    var dict = parameters.dict;
+    var rawVertices = dict.getArray('Vertices');
+    _this14.data.vertices = [];
+
+    for (var i = 0, ii = rawVertices.length; i < ii; i += 2) {
+      _this14.data.vertices.push({
+        x: rawVertices[i],
+        y: rawVertices[i + 1]
+      });
+    }
+
+    return _this14;
+  }
+
+  return PolylineAnnotation;
+}(MarkupAnnotation);
+
+var PolygonAnnotation =
+/*#__PURE__*/
+function (_PolylineAnnotation) {
+  _inherits(PolygonAnnotation, _PolylineAnnotation);
+
+  function PolygonAnnotation(parameters) {
+    var _this15;
+
+    _classCallCheck(this, PolygonAnnotation);
+
+    _this15 = _possibleConstructorReturn(this, _getPrototypeOf(PolygonAnnotation).call(this, parameters));
+    _this15.data.annotationType = _util.AnnotationType.POLYGON;
+    return _this15;
+  }
+
+  return PolygonAnnotation;
+}(PolylineAnnotation);
+
+var CaretAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation7) {
+  _inherits(CaretAnnotation, _MarkupAnnotation7);
+
+  function CaretAnnotation(parameters) {
+    var _this16;
+
+    _classCallCheck(this, CaretAnnotation);
+
+    _this16 = _possibleConstructorReturn(this, _getPrototypeOf(CaretAnnotation).call(this, parameters));
+    _this16.data.annotationType = _util.AnnotationType.CARET;
+    return _this16;
+  }
+
+  return CaretAnnotation;
+}(MarkupAnnotation);
+
+var InkAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation8) {
+  _inherits(InkAnnotation, _MarkupAnnotation8);
+
+  function InkAnnotation(parameters) {
+    var _this17;
+
+    _classCallCheck(this, InkAnnotation);
+
+    _this17 = _possibleConstructorReturn(this, _getPrototypeOf(InkAnnotation).call(this, parameters));
+    _this17.data.annotationType = _util.AnnotationType.INK;
+    var dict = parameters.dict;
+    var xref = parameters.xref;
+    var originalInkLists = dict.getArray('InkList');
+    _this17.data.inkLists = [];
+
+    for (var i = 0, ii = originalInkLists.length; i < ii; ++i) {
+      _this17.data.inkLists.push([]);
+
+      for (var j = 0, jj = originalInkLists[i].length; j < jj; j += 2) {
+        _this17.data.inkLists[i].push({
+          x: xref.fetchIfRef(originalInkLists[i][j]),
+          y: xref.fetchIfRef(originalInkLists[i][j + 1])
+        });
+      }
+    }
+
+    return _this17;
+  }
+
+  return InkAnnotation;
+}(MarkupAnnotation);
+
+var HighlightAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation9) {
+  _inherits(HighlightAnnotation, _MarkupAnnotation9);
+
+  function HighlightAnnotation(parameters) {
+    var _this18;
+
+    _classCallCheck(this, HighlightAnnotation);
+
+    _this18 = _possibleConstructorReturn(this, _getPrototypeOf(HighlightAnnotation).call(this, parameters));
+    _this18.data.annotationType = _util.AnnotationType.HIGHLIGHT;
+    return _this18;
+  }
+
+  return HighlightAnnotation;
+}(MarkupAnnotation);
+
+var UnderlineAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation10) {
+  _inherits(UnderlineAnnotation, _MarkupAnnotation10);
+
+  function UnderlineAnnotation(parameters) {
+    var _this19;
+
+    _classCallCheck(this, UnderlineAnnotation);
+
+    _this19 = _possibleConstructorReturn(this, _getPrototypeOf(UnderlineAnnotation).call(this, parameters));
+    _this19.data.annotationType = _util.AnnotationType.UNDERLINE;
+    return _this19;
+  }
+
+  return UnderlineAnnotation;
+}(MarkupAnnotation);
+
+var SquigglyAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation11) {
+  _inherits(SquigglyAnnotation, _MarkupAnnotation11);
+
+  function SquigglyAnnotation(parameters) {
+    var _this20;
+
+    _classCallCheck(this, SquigglyAnnotation);
+
+    _this20 = _possibleConstructorReturn(this, _getPrototypeOf(SquigglyAnnotation).call(this, parameters));
+    _this20.data.annotationType = _util.AnnotationType.SQUIGGLY;
+    return _this20;
+  }
+
+  return SquigglyAnnotation;
+}(MarkupAnnotation);
+
+var StrikeOutAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation12) {
+  _inherits(StrikeOutAnnotation, _MarkupAnnotation12);
+
+  function StrikeOutAnnotation(parameters) {
+    var _this21;
+
+    _classCallCheck(this, StrikeOutAnnotation);
+
+    _this21 = _possibleConstructorReturn(this, _getPrototypeOf(StrikeOutAnnotation).call(this, parameters));
+    _this21.data.annotationType = _util.AnnotationType.STRIKEOUT;
+    return _this21;
+  }
+
+  return StrikeOutAnnotation;
+}(MarkupAnnotation);
+
+var StampAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation13) {
+  _inherits(StampAnnotation, _MarkupAnnotation13);
+
+  function StampAnnotation(parameters) {
+    var _this22;
+
+    _classCallCheck(this, StampAnnotation);
+
+    _this22 = _possibleConstructorReturn(this, _getPrototypeOf(StampAnnotation).call(this, parameters));
+    _this22.data.annotationType = _util.AnnotationType.STAMP;
+    return _this22;
+  }
+
+  return StampAnnotation;
+}(MarkupAnnotation);
+
+var FileAttachmentAnnotation =
+/*#__PURE__*/
+function (_MarkupAnnotation14) {
+  _inherits(FileAttachmentAnnotation, _MarkupAnnotation14);
+
+  function FileAttachmentAnnotation(parameters) {
+    var _this23;
+
+    _classCallCheck(this, FileAttachmentAnnotation);
+
+    _this23 = _possibleConstructorReturn(this, _getPrototypeOf(FileAttachmentAnnotation).call(this, parameters));
+    var file = new _obj.FileSpec(parameters.dict.get('FS'), parameters.xref);
+    _this23.data.annotationType = _util.AnnotationType.FILEATTACHMENT;
+    _this23.data.file = file.serializable;
+    return _this23;
+  }
+
+  return FileAttachmentAnnotation;
+}(MarkupAnnotation);
+
+/***/ }),
+/* 171 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.OperatorList = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var QueueOptimizer = function QueueOptimizerClosure() {
+  function addState(parentState, pattern, checkFn, iterateFn, processFn) {
+    var state = parentState;
+
+    for (var i = 0, ii = pattern.length - 1; i < ii; i++) {
+      var item = pattern[i];
+      state = state[item] || (state[item] = []);
+    }
+
+    state[pattern[pattern.length - 1]] = {
+      checkFn: checkFn,
+      iterateFn: iterateFn,
+      processFn: processFn
+    };
+  }
+
+  function handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray) {
+    var iFirstPIMXO = iFirstSave + 2;
+
+    for (var i = 0; i < count; i++) {
+      var arg = argsArray[iFirstPIMXO + 4 * i];
+      var imageMask = arg.length === 1 && arg[0];
+
+      if (imageMask && imageMask.width === 1 && imageMask.height === 1 && (!imageMask.data.length || imageMask.data.length === 1 && imageMask.data[0] === 0)) {
+        fnArray[iFirstPIMXO + 4 * i] = _util.OPS.paintSolidColorImageMask;
+        continue;
+      }
+
+      break;
+    }
+
+    return count - i;
+  }
+
+  var InitialState = [];
+  addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintInlineImageXObject, _util.OPS.restore], null, function iterateInlineImageGroup(context, i) {
+    var fnArray = context.fnArray;
+    var iFirstSave = context.iCurr - 3;
+    var pos = (i - iFirstSave) % 4;
+
+    switch (pos) {
+      case 0:
+        return fnArray[i] === _util.OPS.save;
+
+      case 1:
+        return fnArray[i] === _util.OPS.transform;
+
+      case 2:
+        return fnArray[i] === _util.OPS.paintInlineImageXObject;
+
+      case 3:
+        return fnArray[i] === _util.OPS.restore;
+    }
+
+    throw new Error("iterateInlineImageGroup - invalid pos: ".concat(pos));
+  }, function foundInlineImageGroup(context, i) {
+    var MIN_IMAGES_IN_INLINE_IMAGES_BLOCK = 10;
+    var MAX_IMAGES_IN_INLINE_IMAGES_BLOCK = 200;
+    var MAX_WIDTH = 1000;
+    var IMAGE_PADDING = 1;
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var curr = context.iCurr;
+    var iFirstSave = curr - 3;
+    var iFirstTransform = curr - 2;
+    var iFirstPIIXO = curr - 1;
+    var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_INLINE_IMAGES_BLOCK);
+
+    if (count < MIN_IMAGES_IN_INLINE_IMAGES_BLOCK) {
+      return i - (i - iFirstSave) % 4;
+    }
+
+    var maxX = 0;
+    var map = [],
+        maxLineHeight = 0;
+    var currentX = IMAGE_PADDING,
+        currentY = IMAGE_PADDING;
+    var q;
+
+    for (q = 0; q < count; q++) {
+      var transform = argsArray[iFirstTransform + (q << 2)];
+      var img = argsArray[iFirstPIIXO + (q << 2)][0];
+
+      if (currentX + img.width > MAX_WIDTH) {
+        maxX = Math.max(maxX, currentX);
+        currentY += maxLineHeight + 2 * IMAGE_PADDING;
+        currentX = 0;
+        maxLineHeight = 0;
+      }
+
+      map.push({
+        transform: transform,
+        x: currentX,
+        y: currentY,
+        w: img.width,
+        h: img.height
+      });
+      currentX += img.width + 2 * IMAGE_PADDING;
+      maxLineHeight = Math.max(maxLineHeight, img.height);
+    }
+
+    var imgWidth = Math.max(maxX, currentX) + IMAGE_PADDING;
+    var imgHeight = currentY + maxLineHeight + IMAGE_PADDING;
+    var imgData = new Uint8ClampedArray(imgWidth * imgHeight * 4);
+    var imgRowSize = imgWidth << 2;
+
+    for (q = 0; q < count; q++) {
+      var data = argsArray[iFirstPIIXO + (q << 2)][0].data;
+      var rowSize = map[q].w << 2;
+      var dataOffset = 0;
+      var offset = map[q].x + map[q].y * imgWidth << 2;
+      imgData.set(data.subarray(0, rowSize), offset - imgRowSize);
+
+      for (var k = 0, kk = map[q].h; k < kk; k++) {
+        imgData.set(data.subarray(dataOffset, dataOffset + rowSize), offset);
+        dataOffset += rowSize;
+        offset += imgRowSize;
+      }
+
+      imgData.set(data.subarray(dataOffset - rowSize, dataOffset), offset);
+
+      while (offset >= 0) {
+        data[offset - 4] = data[offset];
+        data[offset - 3] = data[offset + 1];
+        data[offset - 2] = data[offset + 2];
+        data[offset - 1] = data[offset + 3];
+        data[offset + rowSize] = data[offset + rowSize - 4];
+        data[offset + rowSize + 1] = data[offset + rowSize - 3];
+        data[offset + rowSize + 2] = data[offset + rowSize - 2];
+        data[offset + rowSize + 3] = data[offset + rowSize - 1];
+        offset -= imgRowSize;
+      }
+    }
+
+    fnArray.splice(iFirstSave, count * 4, _util.OPS.paintInlineImageXObjectGroup);
+    argsArray.splice(iFirstSave, count * 4, [{
+      width: imgWidth,
+      height: imgHeight,
+      kind: _util.ImageKind.RGBA_32BPP,
+      data: imgData
+    }, map]);
+    return iFirstSave + 1;
+  });
+  addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageMaskXObject, _util.OPS.restore], null, function iterateImageMaskGroup(context, i) {
+    var fnArray = context.fnArray;
+    var iFirstSave = context.iCurr - 3;
+    var pos = (i - iFirstSave) % 4;
+
+    switch (pos) {
+      case 0:
+        return fnArray[i] === _util.OPS.save;
+
+      case 1:
+        return fnArray[i] === _util.OPS.transform;
+
+      case 2:
+        return fnArray[i] === _util.OPS.paintImageMaskXObject;
+
+      case 3:
+        return fnArray[i] === _util.OPS.restore;
+    }
+
+    throw new Error("iterateImageMaskGroup - invalid pos: ".concat(pos));
+  }, function foundImageMaskGroup(context, i) {
+    var MIN_IMAGES_IN_MASKS_BLOCK = 10;
+    var MAX_IMAGES_IN_MASKS_BLOCK = 100;
+    var MAX_SAME_IMAGES_IN_MASKS_BLOCK = 1000;
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var curr = context.iCurr;
+    var iFirstSave = curr - 3;
+    var iFirstTransform = curr - 2;
+    var iFirstPIMXO = curr - 1;
+    var count = Math.floor((i - iFirstSave) / 4);
+    count = handlePaintSolidColorImageMask(iFirstSave, count, fnArray, argsArray);
+
+    if (count < MIN_IMAGES_IN_MASKS_BLOCK) {
+      return i - (i - iFirstSave) % 4;
+    }
+
+    var q;
+    var isSameImage = false;
+    var iTransform, transformArgs;
+    var firstPIMXOArg0 = argsArray[iFirstPIMXO][0];
+
+    if (argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0) {
+      isSameImage = true;
+      var firstTransformArg0 = argsArray[iFirstTransform][0];
+      var firstTransformArg3 = argsArray[iFirstTransform][3];
+      iTransform = iFirstTransform + 4;
+      var iPIMXO = iFirstPIMXO + 4;
+
+      for (q = 1; q < count; q++, iTransform += 4, iPIMXO += 4) {
+        transformArgs = argsArray[iTransform];
+
+        if (argsArray[iPIMXO][0] !== firstPIMXOArg0 || transformArgs[0] !== firstTransformArg0 || transformArgs[1] !== 0 || transformArgs[2] !== 0 || transformArgs[3] !== firstTransformArg3) {
+          if (q < MIN_IMAGES_IN_MASKS_BLOCK) {
+            isSameImage = false;
+          } else {
+            count = q;
+          }
+
+          break;
+        }
+      }
+    }
+
+    if (isSameImage) {
+      count = Math.min(count, MAX_SAME_IMAGES_IN_MASKS_BLOCK);
+      var positions = new Float32Array(count * 2);
+      iTransform = iFirstTransform;
+
+      for (q = 0; q < count; q++, iTransform += 4) {
+        transformArgs = argsArray[iTransform];
+        positions[q << 1] = transformArgs[4];
+        positions[(q << 1) + 1] = transformArgs[5];
+      }
+
+      fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectRepeat);
+      argsArray.splice(iFirstSave, count * 4, [firstPIMXOArg0, firstTransformArg0, firstTransformArg3, positions]);
+    } else {
+      count = Math.min(count, MAX_IMAGES_IN_MASKS_BLOCK);
+      var images = [];
+
+      for (q = 0; q < count; q++) {
+        transformArgs = argsArray[iFirstTransform + (q << 2)];
+        var maskParams = argsArray[iFirstPIMXO + (q << 2)][0];
+        images.push({
+          data: maskParams.data,
+          width: maskParams.width,
+          height: maskParams.height,
+          transform: transformArgs
+        });
+      }
+
+      fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageMaskXObjectGroup);
+      argsArray.splice(iFirstSave, count * 4, [images]);
+    }
+
+    return iFirstSave + 1;
+  });
+  addState(InitialState, [_util.OPS.save, _util.OPS.transform, _util.OPS.paintImageXObject, _util.OPS.restore], function (context) {
+    var argsArray = context.argsArray;
+    var iFirstTransform = context.iCurr - 2;
+    return argsArray[iFirstTransform][1] === 0 && argsArray[iFirstTransform][2] === 0;
+  }, function iterateImageGroup(context, i) {
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var iFirstSave = context.iCurr - 3;
+    var pos = (i - iFirstSave) % 4;
+
+    switch (pos) {
+      case 0:
+        return fnArray[i] === _util.OPS.save;
+
+      case 1:
+        if (fnArray[i] !== _util.OPS.transform) {
+          return false;
+        }
+
+        var iFirstTransform = context.iCurr - 2;
+        var firstTransformArg0 = argsArray[iFirstTransform][0];
+        var firstTransformArg3 = argsArray[iFirstTransform][3];
+
+        if (argsArray[i][0] !== firstTransformArg0 || argsArray[i][1] !== 0 || argsArray[i][2] !== 0 || argsArray[i][3] !== firstTransformArg3) {
+          return false;
+        }
+
+        return true;
+
+      case 2:
+        if (fnArray[i] !== _util.OPS.paintImageXObject) {
+          return false;
+        }
+
+        var iFirstPIXO = context.iCurr - 1;
+        var firstPIXOArg0 = argsArray[iFirstPIXO][0];
+
+        if (argsArray[i][0] !== firstPIXOArg0) {
+          return false;
+        }
+
+        return true;
+
+      case 3:
+        return fnArray[i] === _util.OPS.restore;
+    }
+
+    throw new Error("iterateImageGroup - invalid pos: ".concat(pos));
+  }, function (context, i) {
+    var MIN_IMAGES_IN_BLOCK = 3;
+    var MAX_IMAGES_IN_BLOCK = 1000;
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var curr = context.iCurr;
+    var iFirstSave = curr - 3;
+    var iFirstTransform = curr - 2;
+    var iFirstPIXO = curr - 1;
+    var firstPIXOArg0 = argsArray[iFirstPIXO][0];
+    var firstTransformArg0 = argsArray[iFirstTransform][0];
+    var firstTransformArg3 = argsArray[iFirstTransform][3];
+    var count = Math.min(Math.floor((i - iFirstSave) / 4), MAX_IMAGES_IN_BLOCK);
+
+    if (count < MIN_IMAGES_IN_BLOCK) {
+      return i - (i - iFirstSave) % 4;
+    }
+
+    var positions = new Float32Array(count * 2);
+    var iTransform = iFirstTransform;
+
+    for (var q = 0; q < count; q++, iTransform += 4) {
+      var transformArgs = argsArray[iTransform];
+      positions[q << 1] = transformArgs[4];
+      positions[(q << 1) + 1] = transformArgs[5];
+    }
+
+    var args = [firstPIXOArg0, firstTransformArg0, firstTransformArg3, positions];
+    fnArray.splice(iFirstSave, count * 4, _util.OPS.paintImageXObjectRepeat);
+    argsArray.splice(iFirstSave, count * 4, args);
+    return iFirstSave + 1;
+  });
+  addState(InitialState, [_util.OPS.beginText, _util.OPS.setFont, _util.OPS.setTextMatrix, _util.OPS.showText, _util.OPS.endText], null, function iterateShowTextGroup(context, i) {
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var iFirstSave = context.iCurr - 4;
+    var pos = (i - iFirstSave) % 5;
+
+    switch (pos) {
+      case 0:
+        return fnArray[i] === _util.OPS.beginText;
+
+      case 1:
+        return fnArray[i] === _util.OPS.setFont;
+
+      case 2:
+        return fnArray[i] === _util.OPS.setTextMatrix;
+
+      case 3:
+        if (fnArray[i] !== _util.OPS.showText) {
+          return false;
+        }
+
+        var iFirstSetFont = context.iCurr - 3;
+        var firstSetFontArg0 = argsArray[iFirstSetFont][0];
+        var firstSetFontArg1 = argsArray[iFirstSetFont][1];
+
+        if (argsArray[i][0] !== firstSetFontArg0 || argsArray[i][1] !== firstSetFontArg1) {
+          return false;
+        }
+
+        return true;
+
+      case 4:
+        return fnArray[i] === _util.OPS.endText;
+    }
+
+    throw new Error("iterateShowTextGroup - invalid pos: ".concat(pos));
+  }, function (context, i) {
+    var MIN_CHARS_IN_BLOCK = 3;
+    var MAX_CHARS_IN_BLOCK = 1000;
+    var fnArray = context.fnArray,
+        argsArray = context.argsArray;
+    var curr = context.iCurr;
+    var iFirstBeginText = curr - 4;
+    var iFirstSetFont = curr - 3;
+    var iFirstSetTextMatrix = curr - 2;
+    var iFirstShowText = curr - 1;
+    var iFirstEndText = curr;
+    var firstSetFontArg0 = argsArray[iFirstSetFont][0];
+    var firstSetFontArg1 = argsArray[iFirstSetFont][1];
+    var count = Math.min(Math.floor((i - iFirstBeginText) / 5), MAX_CHARS_IN_BLOCK);
+
+    if (count < MIN_CHARS_IN_BLOCK) {
+      return i - (i - iFirstBeginText) % 5;
+    }
+
+    var iFirst = iFirstBeginText;
+
+    if (iFirstBeginText >= 4 && fnArray[iFirstBeginText - 4] === fnArray[iFirstSetFont] && fnArray[iFirstBeginText - 3] === fnArray[iFirstSetTextMatrix] && fnArray[iFirstBeginText - 2] === fnArray[iFirstShowText] && fnArray[iFirstBeginText - 1] === fnArray[iFirstEndText] && argsArray[iFirstBeginText - 4][0] === firstSetFontArg0 && argsArray[iFirstBeginText - 4][1] === firstSetFontArg1) {
+      count++;
+      iFirst -= 5;
+    }
+
+    var iEndText = iFirst + 4;
+
+    for (var q = 1; q < count; q++) {
+      fnArray.splice(iEndText, 3);
+      argsArray.splice(iEndText, 3);
+      iEndText += 2;
+    }
+
+    return iEndText + 1;
+  });
+
+  function QueueOptimizer(queue) {
+    this.queue = queue;
+    this.state = null;
+    this.context = {
+      iCurr: 0,
+      fnArray: queue.fnArray,
+      argsArray: queue.argsArray
+    };
+    this.match = null;
+    this.lastProcessed = 0;
+  }
+
+  QueueOptimizer.prototype = {
+    _optimize: function _optimize() {
+      var fnArray = this.queue.fnArray;
+      var i = this.lastProcessed,
+          ii = fnArray.length;
+      var state = this.state;
+      var match = this.match;
+
+      if (!state && !match && i + 1 === ii && !InitialState[fnArray[i]]) {
+        this.lastProcessed = ii;
+        return;
+      }
+
+      var context = this.context;
+
+      while (i < ii) {
+        if (match) {
+          var iterate = (0, match.iterateFn)(context, i);
+
+          if (iterate) {
+            i++;
+            continue;
+          }
+
+          i = (0, match.processFn)(context, i + 1);
+          ii = fnArray.length;
+          match = null;
+          state = null;
+
+          if (i >= ii) {
+            break;
+          }
+        }
+
+        state = (state || InitialState)[fnArray[i]];
+
+        if (!state || Array.isArray(state)) {
+          i++;
+          continue;
+        }
+
+        context.iCurr = i;
+        i++;
+
+        if (state.checkFn && !(0, state.checkFn)(context)) {
+          state = null;
+          continue;
+        }
+
+        match = state;
+        state = null;
+      }
+
+      this.state = state;
+      this.match = match;
+      this.lastProcessed = i;
+    },
+    push: function push(fn, args) {
+      this.queue.fnArray.push(fn);
+      this.queue.argsArray.push(args);
+
+      this._optimize();
+    },
+    flush: function flush() {
+      while (this.match) {
+        var length = this.queue.fnArray.length;
+        this.lastProcessed = (0, this.match.processFn)(this.context, length);
+        this.match = null;
+        this.state = null;
+
+        this._optimize();
+      }
+    },
+    reset: function reset() {
+      this.state = null;
+      this.match = null;
+      this.lastProcessed = 0;
+    }
+  };
+  return QueueOptimizer;
+}();
+
+var NullOptimizer = function NullOptimizerClosure() {
+  function NullOptimizer(queue) {
+    this.queue = queue;
+  }
+
+  NullOptimizer.prototype = {
+    push: function push(fn, args) {
+      this.queue.fnArray.push(fn);
+      this.queue.argsArray.push(args);
+    },
+    flush: function flush() {},
+    reset: function reset() {}
+  };
+  return NullOptimizer;
+}();
+
+var OperatorList = function OperatorListClosure() {
+  var CHUNK_SIZE = 1000;
+  var CHUNK_SIZE_ABOUT = CHUNK_SIZE - 5;
+
+  function OperatorList(intent, messageHandler, pageIndex) {
+    this.messageHandler = messageHandler;
+    this.fnArray = [];
+    this.argsArray = [];
+
+    if (messageHandler && intent !== 'oplist') {
+      this.optimizer = new QueueOptimizer(this);
+    } else {
+      this.optimizer = new NullOptimizer(this);
+    }
+
+    this.dependencies = Object.create(null);
+    this._totalLength = 0;
+    this.pageIndex = pageIndex;
+    this.intent = intent;
+    this.weight = 0;
+  }
+
+  OperatorList.prototype = {
+    get length() {
+      return this.argsArray.length;
+    },
+
+    get totalLength() {
+      return this._totalLength + this.length;
+    },
+
+    addOp: function addOp(fn, args) {
+      this.optimizer.push(fn, args);
+      this.weight++;
+
+      if (this.messageHandler) {
+        if (this.weight >= CHUNK_SIZE) {
+          this.flush();
+        } else if (this.weight >= CHUNK_SIZE_ABOUT && (fn === _util.OPS.restore || fn === _util.OPS.endText)) {
+          this.flush();
+        }
+      }
+    },
+    addDependency: function addDependency(dependency) {
+      if (dependency in this.dependencies) {
+        return;
+      }
+
+      this.dependencies[dependency] = true;
+      this.addOp(_util.OPS.dependency, [dependency]);
+    },
+    addDependencies: function addDependencies(dependencies) {
+      for (var key in dependencies) {
+        this.addDependency(key);
+      }
+    },
+    addOpList: function addOpList(opList) {
+      Object.assign(this.dependencies, opList.dependencies);
+
+      for (var i = 0, ii = opList.length; i < ii; i++) {
+        this.addOp(opList.fnArray[i], opList.argsArray[i]);
+      }
+    },
+    getIR: function getIR() {
+      return {
+        fnArray: this.fnArray,
+        argsArray: this.argsArray,
+        length: this.length
+      };
+    },
+
+    get _transfers() {
+      var transfers = [];
+      var fnArray = this.fnArray,
+          argsArray = this.argsArray,
+          length = this.length;
+
+      for (var i = 0; i < length; i++) {
+        switch (fnArray[i]) {
+          case _util.OPS.paintInlineImageXObject:
+          case _util.OPS.paintInlineImageXObjectGroup:
+          case _util.OPS.paintImageMaskXObject:
+            var arg = argsArray[i][0];
+            ;
+
+            if (!arg.cached) {
+              transfers.push(arg.data.buffer);
+            }
+
+            break;
+        }
+      }
+
+      return transfers;
+    },
+
+    flush: function flush() {
+      var lastChunk = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+      this.optimizer.flush();
+      var length = this.length;
+      this._totalLength += length;
+      this.messageHandler.send('RenderPageChunk', {
+        operatorList: {
+          fnArray: this.fnArray,
+          argsArray: this.argsArray,
+          lastChunk: lastChunk,
+          length: length
+        },
+        pageIndex: this.pageIndex,
+        intent: this.intent
+      }, this._transfers);
+      this.dependencies = Object.create(null);
+      this.fnArray.length = 0;
+      this.argsArray.length = 0;
+      this.weight = 0;
+      this.optimizer.reset();
+    }
+  };
+  return OperatorList;
+}();
+
+exports.OperatorList = OperatorList;
+
+/***/ }),
+/* 172 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PartialEvaluator = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+var _cmap = __w_pdfjs_require__(173);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _fonts = __w_pdfjs_require__(174);
+
+var _encodings = __w_pdfjs_require__(177);
+
+var _unicode = __w_pdfjs_require__(180);
+
+var _standard_fonts = __w_pdfjs_require__(179);
+
+var _pattern = __w_pdfjs_require__(183);
+
+var _parser = __w_pdfjs_require__(157);
+
+var _bidi = __w_pdfjs_require__(184);
+
+var _colorspace = __w_pdfjs_require__(169);
+
+var _stream = __w_pdfjs_require__(158);
+
+var _glyphlist = __w_pdfjs_require__(178);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _metrics = __w_pdfjs_require__(185);
+
+var _function = __w_pdfjs_require__(186);
+
+var _jpeg_stream = __w_pdfjs_require__(164);
+
+var _murmurhash = __w_pdfjs_require__(188);
+
+var _image_utils = __w_pdfjs_require__(189);
+
+var _operator_list = __w_pdfjs_require__(171);
+
+var _image = __w_pdfjs_require__(190);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+var PartialEvaluator = function PartialEvaluatorClosure() {
+  var DefaultPartialEvaluatorOptions = {
+    forceDataSchema: false,
+    maxImageSize: -1,
+    disableFontFace: false,
+    nativeImageDecoderSupport: _util.NativeImageDecoding.DECODE,
+    ignoreErrors: false,
+    isEvalSupported: true
+  };
+
+  function PartialEvaluator(_ref) {
+    var _this = this;
+
+    var xref = _ref.xref,
+        handler = _ref.handler,
+        pageIndex = _ref.pageIndex,
+        idFactory = _ref.idFactory,
+        fontCache = _ref.fontCache,
+        builtInCMapCache = _ref.builtInCMapCache,
+        _ref$options = _ref.options,
+        options = _ref$options === void 0 ? null : _ref$options,
+        pdfFunctionFactory = _ref.pdfFunctionFactory;
+    this.xref = xref;
+    this.handler = handler;
+    this.pageIndex = pageIndex;
+    this.idFactory = idFactory;
+    this.fontCache = fontCache;
+    this.builtInCMapCache = builtInCMapCache;
+    this.options = options || DefaultPartialEvaluatorOptions;
+    this.pdfFunctionFactory = pdfFunctionFactory;
+    this.parsingType3Font = false;
+
+    this.fetchBuiltInCMap =
+    /*#__PURE__*/
+    function () {
+      var _ref2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee(name) {
+        var data;
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                if (!_this.builtInCMapCache.has(name)) {
+                  _context.next = 2;
+                  break;
+                }
+
+                return _context.abrupt("return", _this.builtInCMapCache.get(name));
+
+              case 2:
+                _context.next = 4;
+                return _this.handler.sendWithPromise('FetchBuiltInCMap', {
+                  name: name
+                });
+
+              case 4:
+                data = _context.sent;
+
+                if (data.compressionType !== _util.CMapCompressionType.NONE) {
+                  _this.builtInCMapCache.set(name, data);
+                }
+
+                return _context.abrupt("return", data);
+
+              case 7:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee);
+      }));
+
+      return function (_x) {
+        return _ref2.apply(this, arguments);
+      };
+    }();
+  }
+
+  var TIME_SLOT_DURATION_MS = 20;
+  var CHECK_TIME_EVERY = 100;
+
+  function TimeSlotManager() {
+    this.reset();
+  }
+
+  TimeSlotManager.prototype = {
+    check: function TimeSlotManager_check() {
+      if (++this.checked < CHECK_TIME_EVERY) {
+        return false;
+      }
+
+      this.checked = 0;
+      return this.endTime <= Date.now();
+    },
+    reset: function TimeSlotManager_reset() {
+      this.endTime = Date.now() + TIME_SLOT_DURATION_MS;
+      this.checked = 0;
+    }
+  };
+
+  function normalizeBlendMode(value) {
+    if (!(0, _primitives.isName)(value)) {
+      return 'source-over';
+    }
+
+    switch (value.name) {
+      case 'Normal':
+      case 'Compatible':
+        return 'source-over';
+
+      case 'Multiply':
+        return 'multiply';
+
+      case 'Screen':
+        return 'screen';
+
+      case 'Overlay':
+        return 'overlay';
+
+      case 'Darken':
+        return 'darken';
+
+      case 'Lighten':
+        return 'lighten';
+
+      case 'ColorDodge':
+        return 'color-dodge';
+
+      case 'ColorBurn':
+        return 'color-burn';
+
+      case 'HardLight':
+        return 'hard-light';
+
+      case 'SoftLight':
+        return 'soft-light';
+
+      case 'Difference':
+        return 'difference';
+
+      case 'Exclusion':
+        return 'exclusion';
+
+      case 'Hue':
+        return 'hue';
+
+      case 'Saturation':
+        return 'saturation';
+
+      case 'Color':
+        return 'color';
+
+      case 'Luminosity':
+        return 'luminosity';
+    }
+
+    (0, _util.warn)('Unsupported blend mode: ' + value.name);
+    return 'source-over';
+  }
+
+  var deferred = Promise.resolve();
+  var TILING_PATTERN = 1,
+      SHADING_PATTERN = 2;
+  PartialEvaluator.prototype = {
+    clone: function clone() {
+      var newOptions = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DefaultPartialEvaluatorOptions;
+      var newEvaluator = Object.create(this);
+      newEvaluator.options = newOptions;
+      return newEvaluator;
+    },
+    hasBlendModes: function PartialEvaluator_hasBlendModes(resources) {
+      if (!(0, _primitives.isDict)(resources)) {
+        return false;
+      }
+
+      var processed = Object.create(null);
+
+      if (resources.objId) {
+        processed[resources.objId] = true;
+      }
+
+      var nodes = [resources],
+          xref = this.xref;
+
+      while (nodes.length) {
+        var key, i, ii;
+        var node = nodes.shift();
+        var graphicStates = node.get('ExtGState');
+
+        if ((0, _primitives.isDict)(graphicStates)) {
+          var graphicStatesKeys = graphicStates.getKeys();
+
+          for (i = 0, ii = graphicStatesKeys.length; i < ii; i++) {
+            key = graphicStatesKeys[i];
+            var graphicState = graphicStates.get(key);
+            var bm = graphicState.get('BM');
+
+            if ((0, _primitives.isName)(bm) && bm.name !== 'Normal') {
+              return true;
+            }
+          }
+        }
+
+        var xObjects = node.get('XObject');
+
+        if (!(0, _primitives.isDict)(xObjects)) {
+          continue;
+        }
+
+        var xObjectsKeys = xObjects.getKeys();
+
+        for (i = 0, ii = xObjectsKeys.length; i < ii; i++) {
+          key = xObjectsKeys[i];
+          var xObject = xObjects.getRaw(key);
+
+          if ((0, _primitives.isRef)(xObject)) {
+            if (processed[xObject.toString()]) {
+              continue;
+            }
+
+            xObject = xref.fetch(xObject);
+          }
+
+          if (!(0, _primitives.isStream)(xObject)) {
+            continue;
+          }
+
+          if (xObject.dict.objId) {
+            if (processed[xObject.dict.objId]) {
+              continue;
+            }
+
+            processed[xObject.dict.objId] = true;
+          }
+
+          var xResources = xObject.dict.get('Resources');
+
+          if ((0, _primitives.isDict)(xResources) && (!xResources.objId || !processed[xResources.objId])) {
+            nodes.push(xResources);
+
+            if (xResources.objId) {
+              processed[xResources.objId] = true;
+            }
+          }
+        }
+      }
+
+      return false;
+    },
+    buildFormXObject: function PartialEvaluator_buildFormXObject(resources, xobj, smask, operatorList, task, initialState) {
+      var dict = xobj.dict;
+      var matrix = dict.getArray('Matrix');
+      var bbox = dict.getArray('BBox');
+
+      if (Array.isArray(bbox) && bbox.length === 4) {
+        bbox = _util.Util.normalizeRect(bbox);
+      } else {
+        bbox = null;
+      }
+
+      var group = dict.get('Group');
+
+      if (group) {
+        var groupOptions = {
+          matrix: matrix,
+          bbox: bbox,
+          smask: smask,
+          isolated: false,
+          knockout: false
+        };
+        var groupSubtype = group.get('S');
+        var colorSpace = null;
+
+        if ((0, _primitives.isName)(groupSubtype, 'Transparency')) {
+          groupOptions.isolated = group.get('I') || false;
+          groupOptions.knockout = group.get('K') || false;
+
+          if (group.has('CS')) {
+            colorSpace = _colorspace.ColorSpace.parse(group.get('CS'), this.xref, resources, this.pdfFunctionFactory);
+          }
+        }
+
+        if (smask && smask.backdrop) {
+          colorSpace = colorSpace || _colorspace.ColorSpace.singletons.rgb;
+          smask.backdrop = colorSpace.getRgb(smask.backdrop, 0);
+        }
+
+        operatorList.addOp(_util.OPS.beginGroup, [groupOptions]);
+      }
+
+      operatorList.addOp(_util.OPS.paintFormXObjectBegin, [matrix, bbox]);
+      return this.getOperatorList({
+        stream: xobj,
+        task: task,
+        resources: dict.get('Resources') || resources,
+        operatorList: operatorList,
+        initialState: initialState
+      }).then(function () {
+        operatorList.addOp(_util.OPS.paintFormXObjectEnd, []);
+
+        if (group) {
+          operatorList.addOp(_util.OPS.endGroup, [groupOptions]);
+        }
+      });
+    },
+    buildPaintImageXObject: function () {
+      var _buildPaintImageXObject = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2(_ref3) {
+        var _this2 = this;
+
+        var resources, image, _ref3$isInline, isInline, operatorList, cacheKey, imageCache, _ref3$forceDisableNat, forceDisableNativeImageDecoder, dict, w, h, maxImageSize, imageMask, imgData, args, width, height, bitStrideLength, imgArray, decode, softMask, mask, SMALL_IMAGE_DIMENSIONS, imageObj, nativeImageDecoderSupport, objId, nativeImageDecoder, imgPromise;
+
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                resources = _ref3.resources, image = _ref3.image, _ref3$isInline = _ref3.isInline, isInline = _ref3$isInline === void 0 ? false : _ref3$isInline, operatorList = _ref3.operatorList, cacheKey = _ref3.cacheKey, imageCache = _ref3.imageCache, _ref3$forceDisableNat = _ref3.forceDisableNativeImageDecoder, forceDisableNativeImageDecoder = _ref3$forceDisableNat === void 0 ? false : _ref3$forceDisableNat;
+                dict = image.dict;
+                w = dict.get('Width', 'W');
+                h = dict.get('Height', 'H');
+
+                if (!(!(w && (0, _util.isNum)(w)) || !(h && (0, _util.isNum)(h)))) {
+                  _context2.next = 7;
+                  break;
+                }
+
+                (0, _util.warn)('Image dimensions are missing, or not numbers.');
+                return _context2.abrupt("return", undefined);
+
+              case 7:
+                maxImageSize = this.options.maxImageSize;
+
+                if (!(maxImageSize !== -1 && w * h > maxImageSize)) {
+                  _context2.next = 11;
+                  break;
+                }
+
+                (0, _util.warn)('Image exceeded maximum allowed size and was removed.');
+                return _context2.abrupt("return", undefined);
+
+              case 11:
+                imageMask = dict.get('ImageMask', 'IM') || false;
+
+                if (!imageMask) {
+                  _context2.next = 24;
+                  break;
+                }
+
+                width = dict.get('Width', 'W');
+                height = dict.get('Height', 'H');
+                bitStrideLength = width + 7 >> 3;
+                imgArray = image.getBytes(bitStrideLength * height, true);
+                decode = dict.getArray('Decode', 'D');
+                imgData = _image.PDFImage.createMask({
+                  imgArray: imgArray,
+                  width: width,
+                  height: height,
+                  imageIsFromDecodeStream: image instanceof _stream.DecodeStream,
+                  inverseDecode: !!decode && decode[0] > 0
+                });
+                imgData.cached = !!cacheKey;
+                args = [imgData];
+                operatorList.addOp(_util.OPS.paintImageMaskXObject, args);
+
+                if (cacheKey) {
+                  imageCache[cacheKey] = {
+                    fn: _util.OPS.paintImageMaskXObject,
+                    args: args
+                  };
+                }
+
+                return _context2.abrupt("return", undefined);
+
+              case 24:
+                softMask = dict.get('SMask', 'SM') || false;
+                mask = dict.get('Mask') || false;
+                SMALL_IMAGE_DIMENSIONS = 200;
+
+                if (!(isInline && !softMask && !mask && !(image instanceof _jpeg_stream.JpegStream) && w + h < SMALL_IMAGE_DIMENSIONS)) {
+                  _context2.next = 32;
+                  break;
+                }
+
+                imageObj = new _image.PDFImage({
+                  xref: this.xref,
+                  res: resources,
+                  image: image,
+                  isInline: isInline,
+                  pdfFunctionFactory: this.pdfFunctionFactory
+                });
+                imgData = imageObj.createImageData(true);
+                operatorList.addOp(_util.OPS.paintInlineImageXObject, [imgData]);
+                return _context2.abrupt("return", undefined);
+
+              case 32:
+                nativeImageDecoderSupport = forceDisableNativeImageDecoder ? _util.NativeImageDecoding.NONE : this.options.nativeImageDecoderSupport;
+                objId = "img_".concat(this.idFactory.createObjId());
+
+                if (this.parsingType3Font) {
+                  (0, _util.assert)(nativeImageDecoderSupport === _util.NativeImageDecoding.NONE, 'Type3 image resources should be completely decoded in the worker.');
+                  objId = "".concat(this.idFactory.getDocId(), "_type3res_").concat(objId);
+                }
+
+                if (!(nativeImageDecoderSupport !== _util.NativeImageDecoding.NONE && !softMask && !mask && image instanceof _jpeg_stream.JpegStream && _image_utils.NativeImageDecoder.isSupported(image, this.xref, resources, this.pdfFunctionFactory))) {
+                  _context2.next = 37;
+                  break;
+                }
+
+                return _context2.abrupt("return", this.handler.sendWithPromise('obj', [objId, this.pageIndex, 'JpegStream', image.getIR(this.options.forceDataSchema)]).then(function () {
+                  operatorList.addDependency(objId);
+                  args = [objId, w, h];
+                  operatorList.addOp(_util.OPS.paintJpegXObject, args);
+
+                  if (cacheKey) {
+                    imageCache[cacheKey] = {
+                      fn: _util.OPS.paintJpegXObject,
+                      args: args
+                    };
+                  }
+                }, function (reason) {
+                  (0, _util.warn)('Native JPEG decoding failed -- trying to recover: ' + (reason && reason.message));
+                  return _this2.buildPaintImageXObject({
+                    resources: resources,
+                    image: image,
+                    isInline: isInline,
+                    operatorList: operatorList,
+                    cacheKey: cacheKey,
+                    imageCache: imageCache,
+                    forceDisableNativeImageDecoder: true
+                  });
+                }));
+
+              case 37:
+                nativeImageDecoder = null;
+
+                if (nativeImageDecoderSupport === _util.NativeImageDecoding.DECODE && (image instanceof _jpeg_stream.JpegStream || mask instanceof _jpeg_stream.JpegStream || softMask instanceof _jpeg_stream.JpegStream)) {
+                  nativeImageDecoder = new _image_utils.NativeImageDecoder({
+                    xref: this.xref,
+                    resources: resources,
+                    handler: this.handler,
+                    forceDataSchema: this.options.forceDataSchema,
+                    pdfFunctionFactory: this.pdfFunctionFactory
+                  });
+                }
+
+                operatorList.addDependency(objId);
+                args = [objId, w, h];
+                imgPromise = _image.PDFImage.buildImage({
+                  handler: this.handler,
+                  xref: this.xref,
+                  res: resources,
+                  image: image,
+                  isInline: isInline,
+                  nativeDecoder: nativeImageDecoder,
+                  pdfFunctionFactory: this.pdfFunctionFactory
+                }).then(function (imageObj) {
+                  var imgData = imageObj.createImageData(false);
+
+                  if (_this2.parsingType3Font) {
+                    return _this2.handler.sendWithPromise('commonobj', [objId, 'FontType3Res', imgData], [imgData.data.buffer]);
+                  }
+
+                  _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', imgData], [imgData.data.buffer]);
+
+                  return undefined;
+                })["catch"](function (reason) {
+                  (0, _util.warn)('Unable to decode image: ' + reason);
+
+                  if (_this2.parsingType3Font) {
+                    return _this2.handler.sendWithPromise('commonobj', [objId, 'FontType3Res', null]);
+                  }
+
+                  _this2.handler.send('obj', [objId, _this2.pageIndex, 'Image', null]);
+
+                  return undefined;
+                });
+
+                if (!this.parsingType3Font) {
+                  _context2.next = 45;
+                  break;
+                }
+
+                _context2.next = 45;
+                return imgPromise;
+
+              case 45:
+                operatorList.addOp(_util.OPS.paintImageXObject, args);
+
+                if (cacheKey) {
+                  imageCache[cacheKey] = {
+                    fn: _util.OPS.paintImageXObject,
+                    args: args
+                  };
+                }
+
+                return _context2.abrupt("return", undefined);
+
+              case 48:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function buildPaintImageXObject(_x2) {
+        return _buildPaintImageXObject.apply(this, arguments);
+      }
+
+      return buildPaintImageXObject;
+    }(),
+    handleSMask: function PartialEvaluator_handleSmask(smask, resources, operatorList, task, stateManager) {
+      var smaskContent = smask.get('G');
+      var smaskOptions = {
+        subtype: smask.get('S').name,
+        backdrop: smask.get('BC')
+      };
+      var transferObj = smask.get('TR');
+
+      if ((0, _function.isPDFFunction)(transferObj)) {
+        var transferFn = this.pdfFunctionFactory.create(transferObj);
+        var transferMap = new Uint8Array(256);
+        var tmp = new Float32Array(1);
+
+        for (var i = 0; i < 256; i++) {
+          tmp[0] = i / 255;
+          transferFn(tmp, 0, tmp, 0);
+          transferMap[i] = tmp[0] * 255 | 0;
+        }
+
+        smaskOptions.transferMap = transferMap;
+      }
+
+      return this.buildFormXObject(resources, smaskContent, smaskOptions, operatorList, task, stateManager.state.clone());
+    },
+    handleTilingType: function handleTilingType(fn, args, resources, pattern, patternDict, operatorList, task) {
+      var _this3 = this;
+
+      var tilingOpList = new _operator_list.OperatorList();
+      var resourcesArray = [patternDict.get('Resources'), resources];
+
+      var patternResources = _primitives.Dict.merge(this.xref, resourcesArray);
+
+      return this.getOperatorList({
+        stream: pattern,
+        task: task,
+        resources: patternResources,
+        operatorList: tilingOpList
+      }).then(function () {
+        return (0, _pattern.getTilingPatternIR)({
+          fnArray: tilingOpList.fnArray,
+          argsArray: tilingOpList.argsArray
+        }, patternDict, args);
+      }).then(function (tilingPatternIR) {
+        operatorList.addDependencies(tilingOpList.dependencies);
+        operatorList.addOp(fn, tilingPatternIR);
+      }, function (reason) {
+        if (_this3.options.ignoreErrors) {
+          _this3.handler.send('UnsupportedFeature', {
+            featureId: _util.UNSUPPORTED_FEATURES.unknown
+          });
+
+          (0, _util.warn)("handleTilingType - ignoring pattern: \"".concat(reason, "\"."));
+          return;
+        }
+
+        throw reason;
+      });
+    },
+    handleSetFont: function PartialEvaluator_handleSetFont(resources, fontArgs, fontRef, operatorList, task, state) {
+      var _this4 = this;
+
+      var fontName;
+
+      if (fontArgs) {
+        fontArgs = fontArgs.slice();
+        fontName = fontArgs[0].name;
+      }
+
+      return this.loadFont(fontName, fontRef, resources).then(function (translated) {
+        if (!translated.font.isType3Font) {
+          return translated;
+        }
+
+        return translated.loadType3Data(_this4, resources, operatorList, task).then(function () {
+          return translated;
+        })["catch"](function (reason) {
+          _this4.handler.send('UnsupportedFeature', {
+            featureId: _util.UNSUPPORTED_FEATURES.font
+          });
+
+          return new TranslatedFont('g_font_error', new _fonts.ErrorFont('Type3 font load error: ' + reason), translated.font);
+        });
+      }).then(function (translated) {
+        state.font = translated.font;
+        translated.send(_this4.handler);
+        return translated.loadedName;
+      });
+    },
+    handleText: function handleText(chars, state) {
+      var font = state.font;
+      var glyphs = font.charsToGlyphs(chars);
+
+      if (font.data) {
+        var isAddToPathSet = !!(state.textRenderingMode & _util.TextRenderingMode.ADD_TO_PATH_FLAG);
+
+        if (isAddToPathSet || state.fillColorSpace.name === 'Pattern' || font.disableFontFace || this.options.disableFontFace) {
+          PartialEvaluator.buildFontPaths(font, glyphs, this.handler);
+        }
+      }
+
+      return glyphs;
+    },
+    setGState: function PartialEvaluator_setGState(resources, gState, operatorList, task, stateManager) {
+      var _this5 = this;
+
+      var gStateObj = [];
+      var gStateKeys = gState.getKeys();
+      var promise = Promise.resolve();
+
+      var _loop = function _loop() {
+        var key = gStateKeys[i];
+        var value = gState.get(key);
+
+        switch (key) {
+          case 'Type':
+            break;
+
+          case 'LW':
+          case 'LC':
+          case 'LJ':
+          case 'ML':
+          case 'D':
+          case 'RI':
+          case 'FL':
+          case 'CA':
+          case 'ca':
+            gStateObj.push([key, value]);
+            break;
+
+          case 'Font':
+            promise = promise.then(function () {
+              return _this5.handleSetFont(resources, null, value[0], operatorList, task, stateManager.state).then(function (loadedName) {
+                operatorList.addDependency(loadedName);
+                gStateObj.push([key, [loadedName, value[1]]]);
+              });
+            });
+            break;
+
+          case 'BM':
+            gStateObj.push([key, normalizeBlendMode(value)]);
+            break;
+
+          case 'SMask':
+            if ((0, _primitives.isName)(value, 'None')) {
+              gStateObj.push([key, false]);
+              break;
+            }
+
+            if ((0, _primitives.isDict)(value)) {
+              promise = promise.then(function () {
+                return _this5.handleSMask(value, resources, operatorList, task, stateManager);
+              });
+              gStateObj.push([key, true]);
+            } else {
+              (0, _util.warn)('Unsupported SMask type');
+            }
+
+            break;
+
+          case 'OP':
+          case 'op':
+          case 'OPM':
+          case 'BG':
+          case 'BG2':
+          case 'UCR':
+          case 'UCR2':
+          case 'TR':
+          case 'TR2':
+          case 'HT':
+          case 'SM':
+          case 'SA':
+          case 'AIS':
+          case 'TK':
+            (0, _util.info)('graphic state operator ' + key);
+            break;
+
+          default:
+            (0, _util.info)('Unknown graphic state operator ' + key);
+            break;
+        }
+      };
+
+      for (var i = 0, ii = gStateKeys.length; i < ii; i++) {
+        _loop();
+      }
+
+      return promise.then(function () {
+        if (gStateObj.length > 0) {
+          operatorList.addOp(_util.OPS.setGState, [gStateObj]);
+        }
+      });
+    },
+    loadFont: function PartialEvaluator_loadFont(fontName, font, resources) {
+      var _this6 = this;
+
+      function errorFont() {
+        return Promise.resolve(new TranslatedFont('g_font_error', new _fonts.ErrorFont('Font ' + fontName + ' is not available'), font));
+      }
+
+      var fontRef,
+          xref = this.xref;
+
+      if (font) {
+        if (!(0, _primitives.isRef)(font)) {
+          throw new Error('The "font" object should be a reference.');
+        }
+
+        fontRef = font;
+      } else {
+        var fontRes = resources.get('Font');
+
+        if (fontRes) {
+          fontRef = fontRes.getRaw(fontName);
+        } else {
+          (0, _util.warn)('fontRes not available');
+          return errorFont();
+        }
+      }
+
+      if (!fontRef) {
+        (0, _util.warn)('fontRef not available');
+        return errorFont();
+      }
+
+      if (this.fontCache.has(fontRef)) {
+        return this.fontCache.get(fontRef);
+      }
+
+      font = xref.fetchIfRef(fontRef);
+
+      if (!(0, _primitives.isDict)(font)) {
+        return errorFont();
+      }
+
+      if (font.translated) {
+        return font.translated;
+      }
+
+      var fontCapability = (0, _util.createPromiseCapability)();
+      var preEvaluatedFont = this.preEvaluateFont(font);
+      var descriptor = preEvaluatedFont.descriptor,
+          hash = preEvaluatedFont.hash;
+      var fontRefIsRef = (0, _primitives.isRef)(fontRef),
+          fontID;
+
+      if (fontRefIsRef) {
+        fontID = fontRef.toString();
+      }
+
+      if (hash && (0, _primitives.isDict)(descriptor)) {
+        if (!descriptor.fontAliases) {
+          descriptor.fontAliases = Object.create(null);
+        }
+
+        var fontAliases = descriptor.fontAliases;
+
+        if (fontAliases[hash]) {
+          var aliasFontRef = fontAliases[hash].aliasRef;
+
+          if (fontRefIsRef && aliasFontRef && this.fontCache.has(aliasFontRef)) {
+            this.fontCache.putAlias(fontRef, aliasFontRef);
+            return this.fontCache.get(fontRef);
+          }
+        } else {
+          fontAliases[hash] = {
+            fontID: _fonts.Font.getFontID()
+          };
+        }
+
+        if (fontRefIsRef) {
+          fontAliases[hash].aliasRef = fontRef;
+        }
+
+        fontID = fontAliases[hash].fontID;
+      }
+
+      if (fontRefIsRef) {
+        this.fontCache.put(fontRef, fontCapability.promise);
+      } else {
+        if (!fontID) {
+          fontID = this.idFactory.createObjId();
+        }
+
+        this.fontCache.put("id_".concat(fontID), fontCapability.promise);
+      }
+
+      (0, _util.assert)(fontID, 'The "fontID" must be defined.');
+      font.loadedName = "".concat(this.idFactory.getDocId(), "_f").concat(fontID);
+      font.translated = fontCapability.promise;
+      var translatedPromise;
+
+      try {
+        translatedPromise = this.translateFont(preEvaluatedFont);
+      } catch (e) {
+        translatedPromise = Promise.reject(e);
+      }
+
+      translatedPromise.then(function (translatedFont) {
+        if (translatedFont.fontType !== undefined) {
+          var xrefFontStats = xref.stats.fontTypes;
+          xrefFontStats[translatedFont.fontType] = true;
+        }
+
+        fontCapability.resolve(new TranslatedFont(font.loadedName, translatedFont, font));
+      })["catch"](function (reason) {
+        _this6.handler.send('UnsupportedFeature', {
+          featureId: _util.UNSUPPORTED_FEATURES.font
+        });
+
+        try {
+          var fontFile3 = descriptor && descriptor.get('FontFile3');
+          var subtype = fontFile3 && fontFile3.get('Subtype');
+          var fontType = (0, _fonts.getFontType)(preEvaluatedFont.type, subtype && subtype.name);
+          var xrefFontStats = xref.stats.fontTypes;
+          xrefFontStats[fontType] = true;
+        } catch (ex) {}
+
+        fontCapability.resolve(new TranslatedFont(font.loadedName, new _fonts.ErrorFont(reason instanceof Error ? reason.message : reason), font));
+      });
+      return fontCapability.promise;
+    },
+    buildPath: function buildPath(operatorList, fn, args) {
+      var parsingText = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+      var lastIndex = operatorList.length - 1;
+
+      if (!args) {
+        args = [];
+      }
+
+      if (lastIndex < 0 || operatorList.fnArray[lastIndex] !== _util.OPS.constructPath) {
+        if (parsingText) {
+          (0, _util.warn)("Encountered path operator \"".concat(fn, "\" inside of a text object."));
+          operatorList.addOp(_util.OPS.save, null);
+        }
+
+        operatorList.addOp(_util.OPS.constructPath, [[fn], args]);
+
+        if (parsingText) {
+          operatorList.addOp(_util.OPS.restore, null);
+        }
+      } else {
+        var opArgs = operatorList.argsArray[lastIndex];
+        opArgs[0].push(fn);
+        Array.prototype.push.apply(opArgs[1], args);
+      }
+    },
+    handleColorN: function () {
+      var _handleColorN = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee3(operatorList, fn, args, cs, patterns, resources, task) {
+        var patternName, pattern, dict, typeNum, color, shading, matrix;
+        return _regenerator["default"].wrap(function _callee3$(_context3) {
+          while (1) {
+            switch (_context3.prev = _context3.next) {
+              case 0:
+                patternName = args[args.length - 1];
+
+                if (!((0, _primitives.isName)(patternName) && (pattern = patterns.get(patternName.name)))) {
+                  _context3.next = 16;
+                  break;
+                }
+
+                dict = (0, _primitives.isStream)(pattern) ? pattern.dict : pattern;
+                typeNum = dict.get('PatternType');
+
+                if (!(typeNum === TILING_PATTERN)) {
+                  _context3.next = 9;
+                  break;
+                }
+
+                color = cs.base ? cs.base.getRgb(args, 0) : null;
+                return _context3.abrupt("return", this.handleTilingType(fn, color, resources, pattern, dict, operatorList, task));
+
+              case 9:
+                if (!(typeNum === SHADING_PATTERN)) {
+                  _context3.next = 15;
+                  break;
+                }
+
+                shading = dict.get('Shading');
+                matrix = dict.getArray('Matrix');
+                pattern = _pattern.Pattern.parseShading(shading, matrix, this.xref, resources, this.handler, this.pdfFunctionFactory);
+                operatorList.addOp(fn, pattern.getIR());
+                return _context3.abrupt("return", undefined);
+
+              case 15:
+                throw new _util.FormatError("Unknown PatternType: ".concat(typeNum));
+
+              case 16:
+                throw new _util.FormatError("Unknown PatternName: ".concat(patternName));
+
+              case 17:
+              case "end":
+                return _context3.stop();
+            }
+          }
+        }, _callee3, this);
+      }));
+
+      function handleColorN(_x3, _x4, _x5, _x6, _x7, _x8, _x9) {
+        return _handleColorN.apply(this, arguments);
+      }
+
+      return handleColorN;
+    }(),
+    getOperatorList: function getOperatorList(_ref4) {
+      var _this7 = this;
+
+      var stream = _ref4.stream,
+          task = _ref4.task,
+          resources = _ref4.resources,
+          operatorList = _ref4.operatorList,
+          _ref4$initialState = _ref4.initialState,
+          initialState = _ref4$initialState === void 0 ? null : _ref4$initialState;
+      resources = resources || _primitives.Dict.empty;
+      initialState = initialState || new EvalState();
+
+      if (!operatorList) {
+        throw new Error('getOperatorList: missing "operatorList" parameter');
+      }
+
+      var self = this;
+      var xref = this.xref;
+      var parsingText = false;
+      var imageCache = Object.create(null);
+
+      var xobjs = resources.get('XObject') || _primitives.Dict.empty;
+
+      var patterns = resources.get('Pattern') || _primitives.Dict.empty;
+
+      var stateManager = new StateManager(initialState);
+      var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
+      var timeSlotManager = new TimeSlotManager();
+
+      function closePendingRestoreOPS(argument) {
+        for (var i = 0, ii = preprocessor.savedStatesDepth; i < ii; i++) {
+          operatorList.addOp(_util.OPS.restore, []);
+        }
+      }
+
+      return new Promise(function promiseBody(resolve, reject) {
+        var next = function next(promise) {
+          promise.then(function () {
+            try {
+              promiseBody(resolve, reject);
+            } catch (ex) {
+              reject(ex);
+            }
+          }, reject);
+        };
+
+        task.ensureNotTerminated();
+        timeSlotManager.reset();
+        var stop,
+            operation = {},
+            i,
+            ii,
+            cs;
+
+        while (!(stop = timeSlotManager.check())) {
+          operation.args = null;
+
+          if (!preprocessor.read(operation)) {
+            break;
+          }
+
+          var args = operation.args;
+          var fn = operation.fn;
+
+          switch (fn | 0) {
+            case _util.OPS.paintXObject:
+              var name = args[0].name;
+
+              if (name && imageCache[name] !== undefined) {
+                operatorList.addOp(imageCache[name].fn, imageCache[name].args);
+                args = null;
+                continue;
+              }
+
+              next(new Promise(function (resolveXObject, rejectXObject) {
+                if (!name) {
+                  throw new _util.FormatError('XObject must be referred to by name.');
+                }
+
+                var xobj = xobjs.get(name);
+
+                if (!xobj) {
+                  operatorList.addOp(fn, args);
+                  resolveXObject();
+                  return;
+                }
+
+                if (!(0, _primitives.isStream)(xobj)) {
+                  throw new _util.FormatError('XObject should be a stream');
+                }
+
+                var type = xobj.dict.get('Subtype');
+
+                if (!(0, _primitives.isName)(type)) {
+                  throw new _util.FormatError('XObject should have a Name subtype');
+                }
+
+                if (type.name === 'Form') {
+                  stateManager.save();
+                  self.buildFormXObject(resources, xobj, null, operatorList, task, stateManager.state.clone()).then(function () {
+                    stateManager.restore();
+                    resolveXObject();
+                  }, rejectXObject);
+                  return;
+                } else if (type.name === 'Image') {
+                  self.buildPaintImageXObject({
+                    resources: resources,
+                    image: xobj,
+                    operatorList: operatorList,
+                    cacheKey: name,
+                    imageCache: imageCache
+                  }).then(resolveXObject, rejectXObject);
+                  return;
+                } else if (type.name === 'PS') {
+                  (0, _util.info)('Ignored XObject subtype PS');
+                } else {
+                  throw new _util.FormatError("Unhandled XObject subtype ".concat(type.name));
+                }
+
+                resolveXObject();
+              })["catch"](function (reason) {
+                if (self.options.ignoreErrors) {
+                  self.handler.send('UnsupportedFeature', {
+                    featureId: _util.UNSUPPORTED_FEATURES.unknown
+                  });
+                  (0, _util.warn)("getOperatorList - ignoring XObject: \"".concat(reason, "\"."));
+                  return;
+                }
+
+                throw reason;
+              }));
+              return;
+
+            case _util.OPS.setFont:
+              var fontSize = args[1];
+              next(self.handleSetFont(resources, args, null, operatorList, task, stateManager.state).then(function (loadedName) {
+                operatorList.addDependency(loadedName);
+                operatorList.addOp(_util.OPS.setFont, [loadedName, fontSize]);
+              }));
+              return;
+
+            case _util.OPS.beginText:
+              parsingText = true;
+              break;
+
+            case _util.OPS.endText:
+              parsingText = false;
+              break;
+
+            case _util.OPS.endInlineImage:
+              var cacheKey = args[0].cacheKey;
+
+              if (cacheKey) {
+                var cacheEntry = imageCache[cacheKey];
+
+                if (cacheEntry !== undefined) {
+                  operatorList.addOp(cacheEntry.fn, cacheEntry.args);
+                  args = null;
+                  continue;
+                }
+              }
+
+              next(self.buildPaintImageXObject({
+                resources: resources,
+                image: args[0],
+                isInline: true,
+                operatorList: operatorList,
+                cacheKey: cacheKey,
+                imageCache: imageCache
+              }));
+              return;
+
+            case _util.OPS.showText:
+              args[0] = self.handleText(args[0], stateManager.state);
+              break;
+
+            case _util.OPS.showSpacedText:
+              var arr = args[0];
+              var combinedGlyphs = [];
+              var arrLength = arr.length;
+              var state = stateManager.state;
+
+              for (i = 0; i < arrLength; ++i) {
+                var arrItem = arr[i];
+
+                if ((0, _util.isString)(arrItem)) {
+                  Array.prototype.push.apply(combinedGlyphs, self.handleText(arrItem, state));
+                } else if ((0, _util.isNum)(arrItem)) {
+                  combinedGlyphs.push(arrItem);
+                }
+              }
+
+              args[0] = combinedGlyphs;
+              fn = _util.OPS.showText;
+              break;
+
+            case _util.OPS.nextLineShowText:
+              operatorList.addOp(_util.OPS.nextLine);
+              args[0] = self.handleText(args[0], stateManager.state);
+              fn = _util.OPS.showText;
+              break;
+
+            case _util.OPS.nextLineSetSpacingShowText:
+              operatorList.addOp(_util.OPS.nextLine);
+              operatorList.addOp(_util.OPS.setWordSpacing, [args.shift()]);
+              operatorList.addOp(_util.OPS.setCharSpacing, [args.shift()]);
+              args[0] = self.handleText(args[0], stateManager.state);
+              fn = _util.OPS.showText;
+              break;
+
+            case _util.OPS.setTextRenderingMode:
+              stateManager.state.textRenderingMode = args[0];
+              break;
+
+            case _util.OPS.setFillColorSpace:
+              stateManager.state.fillColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory);
+              continue;
+
+            case _util.OPS.setStrokeColorSpace:
+              stateManager.state.strokeColorSpace = _colorspace.ColorSpace.parse(args[0], xref, resources, self.pdfFunctionFactory);
+              continue;
+
+            case _util.OPS.setFillColor:
+              cs = stateManager.state.fillColorSpace;
+              args = cs.getRgb(args, 0);
+              fn = _util.OPS.setFillRGBColor;
+              break;
+
+            case _util.OPS.setStrokeColor:
+              cs = stateManager.state.strokeColorSpace;
+              args = cs.getRgb(args, 0);
+              fn = _util.OPS.setStrokeRGBColor;
+              break;
+
+            case _util.OPS.setFillGray:
+              stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.gray;
+              args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0);
+              fn = _util.OPS.setFillRGBColor;
+              break;
+
+            case _util.OPS.setStrokeGray:
+              stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.gray;
+              args = _colorspace.ColorSpace.singletons.gray.getRgb(args, 0);
+              fn = _util.OPS.setStrokeRGBColor;
+              break;
+
+            case _util.OPS.setFillCMYKColor:
+              stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.cmyk;
+              args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0);
+              fn = _util.OPS.setFillRGBColor;
+              break;
+
+            case _util.OPS.setStrokeCMYKColor:
+              stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.cmyk;
+              args = _colorspace.ColorSpace.singletons.cmyk.getRgb(args, 0);
+              fn = _util.OPS.setStrokeRGBColor;
+              break;
+
+            case _util.OPS.setFillRGBColor:
+              stateManager.state.fillColorSpace = _colorspace.ColorSpace.singletons.rgb;
+              args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0);
+              break;
+
+            case _util.OPS.setStrokeRGBColor:
+              stateManager.state.strokeColorSpace = _colorspace.ColorSpace.singletons.rgb;
+              args = _colorspace.ColorSpace.singletons.rgb.getRgb(args, 0);
+              break;
+
+            case _util.OPS.setFillColorN:
+              cs = stateManager.state.fillColorSpace;
+
+              if (cs.name === 'Pattern') {
+                next(self.handleColorN(operatorList, _util.OPS.setFillColorN, args, cs, patterns, resources, task));
+                return;
+              }
+
+              args = cs.getRgb(args, 0);
+              fn = _util.OPS.setFillRGBColor;
+              break;
+
+            case _util.OPS.setStrokeColorN:
+              cs = stateManager.state.strokeColorSpace;
+
+              if (cs.name === 'Pattern') {
+                next(self.handleColorN(operatorList, _util.OPS.setStrokeColorN, args, cs, patterns, resources, task));
+                return;
+              }
+
+              args = cs.getRgb(args, 0);
+              fn = _util.OPS.setStrokeRGBColor;
+              break;
+
+            case _util.OPS.shadingFill:
+              var shadingRes = resources.get('Shading');
+
+              if (!shadingRes) {
+                throw new _util.FormatError('No shading resource found');
+              }
+
+              var shading = shadingRes.get(args[0].name);
+
+              if (!shading) {
+                throw new _util.FormatError('No shading object found');
+              }
+
+              var shadingFill = _pattern.Pattern.parseShading(shading, null, xref, resources, self.handler, self.pdfFunctionFactory);
+
+              var patternIR = shadingFill.getIR();
+              args = [patternIR];
+              fn = _util.OPS.shadingFill;
+              break;
+
+            case _util.OPS.setGState:
+              var dictName = args[0];
+              var extGState = resources.get('ExtGState');
+
+              if (!(0, _primitives.isDict)(extGState) || !extGState.has(dictName.name)) {
+                break;
+              }
+
+              var gState = extGState.get(dictName.name);
+              next(self.setGState(resources, gState, operatorList, task, stateManager));
+              return;
+
+            case _util.OPS.moveTo:
+            case _util.OPS.lineTo:
+            case _util.OPS.curveTo:
+            case _util.OPS.curveTo2:
+            case _util.OPS.curveTo3:
+            case _util.OPS.closePath:
+            case _util.OPS.rectangle:
+              self.buildPath(operatorList, fn, args, parsingText);
+              continue;
+
+            case _util.OPS.markPoint:
+            case _util.OPS.markPointProps:
+            case _util.OPS.beginMarkedContent:
+            case _util.OPS.beginMarkedContentProps:
+            case _util.OPS.endMarkedContent:
+            case _util.OPS.beginCompat:
+            case _util.OPS.endCompat:
+              continue;
+
+            default:
+              if (args !== null) {
+                for (i = 0, ii = args.length; i < ii; i++) {
+                  if (args[i] instanceof _primitives.Dict) {
+                    break;
+                  }
+                }
+
+                if (i < ii) {
+                  (0, _util.warn)('getOperatorList - ignoring operator: ' + fn);
+                  continue;
+                }
+              }
+
+          }
+
+          operatorList.addOp(fn, args);
+        }
+
+        if (stop) {
+          next(deferred);
+          return;
+        }
+
+        closePendingRestoreOPS();
+        resolve();
+      })["catch"](function (reason) {
+        if (_this7.options.ignoreErrors) {
+          _this7.handler.send('UnsupportedFeature', {
+            featureId: _util.UNSUPPORTED_FEATURES.unknown
+          });
+
+          (0, _util.warn)("getOperatorList - ignoring errors during \"".concat(task.name, "\" ") + "task: \"".concat(reason, "\"."));
+          closePendingRestoreOPS();
+          return;
+        }
+
+        throw reason;
+      });
+    },
+    getTextContent: function getTextContent(_ref5) {
+      var _this8 = this;
+
+      var stream = _ref5.stream,
+          task = _ref5.task,
+          resources = _ref5.resources,
+          _ref5$stateManager = _ref5.stateManager,
+          stateManager = _ref5$stateManager === void 0 ? null : _ref5$stateManager,
+          _ref5$normalizeWhites = _ref5.normalizeWhitespace,
+          normalizeWhitespace = _ref5$normalizeWhites === void 0 ? false : _ref5$normalizeWhites,
+          _ref5$combineTextItem = _ref5.combineTextItems,
+          combineTextItems = _ref5$combineTextItem === void 0 ? false : _ref5$combineTextItem,
+          sink = _ref5.sink,
+          _ref5$seenStyles = _ref5.seenStyles,
+          seenStyles = _ref5$seenStyles === void 0 ? Object.create(null) : _ref5$seenStyles;
+      resources = resources || _primitives.Dict.empty;
+      stateManager = stateManager || new StateManager(new TextState());
+      var WhitespaceRegexp = /\s/g;
+      var textContent = {
+        items: [],
+        styles: Object.create(null)
+      };
+      var textContentItem = {
+        initialized: false,
+        str: [],
+        width: 0,
+        height: 0,
+        vertical: false,
+        lastAdvanceWidth: 0,
+        lastAdvanceHeight: 0,
+        textAdvanceScale: 0,
+        spaceWidth: 0,
+        fakeSpaceMin: Infinity,
+        fakeMultiSpaceMin: Infinity,
+        fakeMultiSpaceMax: -0,
+        textRunBreakAllowed: false,
+        transform: null,
+        fontName: null
+      };
+      var SPACE_FACTOR = 0.3;
+      var MULTI_SPACE_FACTOR = 1.5;
+      var MULTI_SPACE_FACTOR_MAX = 4;
+      var self = this;
+      var xref = this.xref;
+      var xobjs = null;
+      var skipEmptyXObjs = Object.create(null);
+      var preprocessor = new EvaluatorPreprocessor(stream, xref, stateManager);
+      var textState;
+
+      function ensureTextContentItem() {
+        if (textContentItem.initialized) {
+          return textContentItem;
+        }
+
+        var font = textState.font;
+
+        if (!(font.loadedName in seenStyles)) {
+          seenStyles[font.loadedName] = true;
+          textContent.styles[font.loadedName] = {
+            fontFamily: font.fallbackName,
+            ascent: font.ascent,
+            descent: font.descent,
+            vertical: !!font.vertical
+          };
+        }
+
+        textContentItem.fontName = font.loadedName;
+        var tsm = [textState.fontSize * textState.textHScale, 0, 0, textState.fontSize, 0, textState.textRise];
+
+        if (font.isType3Font && textState.fontSize <= 1 && !(0, _util.isArrayEqual)(textState.fontMatrix, _util.FONT_IDENTITY_MATRIX)) {
+          var glyphHeight = font.bbox[3] - font.bbox[1];
+
+          if (glyphHeight > 0) {
+            tsm[3] *= glyphHeight * textState.fontMatrix[3];
+          }
+        }
+
+        var trm = _util.Util.transform(textState.ctm, _util.Util.transform(textState.textMatrix, tsm));
+
+        textContentItem.transform = trm;
+
+        if (!font.vertical) {
+          textContentItem.width = 0;
+          textContentItem.height = Math.sqrt(trm[2] * trm[2] + trm[3] * trm[3]);
+          textContentItem.vertical = false;
+        } else {
+          textContentItem.width = Math.sqrt(trm[0] * trm[0] + trm[1] * trm[1]);
+          textContentItem.height = 0;
+          textContentItem.vertical = true;
+        }
+
+        var a = textState.textLineMatrix[0];
+        var b = textState.textLineMatrix[1];
+        var scaleLineX = Math.sqrt(a * a + b * b);
+        a = textState.ctm[0];
+        b = textState.ctm[1];
+        var scaleCtmX = Math.sqrt(a * a + b * b);
+        textContentItem.textAdvanceScale = scaleCtmX * scaleLineX;
+        textContentItem.lastAdvanceWidth = 0;
+        textContentItem.lastAdvanceHeight = 0;
+        var spaceWidth = font.spaceWidth / 1000 * textState.fontSize;
+
+        if (spaceWidth) {
+          textContentItem.spaceWidth = spaceWidth;
+          textContentItem.fakeSpaceMin = spaceWidth * SPACE_FACTOR;
+          textContentItem.fakeMultiSpaceMin = spaceWidth * MULTI_SPACE_FACTOR;
+          textContentItem.fakeMultiSpaceMax = spaceWidth * MULTI_SPACE_FACTOR_MAX;
+          textContentItem.textRunBreakAllowed = !font.isMonospace;
+        } else {
+          textContentItem.spaceWidth = 0;
+          textContentItem.fakeSpaceMin = Infinity;
+          textContentItem.fakeMultiSpaceMin = Infinity;
+          textContentItem.fakeMultiSpaceMax = 0;
+          textContentItem.textRunBreakAllowed = false;
+        }
+
+        textContentItem.initialized = true;
+        return textContentItem;
+      }
+
+      function replaceWhitespace(str) {
+        var i = 0,
+            ii = str.length,
+            code;
+
+        while (i < ii && (code = str.charCodeAt(i)) >= 0x20 && code <= 0x7F) {
+          i++;
+        }
+
+        return i < ii ? str.replace(WhitespaceRegexp, ' ') : str;
+      }
+
+      function runBidiTransform(textChunk) {
+        var str = textChunk.str.join('');
+        var bidiResult = (0, _bidi.bidi)(str, -1, textChunk.vertical);
+        return {
+          str: normalizeWhitespace ? replaceWhitespace(bidiResult.str) : bidiResult.str,
+          dir: bidiResult.dir,
+          width: textChunk.width,
+          height: textChunk.height,
+          transform: textChunk.transform,
+          fontName: textChunk.fontName
+        };
+      }
+
+      function handleSetFont(fontName, fontRef) {
+        return self.loadFont(fontName, fontRef, resources).then(function (translated) {
+          textState.font = translated.font;
+          textState.fontMatrix = translated.font.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+        });
+      }
+
+      function buildTextContentItem(chars) {
+        var font = textState.font;
+        var textChunk = ensureTextContentItem();
+        var width = 0;
+        var height = 0;
+        var glyphs = font.charsToGlyphs(chars);
+
+        for (var i = 0; i < glyphs.length; i++) {
+          var glyph = glyphs[i];
+          var glyphWidth = null;
+
+          if (font.vertical && glyph.vmetric) {
+            glyphWidth = glyph.vmetric[0];
+          } else {
+            glyphWidth = glyph.width;
+          }
+
+          var glyphUnicode = glyph.unicode;
+          var NormalizedUnicodes = (0, _unicode.getNormalizedUnicodes)();
+
+          if (NormalizedUnicodes[glyphUnicode] !== undefined) {
+            glyphUnicode = NormalizedUnicodes[glyphUnicode];
+          }
+
+          glyphUnicode = (0, _unicode.reverseIfRtl)(glyphUnicode);
+          var charSpacing = textState.charSpacing;
+
+          if (glyph.isSpace) {
+            var wordSpacing = textState.wordSpacing;
+            charSpacing += wordSpacing;
+
+            if (wordSpacing > 0) {
+              addFakeSpaces(wordSpacing, textChunk.str);
+            }
+          }
+
+          var tx = 0;
+          var ty = 0;
+
+          if (!font.vertical) {
+            var w0 = glyphWidth * textState.fontMatrix[0];
+            tx = (w0 * textState.fontSize + charSpacing) * textState.textHScale;
+            width += tx;
+          } else {
+            var w1 = glyphWidth * textState.fontMatrix[0];
+            ty = w1 * textState.fontSize + charSpacing;
+            height += ty;
+          }
+
+          textState.translateTextMatrix(tx, ty);
+          textChunk.str.push(glyphUnicode);
+        }
+
+        if (!font.vertical) {
+          textChunk.lastAdvanceWidth = width;
+          textChunk.width += width;
+        } else {
+          textChunk.lastAdvanceHeight = height;
+          textChunk.height += Math.abs(height);
+        }
+
+        return textChunk;
+      }
+
+      function addFakeSpaces(width, strBuf) {
+        if (width < textContentItem.fakeSpaceMin) {
+          return;
+        }
+
+        if (width < textContentItem.fakeMultiSpaceMin) {
+          strBuf.push(' ');
+          return;
+        }
+
+        var fakeSpaces = Math.round(width / textContentItem.spaceWidth);
+
+        while (fakeSpaces-- > 0) {
+          strBuf.push(' ');
+        }
+      }
+
+      function flushTextContentItem() {
+        if (!textContentItem.initialized) {
+          return;
+        }
+
+        if (!textContentItem.vertical) {
+          textContentItem.width *= textContentItem.textAdvanceScale;
+        } else {
+          textContentItem.height *= textContentItem.textAdvanceScale;
+        }
+
+        textContent.items.push(runBidiTransform(textContentItem));
+        textContentItem.initialized = false;
+        textContentItem.str.length = 0;
+      }
+
+      function enqueueChunk() {
+        var length = textContent.items.length;
+
+        if (length > 0) {
+          sink.enqueue(textContent, length);
+          textContent.items = [];
+          textContent.styles = Object.create(null);
+        }
+      }
+
+      var timeSlotManager = new TimeSlotManager();
+      return new Promise(function promiseBody(resolve, reject) {
+        var next = function next(promise) {
+          enqueueChunk();
+          Promise.all([promise, sink.ready]).then(function () {
+            try {
+              promiseBody(resolve, reject);
+            } catch (ex) {
+              reject(ex);
+            }
+          }, reject);
+        };
+
+        task.ensureNotTerminated();
+        timeSlotManager.reset();
+        var stop,
+            operation = {},
+            args = [];
+
+        while (!(stop = timeSlotManager.check())) {
+          args.length = 0;
+          operation.args = args;
+
+          if (!preprocessor.read(operation)) {
+            break;
+          }
+
+          textState = stateManager.state;
+          var fn = operation.fn;
+          args = operation.args;
+          var advance, diff;
+
+          switch (fn | 0) {
+            case _util.OPS.setFont:
+              var fontNameArg = args[0].name,
+                  fontSizeArg = args[1];
+
+              if (textState.font && fontNameArg === textState.fontName && fontSizeArg === textState.fontSize) {
+                break;
+              }
+
+              flushTextContentItem();
+              textState.fontName = fontNameArg;
+              textState.fontSize = fontSizeArg;
+              next(handleSetFont(fontNameArg, null));
+              return;
+
+            case _util.OPS.setTextRise:
+              flushTextContentItem();
+              textState.textRise = args[0];
+              break;
+
+            case _util.OPS.setHScale:
+              flushTextContentItem();
+              textState.textHScale = args[0] / 100;
+              break;
+
+            case _util.OPS.setLeading:
+              flushTextContentItem();
+              textState.leading = args[0];
+              break;
+
+            case _util.OPS.moveText:
+              var isSameTextLine = !textState.font ? false : (textState.font.vertical ? args[0] : args[1]) === 0;
+              advance = args[0] - args[1];
+
+              if (combineTextItems && isSameTextLine && textContentItem.initialized && advance > 0 && advance <= textContentItem.fakeMultiSpaceMax) {
+                textState.translateTextLineMatrix(args[0], args[1]);
+                textContentItem.width += args[0] - textContentItem.lastAdvanceWidth;
+                textContentItem.height += args[1] - textContentItem.lastAdvanceHeight;
+                diff = args[0] - textContentItem.lastAdvanceWidth - (args[1] - textContentItem.lastAdvanceHeight);
+                addFakeSpaces(diff, textContentItem.str);
+                break;
+              }
+
+              flushTextContentItem();
+              textState.translateTextLineMatrix(args[0], args[1]);
+              textState.textMatrix = textState.textLineMatrix.slice();
+              break;
+
+            case _util.OPS.setLeadingMoveText:
+              flushTextContentItem();
+              textState.leading = -args[1];
+              textState.translateTextLineMatrix(args[0], args[1]);
+              textState.textMatrix = textState.textLineMatrix.slice();
+              break;
+
+            case _util.OPS.nextLine:
+              flushTextContentItem();
+              textState.carriageReturn();
+              break;
+
+            case _util.OPS.setTextMatrix:
+              advance = textState.calcTextLineMatrixAdvance(args[0], args[1], args[2], args[3], args[4], args[5]);
+
+              if (combineTextItems && advance !== null && textContentItem.initialized && advance.value > 0 && advance.value <= textContentItem.fakeMultiSpaceMax) {
+                textState.translateTextLineMatrix(advance.width, advance.height);
+                textContentItem.width += advance.width - textContentItem.lastAdvanceWidth;
+                textContentItem.height += advance.height - textContentItem.lastAdvanceHeight;
+                diff = advance.width - textContentItem.lastAdvanceWidth - (advance.height - textContentItem.lastAdvanceHeight);
+                addFakeSpaces(diff, textContentItem.str);
+                break;
+              }
+
+              flushTextContentItem();
+              textState.setTextMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+              textState.setTextLineMatrix(args[0], args[1], args[2], args[3], args[4], args[5]);
+              break;
+
+            case _util.OPS.setCharSpacing:
+              textState.charSpacing = args[0];
+              break;
+
+            case _util.OPS.setWordSpacing:
+              textState.wordSpacing = args[0];
+              break;
+
+            case _util.OPS.beginText:
+              flushTextContentItem();
+              textState.textMatrix = _util.IDENTITY_MATRIX.slice();
+              textState.textLineMatrix = _util.IDENTITY_MATRIX.slice();
+              break;
+
+            case _util.OPS.showSpacedText:
+              var items = args[0];
+              var offset;
+
+              for (var j = 0, jj = items.length; j < jj; j++) {
+                if (typeof items[j] === 'string') {
+                  buildTextContentItem(items[j]);
+                } else if ((0, _util.isNum)(items[j])) {
+                  ensureTextContentItem();
+                  advance = items[j] * textState.fontSize / 1000;
+                  var breakTextRun = false;
+
+                  if (textState.font.vertical) {
+                    offset = advance;
+                    textState.translateTextMatrix(0, offset);
+                    breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
+
+                    if (!breakTextRun) {
+                      textContentItem.height += offset;
+                    }
+                  } else {
+                    advance = -advance;
+                    offset = advance * textState.textHScale;
+                    textState.translateTextMatrix(offset, 0);
+                    breakTextRun = textContentItem.textRunBreakAllowed && advance > textContentItem.fakeMultiSpaceMax;
+
+                    if (!breakTextRun) {
+                      textContentItem.width += offset;
+                    }
+                  }
+
+                  if (breakTextRun) {
+                    flushTextContentItem();
+                  } else if (advance > 0) {
+                    addFakeSpaces(advance, textContentItem.str);
+                  }
+                }
+              }
+
+              break;
+
+            case _util.OPS.showText:
+              buildTextContentItem(args[0]);
+              break;
+
+            case _util.OPS.nextLineShowText:
+              flushTextContentItem();
+              textState.carriageReturn();
+              buildTextContentItem(args[0]);
+              break;
+
+            case _util.OPS.nextLineSetSpacingShowText:
+              flushTextContentItem();
+              textState.wordSpacing = args[0];
+              textState.charSpacing = args[1];
+              textState.carriageReturn();
+              buildTextContentItem(args[2]);
+              break;
+
+            case _util.OPS.paintXObject:
+              flushTextContentItem();
+
+              if (!xobjs) {
+                xobjs = resources.get('XObject') || _primitives.Dict.empty;
+              }
+
+              var name = args[0].name;
+
+              if (name && skipEmptyXObjs[name] !== undefined) {
+                break;
+              }
+
+              next(new Promise(function (resolveXObject, rejectXObject) {
+                if (!name) {
+                  throw new _util.FormatError('XObject must be referred to by name.');
+                }
+
+                var xobj = xobjs.get(name);
+
+                if (!xobj) {
+                  resolveXObject();
+                  return;
+                }
+
+                if (!(0, _primitives.isStream)(xobj)) {
+                  throw new _util.FormatError('XObject should be a stream');
+                }
+
+                var type = xobj.dict.get('Subtype');
+
+                if (!(0, _primitives.isName)(type)) {
+                  throw new _util.FormatError('XObject should have a Name subtype');
+                }
+
+                if (type.name !== 'Form') {
+                  skipEmptyXObjs[name] = true;
+                  resolveXObject();
+                  return;
+                }
+
+                var currentState = stateManager.state.clone();
+                var xObjStateManager = new StateManager(currentState);
+                var matrix = xobj.dict.getArray('Matrix');
+
+                if (Array.isArray(matrix) && matrix.length === 6) {
+                  xObjStateManager.transform(matrix);
+                }
+
+                enqueueChunk();
+                var sinkWrapper = {
+                  enqueueInvoked: false,
+                  enqueue: function enqueue(chunk, size) {
+                    this.enqueueInvoked = true;
+                    sink.enqueue(chunk, size);
+                  },
+
+                  get desiredSize() {
+                    return sink.desiredSize;
+                  },
+
+                  get ready() {
+                    return sink.ready;
+                  }
+
+                };
+                self.getTextContent({
+                  stream: xobj,
+                  task: task,
+                  resources: xobj.dict.get('Resources') || resources,
+                  stateManager: xObjStateManager,
+                  normalizeWhitespace: normalizeWhitespace,
+                  combineTextItems: combineTextItems,
+                  sink: sinkWrapper,
+                  seenStyles: seenStyles
+                }).then(function () {
+                  if (!sinkWrapper.enqueueInvoked) {
+                    skipEmptyXObjs[name] = true;
+                  }
+
+                  resolveXObject();
+                }, rejectXObject);
+              })["catch"](function (reason) {
+                if (reason instanceof _util.AbortException) {
+                  return;
+                }
+
+                if (self.options.ignoreErrors) {
+                  (0, _util.warn)("getTextContent - ignoring XObject: \"".concat(reason, "\"."));
+                  return;
+                }
+
+                throw reason;
+              }));
+              return;
+
+            case _util.OPS.setGState:
+              flushTextContentItem();
+              var dictName = args[0];
+              var extGState = resources.get('ExtGState');
+
+              if (!(0, _primitives.isDict)(extGState) || !(0, _primitives.isName)(dictName)) {
+                break;
+              }
+
+              var gState = extGState.get(dictName.name);
+
+              if (!(0, _primitives.isDict)(gState)) {
+                break;
+              }
+
+              var gStateFont = gState.get('Font');
+
+              if (gStateFont) {
+                textState.fontName = null;
+                textState.fontSize = gStateFont[1];
+                next(handleSetFont(null, gStateFont[0]));
+                return;
+              }
+
+              break;
+          }
+
+          if (textContent.items.length >= sink.desiredSize) {
+            stop = true;
+            break;
+          }
+        }
+
+        if (stop) {
+          next(deferred);
+          return;
+        }
+
+        flushTextContentItem();
+        enqueueChunk();
+        resolve();
+      })["catch"](function (reason) {
+        if (reason instanceof _util.AbortException) {
+          return;
+        }
+
+        if (_this8.options.ignoreErrors) {
+          (0, _util.warn)("getTextContent - ignoring errors during \"".concat(task.name, "\" ") + "task: \"".concat(reason, "\"."));
+          flushTextContentItem();
+          enqueueChunk();
+          return;
+        }
+
+        throw reason;
+      });
+    },
+    extractDataStructures: function PartialEvaluator_extractDataStructures(dict, baseDict, properties) {
+      var _this9 = this;
+
+      var xref = this.xref,
+          cidToGidBytes;
+      var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
+      var toUnicodePromise = toUnicode ? this.readToUnicode(toUnicode) : Promise.resolve(undefined);
+
+      if (properties.composite) {
+        var cidSystemInfo = dict.get('CIDSystemInfo');
+
+        if ((0, _primitives.isDict)(cidSystemInfo)) {
+          properties.cidSystemInfo = {
+            registry: (0, _util.stringToPDFString)(cidSystemInfo.get('Registry')),
+            ordering: (0, _util.stringToPDFString)(cidSystemInfo.get('Ordering')),
+            supplement: cidSystemInfo.get('Supplement')
+          };
+        }
+
+        var cidToGidMap = dict.get('CIDToGIDMap');
+
+        if ((0, _primitives.isStream)(cidToGidMap)) {
+          cidToGidBytes = cidToGidMap.getBytes();
+        }
+      }
+
+      var differences = [];
+      var baseEncodingName = null;
+      var encoding;
+
+      if (dict.has('Encoding')) {
+        encoding = dict.get('Encoding');
+
+        if ((0, _primitives.isDict)(encoding)) {
+          baseEncodingName = encoding.get('BaseEncoding');
+          baseEncodingName = (0, _primitives.isName)(baseEncodingName) ? baseEncodingName.name : null;
+
+          if (encoding.has('Differences')) {
+            var diffEncoding = encoding.get('Differences');
+            var index = 0;
+
+            for (var j = 0, jj = diffEncoding.length; j < jj; j++) {
+              var data = xref.fetchIfRef(diffEncoding[j]);
+
+              if ((0, _util.isNum)(data)) {
+                index = data;
+              } else if ((0, _primitives.isName)(data)) {
+                differences[index++] = data.name;
+              } else {
+                throw new _util.FormatError("Invalid entry in 'Differences' array: ".concat(data));
+              }
+            }
+          }
+        } else if ((0, _primitives.isName)(encoding)) {
+          baseEncodingName = encoding.name;
+        } else {
+          throw new _util.FormatError('Encoding is not a Name nor a Dict');
+        }
+
+        if (baseEncodingName !== 'MacRomanEncoding' && baseEncodingName !== 'MacExpertEncoding' && baseEncodingName !== 'WinAnsiEncoding') {
+          baseEncodingName = null;
+        }
+      }
+
+      if (baseEncodingName) {
+        properties.defaultEncoding = (0, _encodings.getEncoding)(baseEncodingName).slice();
+      } else {
+        var isSymbolicFont = !!(properties.flags & _fonts.FontFlags.Symbolic);
+        var isNonsymbolicFont = !!(properties.flags & _fonts.FontFlags.Nonsymbolic);
+        encoding = _encodings.StandardEncoding;
+
+        if (properties.type === 'TrueType' && !isNonsymbolicFont) {
+          encoding = _encodings.WinAnsiEncoding;
+        }
+
+        if (isSymbolicFont) {
+          encoding = _encodings.MacRomanEncoding;
+
+          if (!properties.file) {
+            if (/Symbol/i.test(properties.name)) {
+              encoding = _encodings.SymbolSetEncoding;
+            } else if (/Dingbats/i.test(properties.name)) {
+              encoding = _encodings.ZapfDingbatsEncoding;
+            }
+          }
+        }
+
+        properties.defaultEncoding = encoding;
+      }
+
+      properties.differences = differences;
+      properties.baseEncodingName = baseEncodingName;
+      properties.hasEncoding = !!baseEncodingName || differences.length > 0;
+      properties.dict = dict;
+      return toUnicodePromise.then(function (toUnicode) {
+        properties.toUnicode = toUnicode;
+        return _this9.buildToUnicode(properties);
+      }).then(function (toUnicode) {
+        properties.toUnicode = toUnicode;
+
+        if (cidToGidBytes) {
+          properties.cidToGidMap = _this9.readCidToGidMap(cidToGidBytes, toUnicode);
+        }
+
+        return properties;
+      });
+    },
+    _buildSimpleFontToUnicode: function _buildSimpleFontToUnicode(properties) {
+      (0, _util.assert)(!properties.composite, 'Must be a simple font.');
+      var toUnicode = [],
+          charcode,
+          glyphName;
+      var encoding = properties.defaultEncoding.slice();
+      var baseEncodingName = properties.baseEncodingName;
+      var differences = properties.differences;
+
+      for (charcode in differences) {
+        glyphName = differences[charcode];
+
+        if (glyphName === '.notdef') {
+          continue;
+        }
+
+        encoding[charcode] = glyphName;
+      }
+
+      var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+
+      for (charcode in encoding) {
+        glyphName = encoding[charcode];
+
+        if (glyphName === '') {
+          continue;
+        } else if (glyphsUnicodeMap[glyphName] === undefined) {
+          var code = 0;
+
+          switch (glyphName[0]) {
+            case 'G':
+              if (glyphName.length === 3) {
+                code = parseInt(glyphName.substring(1), 16);
+              }
+
+              break;
+
+            case 'g':
+              if (glyphName.length === 5) {
+                code = parseInt(glyphName.substring(1), 16);
+              }
+
+              break;
+
+            case 'C':
+            case 'c':
+              if (glyphName.length >= 3) {
+                code = +glyphName.substring(1);
+              }
+
+              break;
+
+            default:
+              var unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
+
+              if (unicode !== -1) {
+                code = unicode;
+              }
+
+          }
+
+          if (code) {
+            if (baseEncodingName && code === +charcode) {
+              var baseEncoding = (0, _encodings.getEncoding)(baseEncodingName);
+
+              if (baseEncoding && (glyphName = baseEncoding[charcode])) {
+                toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
+                continue;
+              }
+            }
+
+            toUnicode[charcode] = String.fromCodePoint(code);
+          }
+
+          continue;
+        }
+
+        toUnicode[charcode] = String.fromCharCode(glyphsUnicodeMap[glyphName]);
+      }
+
+      return new _fonts.ToUnicodeMap(toUnicode);
+    },
+    buildToUnicode: function buildToUnicode(properties) {
+      properties.hasIncludedToUnicodeMap = !!properties.toUnicode && properties.toUnicode.length > 0;
+
+      if (properties.hasIncludedToUnicodeMap) {
+        if (!properties.composite && properties.hasEncoding) {
+          properties.fallbackToUnicode = this._buildSimpleFontToUnicode(properties);
+        }
+
+        return Promise.resolve(properties.toUnicode);
+      }
+
+      if (!properties.composite) {
+        return Promise.resolve(this._buildSimpleFontToUnicode(properties));
+      }
+
+      if (properties.composite && (properties.cMap.builtInCMap && !(properties.cMap instanceof _cmap.IdentityCMap) || properties.cidSystemInfo.registry === 'Adobe' && (properties.cidSystemInfo.ordering === 'GB1' || properties.cidSystemInfo.ordering === 'CNS1' || properties.cidSystemInfo.ordering === 'Japan1' || properties.cidSystemInfo.ordering === 'Korea1'))) {
+        var registry = properties.cidSystemInfo.registry;
+        var ordering = properties.cidSystemInfo.ordering;
+
+        var ucs2CMapName = _primitives.Name.get(registry + '-' + ordering + '-UCS2');
+
+        return _cmap.CMapFactory.create({
+          encoding: ucs2CMapName,
+          fetchBuiltInCMap: this.fetchBuiltInCMap,
+          useCMap: null
+        }).then(function (ucs2CMap) {
+          var cMap = properties.cMap;
+          var toUnicode = [];
+          cMap.forEach(function (charcode, cid) {
+            if (cid > 0xffff) {
+              throw new _util.FormatError('Max size of CID is 65,535');
+            }
+
+            var ucs2 = ucs2CMap.lookup(cid);
+
+            if (ucs2) {
+              toUnicode[charcode] = String.fromCharCode((ucs2.charCodeAt(0) << 8) + ucs2.charCodeAt(1));
+            }
+          });
+          return new _fonts.ToUnicodeMap(toUnicode);
+        });
+      }
+
+      return Promise.resolve(new _fonts.IdentityToUnicodeMap(properties.firstChar, properties.lastChar));
+    },
+    readToUnicode: function PartialEvaluator_readToUnicode(toUnicode) {
+      var cmapObj = toUnicode;
+
+      if ((0, _primitives.isName)(cmapObj)) {
+        return _cmap.CMapFactory.create({
+          encoding: cmapObj,
+          fetchBuiltInCMap: this.fetchBuiltInCMap,
+          useCMap: null
+        }).then(function (cmap) {
+          if (cmap instanceof _cmap.IdentityCMap) {
+            return new _fonts.IdentityToUnicodeMap(0, 0xFFFF);
+          }
+
+          return new _fonts.ToUnicodeMap(cmap.getMap());
+        });
+      } else if ((0, _primitives.isStream)(cmapObj)) {
+        return _cmap.CMapFactory.create({
+          encoding: cmapObj,
+          fetchBuiltInCMap: this.fetchBuiltInCMap,
+          useCMap: null
+        }).then(function (cmap) {
+          if (cmap instanceof _cmap.IdentityCMap) {
+            return new _fonts.IdentityToUnicodeMap(0, 0xFFFF);
+          }
+
+          var map = new Array(cmap.length);
+          cmap.forEach(function (charCode, token) {
+            var str = [];
+
+            for (var k = 0; k < token.length; k += 2) {
+              var w1 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
+
+              if ((w1 & 0xF800) !== 0xD800) {
+                str.push(w1);
+                continue;
+              }
+
+              k += 2;
+              var w2 = token.charCodeAt(k) << 8 | token.charCodeAt(k + 1);
+              str.push(((w1 & 0x3ff) << 10) + (w2 & 0x3ff) + 0x10000);
+            }
+
+            map[charCode] = String.fromCodePoint.apply(String, str);
+          });
+          return new _fonts.ToUnicodeMap(map);
+        });
+      }
+
+      return Promise.resolve(null);
+    },
+    readCidToGidMap: function readCidToGidMap(glyphsData, toUnicode) {
+      var result = [];
+
+      for (var j = 0, jj = glyphsData.length; j < jj; j++) {
+        var glyphID = glyphsData[j++] << 8 | glyphsData[j];
+        var code = j >> 1;
+
+        if (glyphID === 0 && !toUnicode.has(code)) {
+          continue;
+        }
+
+        result[code] = glyphID;
+      }
+
+      return result;
+    },
+    extractWidths: function PartialEvaluator_extractWidths(dict, descriptor, properties) {
+      var xref = this.xref;
+      var glyphsWidths = [];
+      var defaultWidth = 0;
+      var glyphsVMetrics = [];
+      var defaultVMetrics;
+      var i, ii, j, jj, start, code, widths;
+
+      if (properties.composite) {
+        defaultWidth = dict.has('DW') ? dict.get('DW') : 1000;
+        widths = dict.get('W');
+
+        if (widths) {
+          for (i = 0, ii = widths.length; i < ii; i++) {
+            start = xref.fetchIfRef(widths[i++]);
+            code = xref.fetchIfRef(widths[i]);
+
+            if (Array.isArray(code)) {
+              for (j = 0, jj = code.length; j < jj; j++) {
+                glyphsWidths[start++] = xref.fetchIfRef(code[j]);
+              }
+            } else {
+              var width = xref.fetchIfRef(widths[++i]);
+
+              for (j = start; j <= code; j++) {
+                glyphsWidths[j] = width;
+              }
+            }
+          }
+        }
+
+        if (properties.vertical) {
+          var vmetrics = dict.getArray('DW2') || [880, -1000];
+          defaultVMetrics = [vmetrics[1], defaultWidth * 0.5, vmetrics[0]];
+          vmetrics = dict.get('W2');
+
+          if (vmetrics) {
+            for (i = 0, ii = vmetrics.length; i < ii; i++) {
+              start = xref.fetchIfRef(vmetrics[i++]);
+              code = xref.fetchIfRef(vmetrics[i]);
+
+              if (Array.isArray(code)) {
+                for (j = 0, jj = code.length; j < jj; j++) {
+                  glyphsVMetrics[start++] = [xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j++]), xref.fetchIfRef(code[j])];
+                }
+              } else {
+                var vmetric = [xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i]), xref.fetchIfRef(vmetrics[++i])];
+
+                for (j = start; j <= code; j++) {
+                  glyphsVMetrics[j] = vmetric;
+                }
+              }
+            }
+          }
+        }
+      } else {
+        var firstChar = properties.firstChar;
+        widths = dict.get('Widths');
+
+        if (widths) {
+          j = firstChar;
+
+          for (i = 0, ii = widths.length; i < ii; i++) {
+            glyphsWidths[j++] = xref.fetchIfRef(widths[i]);
+          }
+
+          defaultWidth = parseFloat(descriptor.get('MissingWidth')) || 0;
+        } else {
+          var baseFontName = dict.get('BaseFont');
+
+          if ((0, _primitives.isName)(baseFontName)) {
+            var metrics = this.getBaseFontMetrics(baseFontName.name);
+            glyphsWidths = this.buildCharCodeToWidth(metrics.widths, properties);
+            defaultWidth = metrics.defaultWidth;
+          }
+        }
+      }
+
+      var isMonospace = true;
+      var firstWidth = defaultWidth;
+
+      for (var glyph in glyphsWidths) {
+        var glyphWidth = glyphsWidths[glyph];
+
+        if (!glyphWidth) {
+          continue;
+        }
+
+        if (!firstWidth) {
+          firstWidth = glyphWidth;
+          continue;
+        }
+
+        if (firstWidth !== glyphWidth) {
+          isMonospace = false;
+          break;
+        }
+      }
+
+      if (isMonospace) {
+        properties.flags |= _fonts.FontFlags.FixedPitch;
+      }
+
+      properties.defaultWidth = defaultWidth;
+      properties.widths = glyphsWidths;
+      properties.defaultVMetrics = defaultVMetrics;
+      properties.vmetrics = glyphsVMetrics;
+    },
+    isSerifFont: function PartialEvaluator_isSerifFont(baseFontName) {
+      var fontNameWoStyle = baseFontName.split('-')[0];
+      return fontNameWoStyle in (0, _standard_fonts.getSerifFonts)() || fontNameWoStyle.search(/serif/gi) !== -1;
+    },
+    getBaseFontMetrics: function PartialEvaluator_getBaseFontMetrics(name) {
+      var defaultWidth = 0;
+      var widths = [];
+      var monospace = false;
+      var stdFontMap = (0, _standard_fonts.getStdFontMap)();
+      var lookupName = stdFontMap[name] || name;
+      var Metrics = (0, _metrics.getMetrics)();
+
+      if (!(lookupName in Metrics)) {
+        if (this.isSerifFont(name)) {
+          lookupName = 'Times-Roman';
+        } else {
+          lookupName = 'Helvetica';
+        }
+      }
+
+      var glyphWidths = Metrics[lookupName];
+
+      if ((0, _util.isNum)(glyphWidths)) {
+        defaultWidth = glyphWidths;
+        monospace = true;
+      } else {
+        widths = glyphWidths();
+      }
+
+      return {
+        defaultWidth: defaultWidth,
+        monospace: monospace,
+        widths: widths
+      };
+    },
+    buildCharCodeToWidth: function PartialEvaluator_bulildCharCodeToWidth(widthsByGlyphName, properties) {
+      var widths = Object.create(null);
+      var differences = properties.differences;
+      var encoding = properties.defaultEncoding;
+
+      for (var charCode = 0; charCode < 256; charCode++) {
+        if (charCode in differences && widthsByGlyphName[differences[charCode]]) {
+          widths[charCode] = widthsByGlyphName[differences[charCode]];
+          continue;
+        }
+
+        if (charCode in encoding && widthsByGlyphName[encoding[charCode]]) {
+          widths[charCode] = widthsByGlyphName[encoding[charCode]];
+          continue;
+        }
+      }
+
+      return widths;
+    },
+    preEvaluateFont: function PartialEvaluator_preEvaluateFont(dict) {
+      var baseDict = dict;
+      var type = dict.get('Subtype');
+
+      if (!(0, _primitives.isName)(type)) {
+        throw new _util.FormatError('invalid font Subtype');
+      }
+
+      var composite = false;
+      var uint8array;
+
+      if (type.name === 'Type0') {
+        var df = dict.get('DescendantFonts');
+
+        if (!df) {
+          throw new _util.FormatError('Descendant fonts are not specified');
+        }
+
+        dict = Array.isArray(df) ? this.xref.fetchIfRef(df[0]) : df;
+        type = dict.get('Subtype');
+
+        if (!(0, _primitives.isName)(type)) {
+          throw new _util.FormatError('invalid font Subtype');
+        }
+
+        composite = true;
+      }
+
+      var descriptor = dict.get('FontDescriptor');
+
+      if (descriptor) {
+        var hash = new _murmurhash.MurmurHash3_64();
+        var encoding = baseDict.getRaw('Encoding');
+
+        if ((0, _primitives.isName)(encoding)) {
+          hash.update(encoding.name);
+        } else if ((0, _primitives.isRef)(encoding)) {
+          hash.update(encoding.toString());
+        } else if ((0, _primitives.isDict)(encoding)) {
+          var keys = encoding.getKeys();
+
+          for (var i = 0, ii = keys.length; i < ii; i++) {
+            var entry = encoding.getRaw(keys[i]);
+
+            if ((0, _primitives.isName)(entry)) {
+              hash.update(entry.name);
+            } else if ((0, _primitives.isRef)(entry)) {
+              hash.update(entry.toString());
+            } else if (Array.isArray(entry)) {
+              var diffLength = entry.length,
+                  diffBuf = new Array(diffLength);
+
+              for (var j = 0; j < diffLength; j++) {
+                var diffEntry = entry[j];
+
+                if ((0, _primitives.isName)(diffEntry)) {
+                  diffBuf[j] = diffEntry.name;
+                } else if ((0, _util.isNum)(diffEntry) || (0, _primitives.isRef)(diffEntry)) {
+                  diffBuf[j] = diffEntry.toString();
+                }
+              }
+
+              hash.update(diffBuf.join());
+            }
+          }
+        }
+
+        var firstChar = dict.get('FirstChar') || 0;
+        var lastChar = dict.get('LastChar') || (composite ? 0xFFFF : 0xFF);
+        hash.update("".concat(firstChar, "-").concat(lastChar));
+        var toUnicode = dict.get('ToUnicode') || baseDict.get('ToUnicode');
+
+        if ((0, _primitives.isStream)(toUnicode)) {
+          var stream = toUnicode.str || toUnicode;
+          uint8array = stream.buffer ? new Uint8Array(stream.buffer.buffer, 0, stream.bufferLength) : new Uint8Array(stream.bytes.buffer, stream.start, stream.end - stream.start);
+          hash.update(uint8array);
+        } else if ((0, _primitives.isName)(toUnicode)) {
+          hash.update(toUnicode.name);
+        }
+
+        var widths = dict.get('Widths') || baseDict.get('Widths');
+
+        if (widths) {
+          uint8array = new Uint8Array(new Uint32Array(widths).buffer);
+          hash.update(uint8array);
+        }
+      }
+
+      return {
+        descriptor: descriptor,
+        dict: dict,
+        baseDict: baseDict,
+        composite: composite,
+        type: type.name,
+        hash: hash ? hash.hexdigest() : ''
+      };
+    },
+    translateFont: function PartialEvaluator_translateFont(preEvaluatedFont) {
+      var _this10 = this;
+
+      var baseDict = preEvaluatedFont.baseDict;
+      var dict = preEvaluatedFont.dict;
+      var composite = preEvaluatedFont.composite;
+      var descriptor = preEvaluatedFont.descriptor;
+      var type = preEvaluatedFont.type;
+      var maxCharIndex = composite ? 0xFFFF : 0xFF;
+      var properties;
+
+      if (!descriptor) {
+        if (type === 'Type3') {
+          descriptor = new _primitives.Dict(null);
+          descriptor.set('FontName', _primitives.Name.get(type));
+          descriptor.set('FontBBox', dict.getArray('FontBBox'));
+        } else {
+          var baseFontName = dict.get('BaseFont');
+
+          if (!(0, _primitives.isName)(baseFontName)) {
+            throw new _util.FormatError('Base font is not specified');
+          }
+
+          baseFontName = baseFontName.name.replace(/[,_]/g, '-');
+          var metrics = this.getBaseFontMetrics(baseFontName);
+          var fontNameWoStyle = baseFontName.split('-')[0];
+          var flags = (this.isSerifFont(fontNameWoStyle) ? _fonts.FontFlags.Serif : 0) | (metrics.monospace ? _fonts.FontFlags.FixedPitch : 0) | ((0, _standard_fonts.getSymbolsFonts)()[fontNameWoStyle] ? _fonts.FontFlags.Symbolic : _fonts.FontFlags.Nonsymbolic);
+          properties = {
+            type: type,
+            name: baseFontName,
+            widths: metrics.widths,
+            defaultWidth: metrics.defaultWidth,
+            flags: flags,
+            firstChar: 0,
+            lastChar: maxCharIndex
+          };
+          return this.extractDataStructures(dict, dict, properties).then(function (properties) {
+            properties.widths = _this10.buildCharCodeToWidth(metrics.widths, properties);
+            return new _fonts.Font(baseFontName, null, properties);
+          });
+        }
+      }
+
+      var firstChar = dict.get('FirstChar') || 0;
+      var lastChar = dict.get('LastChar') || maxCharIndex;
+      var fontName = descriptor.get('FontName');
+      var baseFont = dict.get('BaseFont');
+
+      if ((0, _util.isString)(fontName)) {
+        fontName = _primitives.Name.get(fontName);
+      }
+
+      if ((0, _util.isString)(baseFont)) {
+        baseFont = _primitives.Name.get(baseFont);
+      }
+
+      if (type !== 'Type3') {
+        var fontNameStr = fontName && fontName.name;
+        var baseFontStr = baseFont && baseFont.name;
+
+        if (fontNameStr !== baseFontStr) {
+          (0, _util.info)("The FontDescriptor's FontName is \"".concat(fontNameStr, "\" but ") + "should be the same as the Font's BaseFont \"".concat(baseFontStr, "\"."));
+
+          if (fontNameStr && baseFontStr && baseFontStr.startsWith(fontNameStr)) {
+            fontName = baseFont;
+          }
+        }
+      }
+
+      fontName = fontName || baseFont;
+
+      if (!(0, _primitives.isName)(fontName)) {
+        throw new _util.FormatError('invalid font name');
+      }
+
+      var fontFile = descriptor.get('FontFile', 'FontFile2', 'FontFile3');
+
+      if (fontFile) {
+        if (fontFile.dict) {
+          var subtype = fontFile.dict.get('Subtype');
+
+          if (subtype) {
+            subtype = subtype.name;
+          }
+
+          var length1 = fontFile.dict.get('Length1');
+          var length2 = fontFile.dict.get('Length2');
+          var length3 = fontFile.dict.get('Length3');
+        }
+      }
+
+      properties = {
+        type: type,
+        name: fontName.name,
+        subtype: subtype,
+        file: fontFile,
+        length1: length1,
+        length2: length2,
+        length3: length3,
+        loadedName: baseDict.loadedName,
+        composite: composite,
+        wideChars: composite,
+        fixedPitch: false,
+        fontMatrix: dict.getArray('FontMatrix') || _util.FONT_IDENTITY_MATRIX,
+        firstChar: firstChar || 0,
+        lastChar: lastChar || maxCharIndex,
+        bbox: descriptor.getArray('FontBBox'),
+        ascent: descriptor.get('Ascent'),
+        descent: descriptor.get('Descent'),
+        xHeight: descriptor.get('XHeight'),
+        capHeight: descriptor.get('CapHeight'),
+        flags: descriptor.get('Flags'),
+        italicAngle: descriptor.get('ItalicAngle'),
+        isType3Font: false
+      };
+      var cMapPromise;
+
+      if (composite) {
+        var cidEncoding = baseDict.get('Encoding');
+
+        if ((0, _primitives.isName)(cidEncoding)) {
+          properties.cidEncoding = cidEncoding.name;
+        }
+
+        cMapPromise = _cmap.CMapFactory.create({
+          encoding: cidEncoding,
+          fetchBuiltInCMap: this.fetchBuiltInCMap,
+          useCMap: null
+        }).then(function (cMap) {
+          properties.cMap = cMap;
+          properties.vertical = properties.cMap.vertical;
+        });
+      } else {
+        cMapPromise = Promise.resolve(undefined);
+      }
+
+      return cMapPromise.then(function () {
+        return _this10.extractDataStructures(dict, baseDict, properties);
+      }).then(function (properties) {
+        _this10.extractWidths(dict, descriptor, properties);
+
+        if (type === 'Type3') {
+          properties.isType3Font = true;
+        }
+
+        return new _fonts.Font(fontName.name, fontFile, properties);
+      });
+    }
+  };
+
+  PartialEvaluator.buildFontPaths = function (font, glyphs, handler) {
+    function buildPath(fontChar) {
+      if (font.renderer.hasBuiltPath(fontChar)) {
+        return;
+      }
+
+      handler.send('commonobj', ["".concat(font.loadedName, "_path_").concat(fontChar), 'FontPath', font.renderer.getPathJs(fontChar)]);
+    }
+
+    var _iteratorNormalCompletion = true;
+    var _didIteratorError = false;
+    var _iteratorError = undefined;
+
+    try {
+      for (var _iterator = glyphs[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
+        var glyph = _step.value;
+        buildPath(glyph.fontChar);
+        var accent = glyph.accent;
+
+        if (accent && accent.fontChar) {
+          buildPath(accent.fontChar);
+        }
+      }
+    } catch (err) {
+      _didIteratorError = true;
+      _iteratorError = err;
+    } finally {
+      try {
+        if (!_iteratorNormalCompletion && _iterator["return"] != null) {
+          _iterator["return"]();
+        }
+      } finally {
+        if (_didIteratorError) {
+          throw _iteratorError;
+        }
+      }
+    }
+  };
+
+  return PartialEvaluator;
+}();
+
+exports.PartialEvaluator = PartialEvaluator;
+
+var TranslatedFont = function TranslatedFontClosure() {
+  function TranslatedFont(loadedName, font, dict) {
+    this.loadedName = loadedName;
+    this.font = font;
+    this.dict = dict;
+    this.type3Loaded = null;
+    this.sent = false;
+  }
+
+  TranslatedFont.prototype = {
+    send: function send(handler) {
+      if (this.sent) {
+        return;
+      }
+
+      this.sent = true;
+      handler.send('commonobj', [this.loadedName, 'Font', this.font.exportData()]);
+    },
+    fallback: function fallback(handler) {
+      if (!this.font.data) {
+        return;
+      }
+
+      this.font.disableFontFace = true;
+      var glyphs = this.font.glyphCacheValues;
+      PartialEvaluator.buildFontPaths(this.font, glyphs, handler);
+    },
+    loadType3Data: function loadType3Data(evaluator, resources, parentOperatorList, task) {
+      if (!this.font.isType3Font) {
+        throw new Error('Must be a Type3 font.');
+      }
+
+      if (this.type3Loaded) {
+        return this.type3Loaded;
+      }
+
+      var type3Options = Object.create(evaluator.options);
+      type3Options.ignoreErrors = false;
+      type3Options.nativeImageDecoderSupport = _util.NativeImageDecoding.NONE;
+      var type3Evaluator = evaluator.clone(type3Options);
+      type3Evaluator.parsingType3Font = true;
+      var translatedFont = this.font;
+      var loadCharProcsPromise = Promise.resolve();
+      var charProcs = this.dict.get('CharProcs');
+      var fontResources = this.dict.get('Resources') || resources;
+      var charProcKeys = charProcs.getKeys();
+      var charProcOperatorList = Object.create(null);
+
+      var _loop2 = function _loop2() {
+        var key = charProcKeys[i];
+        loadCharProcsPromise = loadCharProcsPromise.then(function () {
+          var glyphStream = charProcs.get(key);
+          var operatorList = new _operator_list.OperatorList();
+          return type3Evaluator.getOperatorList({
+            stream: glyphStream,
+            task: task,
+            resources: fontResources,
+            operatorList: operatorList
+          }).then(function () {
+            charProcOperatorList[key] = operatorList.getIR();
+            parentOperatorList.addDependencies(operatorList.dependencies);
+          })["catch"](function (reason) {
+            (0, _util.warn)("Type3 font resource \"".concat(key, "\" is not available."));
+            var operatorList = new _operator_list.OperatorList();
+            charProcOperatorList[key] = operatorList.getIR();
+          });
+        });
+      };
+
+      for (var i = 0, n = charProcKeys.length; i < n; ++i) {
+        _loop2();
+      }
+
+      this.type3Loaded = loadCharProcsPromise.then(function () {
+        translatedFont.charProcOperatorList = charProcOperatorList;
+      });
+      return this.type3Loaded;
+    }
+  };
+  return TranslatedFont;
+}();
+
+var StateManager = function StateManagerClosure() {
+  function StateManager(initialState) {
+    this.state = initialState;
+    this.stateStack = [];
+  }
+
+  StateManager.prototype = {
+    save: function save() {
+      var old = this.state;
+      this.stateStack.push(this.state);
+      this.state = old.clone();
+    },
+    restore: function restore() {
+      var prev = this.stateStack.pop();
+
+      if (prev) {
+        this.state = prev;
+      }
+    },
+    transform: function transform(args) {
+      this.state.ctm = _util.Util.transform(this.state.ctm, args);
+    }
+  };
+  return StateManager;
+}();
+
+var TextState = function TextStateClosure() {
+  function TextState() {
+    this.ctm = new Float32Array(_util.IDENTITY_MATRIX);
+    this.fontName = null;
+    this.fontSize = 0;
+    this.font = null;
+    this.fontMatrix = _util.FONT_IDENTITY_MATRIX;
+    this.textMatrix = _util.IDENTITY_MATRIX.slice();
+    this.textLineMatrix = _util.IDENTITY_MATRIX.slice();
+    this.charSpacing = 0;
+    this.wordSpacing = 0;
+    this.leading = 0;
+    this.textHScale = 1;
+    this.textRise = 0;
+  }
+
+  TextState.prototype = {
+    setTextMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
+      var m = this.textMatrix;
+      m[0] = a;
+      m[1] = b;
+      m[2] = c;
+      m[3] = d;
+      m[4] = e;
+      m[5] = f;
+    },
+    setTextLineMatrix: function TextState_setTextMatrix(a, b, c, d, e, f) {
+      var m = this.textLineMatrix;
+      m[0] = a;
+      m[1] = b;
+      m[2] = c;
+      m[3] = d;
+      m[4] = e;
+      m[5] = f;
+    },
+    translateTextMatrix: function TextState_translateTextMatrix(x, y) {
+      var m = this.textMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+    },
+    translateTextLineMatrix: function TextState_translateTextMatrix(x, y) {
+      var m = this.textLineMatrix;
+      m[4] = m[0] * x + m[2] * y + m[4];
+      m[5] = m[1] * x + m[3] * y + m[5];
+    },
+    calcTextLineMatrixAdvance: function TextState_calcTextLineMatrixAdvance(a, b, c, d, e, f) {
+      var font = this.font;
+
+      if (!font) {
+        return null;
+      }
+
+      var m = this.textLineMatrix;
+
+      if (!(a === m[0] && b === m[1] && c === m[2] && d === m[3])) {
+        return null;
+      }
+
+      var txDiff = e - m[4],
+          tyDiff = f - m[5];
+
+      if (font.vertical && txDiff !== 0 || !font.vertical && tyDiff !== 0) {
+        return null;
+      }
+
+      var tx,
+          ty,
+          denominator = a * d - b * c;
+
+      if (font.vertical) {
+        tx = -tyDiff * c / denominator;
+        ty = tyDiff * a / denominator;
+      } else {
+        tx = txDiff * d / denominator;
+        ty = -txDiff * b / denominator;
+      }
+
+      return {
+        width: tx,
+        height: ty,
+        value: font.vertical ? ty : tx
+      };
+    },
+    calcRenderMatrix: function TextState_calcRendeMatrix(ctm) {
+      var tsm = [this.fontSize * this.textHScale, 0, 0, this.fontSize, 0, this.textRise];
+      return _util.Util.transform(ctm, _util.Util.transform(this.textMatrix, tsm));
+    },
+    carriageReturn: function TextState_carriageReturn() {
+      this.translateTextLineMatrix(0, -this.leading);
+      this.textMatrix = this.textLineMatrix.slice();
+    },
+    clone: function TextState_clone() {
+      var clone = Object.create(this);
+      clone.textMatrix = this.textMatrix.slice();
+      clone.textLineMatrix = this.textLineMatrix.slice();
+      clone.fontMatrix = this.fontMatrix.slice();
+      return clone;
+    }
+  };
+  return TextState;
+}();
+
+var EvalState = function EvalStateClosure() {
+  function EvalState() {
+    this.ctm = new Float32Array(_util.IDENTITY_MATRIX);
+    this.font = null;
+    this.textRenderingMode = _util.TextRenderingMode.FILL;
+    this.fillColorSpace = _colorspace.ColorSpace.singletons.gray;
+    this.strokeColorSpace = _colorspace.ColorSpace.singletons.gray;
+  }
+
+  EvalState.prototype = {
+    clone: function CanvasExtraState_clone() {
+      return Object.create(this);
+    }
+  };
+  return EvalState;
+}();
+
+var EvaluatorPreprocessor = function EvaluatorPreprocessorClosure() {
+  var getOPMap = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['w'] = {
+      id: _util.OPS.setLineWidth,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['J'] = {
+      id: _util.OPS.setLineCap,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['j'] = {
+      id: _util.OPS.setLineJoin,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['M'] = {
+      id: _util.OPS.setMiterLimit,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['d'] = {
+      id: _util.OPS.setDash,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['ri'] = {
+      id: _util.OPS.setRenderingIntent,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['i'] = {
+      id: _util.OPS.setFlatness,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['gs'] = {
+      id: _util.OPS.setGState,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['q'] = {
+      id: _util.OPS.save,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['Q'] = {
+      id: _util.OPS.restore,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['cm'] = {
+      id: _util.OPS.transform,
+      numArgs: 6,
+      variableArgs: false
+    };
+    t['m'] = {
+      id: _util.OPS.moveTo,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['l'] = {
+      id: _util.OPS.lineTo,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['c'] = {
+      id: _util.OPS.curveTo,
+      numArgs: 6,
+      variableArgs: false
+    };
+    t['v'] = {
+      id: _util.OPS.curveTo2,
+      numArgs: 4,
+      variableArgs: false
+    };
+    t['y'] = {
+      id: _util.OPS.curveTo3,
+      numArgs: 4,
+      variableArgs: false
+    };
+    t['h'] = {
+      id: _util.OPS.closePath,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['re'] = {
+      id: _util.OPS.rectangle,
+      numArgs: 4,
+      variableArgs: false
+    };
+    t['S'] = {
+      id: _util.OPS.stroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['s'] = {
+      id: _util.OPS.closeStroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['f'] = {
+      id: _util.OPS.fill,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['F'] = {
+      id: _util.OPS.fill,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['f*'] = {
+      id: _util.OPS.eoFill,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['B'] = {
+      id: _util.OPS.fillStroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['B*'] = {
+      id: _util.OPS.eoFillStroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['b'] = {
+      id: _util.OPS.closeFillStroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['b*'] = {
+      id: _util.OPS.closeEOFillStroke,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['n'] = {
+      id: _util.OPS.endPath,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['W'] = {
+      id: _util.OPS.clip,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['W*'] = {
+      id: _util.OPS.eoClip,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['BT'] = {
+      id: _util.OPS.beginText,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['ET'] = {
+      id: _util.OPS.endText,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['Tc'] = {
+      id: _util.OPS.setCharSpacing,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Tw'] = {
+      id: _util.OPS.setWordSpacing,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Tz'] = {
+      id: _util.OPS.setHScale,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['TL'] = {
+      id: _util.OPS.setLeading,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Tf'] = {
+      id: _util.OPS.setFont,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['Tr'] = {
+      id: _util.OPS.setTextRenderingMode,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Ts'] = {
+      id: _util.OPS.setTextRise,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Td'] = {
+      id: _util.OPS.moveText,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['TD'] = {
+      id: _util.OPS.setLeadingMoveText,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['Tm'] = {
+      id: _util.OPS.setTextMatrix,
+      numArgs: 6,
+      variableArgs: false
+    };
+    t['T*'] = {
+      id: _util.OPS.nextLine,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['Tj'] = {
+      id: _util.OPS.showText,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['TJ'] = {
+      id: _util.OPS.showSpacedText,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['\''] = {
+      id: _util.OPS.nextLineShowText,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['"'] = {
+      id: _util.OPS.nextLineSetSpacingShowText,
+      numArgs: 3,
+      variableArgs: false
+    };
+    t['d0'] = {
+      id: _util.OPS.setCharWidth,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['d1'] = {
+      id: _util.OPS.setCharWidthAndBounds,
+      numArgs: 6,
+      variableArgs: false
+    };
+    t['CS'] = {
+      id: _util.OPS.setStrokeColorSpace,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['cs'] = {
+      id: _util.OPS.setFillColorSpace,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['SC'] = {
+      id: _util.OPS.setStrokeColor,
+      numArgs: 4,
+      variableArgs: true
+    };
+    t['SCN'] = {
+      id: _util.OPS.setStrokeColorN,
+      numArgs: 33,
+      variableArgs: true
+    };
+    t['sc'] = {
+      id: _util.OPS.setFillColor,
+      numArgs: 4,
+      variableArgs: true
+    };
+    t['scn'] = {
+      id: _util.OPS.setFillColorN,
+      numArgs: 33,
+      variableArgs: true
+    };
+    t['G'] = {
+      id: _util.OPS.setStrokeGray,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['g'] = {
+      id: _util.OPS.setFillGray,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['RG'] = {
+      id: _util.OPS.setStrokeRGBColor,
+      numArgs: 3,
+      variableArgs: false
+    };
+    t['rg'] = {
+      id: _util.OPS.setFillRGBColor,
+      numArgs: 3,
+      variableArgs: false
+    };
+    t['K'] = {
+      id: _util.OPS.setStrokeCMYKColor,
+      numArgs: 4,
+      variableArgs: false
+    };
+    t['k'] = {
+      id: _util.OPS.setFillCMYKColor,
+      numArgs: 4,
+      variableArgs: false
+    };
+    t['sh'] = {
+      id: _util.OPS.shadingFill,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['BI'] = {
+      id: _util.OPS.beginInlineImage,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['ID'] = {
+      id: _util.OPS.beginImageData,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['EI'] = {
+      id: _util.OPS.endInlineImage,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['Do'] = {
+      id: _util.OPS.paintXObject,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['MP'] = {
+      id: _util.OPS.markPoint,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['DP'] = {
+      id: _util.OPS.markPointProps,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['BMC'] = {
+      id: _util.OPS.beginMarkedContent,
+      numArgs: 1,
+      variableArgs: false
+    };
+    t['BDC'] = {
+      id: _util.OPS.beginMarkedContentProps,
+      numArgs: 2,
+      variableArgs: false
+    };
+    t['EMC'] = {
+      id: _util.OPS.endMarkedContent,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['BX'] = {
+      id: _util.OPS.beginCompat,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['EX'] = {
+      id: _util.OPS.endCompat,
+      numArgs: 0,
+      variableArgs: false
+    };
+    t['BM'] = null;
+    t['BD'] = null;
+    t['true'] = null;
+    t['fa'] = null;
+    t['fal'] = null;
+    t['fals'] = null;
+    t['false'] = null;
+    t['nu'] = null;
+    t['nul'] = null;
+    t['null'] = null;
+  });
+  var MAX_INVALID_PATH_OPS = 20;
+
+  function EvaluatorPreprocessor(stream, xref, stateManager) {
+    this.opMap = getOPMap();
+    this.parser = new _parser.Parser({
+      lexer: new _parser.Lexer(stream, this.opMap),
+      xref: xref
+    });
+    this.stateManager = stateManager;
+    this.nonProcessedArgs = [];
+    this._numInvalidPathOPS = 0;
+  }
+
+  EvaluatorPreprocessor.prototype = {
+    get savedStatesDepth() {
+      return this.stateManager.stateStack.length;
+    },
+
+    read: function EvaluatorPreprocessor_read(operation) {
+      var args = operation.args;
+
+      while (true) {
+        var obj = this.parser.getObj();
+
+        if ((0, _primitives.isCmd)(obj)) {
+          var cmd = obj.cmd;
+          var opSpec = this.opMap[cmd];
+
+          if (!opSpec) {
+            (0, _util.warn)("Unknown command \"".concat(cmd, "\"."));
+            continue;
+          }
+
+          var fn = opSpec.id;
+          var numArgs = opSpec.numArgs;
+          var argsLength = args !== null ? args.length : 0;
+
+          if (!opSpec.variableArgs) {
+            if (argsLength !== numArgs) {
+              var nonProcessedArgs = this.nonProcessedArgs;
+
+              while (argsLength > numArgs) {
+                nonProcessedArgs.push(args.shift());
+                argsLength--;
+              }
+
+              while (argsLength < numArgs && nonProcessedArgs.length !== 0) {
+                if (args === null) {
+                  args = [];
+                }
+
+                args.unshift(nonProcessedArgs.pop());
+                argsLength++;
+              }
+            }
+
+            if (argsLength < numArgs) {
+              var partialMsg = "command ".concat(cmd, ": expected ").concat(numArgs, " args, ") + "but received ".concat(argsLength, " args.");
+
+              if (fn >= _util.OPS.moveTo && fn <= _util.OPS.endPath && ++this._numInvalidPathOPS > MAX_INVALID_PATH_OPS) {
+                throw new _util.FormatError("Invalid ".concat(partialMsg));
+              }
+
+              (0, _util.warn)("Skipping ".concat(partialMsg));
+
+              if (args !== null) {
+                args.length = 0;
+              }
+
+              continue;
+            }
+          } else if (argsLength > numArgs) {
+            (0, _util.info)("Command ".concat(cmd, ": expected [0, ").concat(numArgs, "] args, ") + "but received ".concat(argsLength, " args."));
+          }
+
+          this.preprocessCommand(fn, args);
+          operation.fn = fn;
+          operation.args = args;
+          return true;
+        }
+
+        if ((0, _primitives.isEOF)(obj)) {
+          return false;
+        }
+
+        if (obj !== null) {
+          if (args === null) {
+            args = [];
+          }
+
+          args.push(obj);
+
+          if (args.length > 33) {
+            throw new _util.FormatError('Too many arguments');
+          }
+        }
+      }
+    },
+    preprocessCommand: function EvaluatorPreprocessor_preprocessCommand(fn, args) {
+      switch (fn | 0) {
+        case _util.OPS.save:
+          this.stateManager.save();
+          break;
+
+        case _util.OPS.restore:
+          this.stateManager.restore();
+          break;
+
+        case _util.OPS.transform:
+          this.stateManager.transform(args);
+          break;
+      }
+    }
+  };
+  return EvaluatorPreprocessor;
+}();
+
+/***/ }),
+/* 173 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.CMapFactory = exports.IdentityCMap = exports.CMap = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _parser = __w_pdfjs_require__(157);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var BUILT_IN_CMAPS = ['Adobe-GB1-UCS2', 'Adobe-CNS1-UCS2', 'Adobe-Japan1-UCS2', 'Adobe-Korea1-UCS2', '78-EUC-H', '78-EUC-V', '78-H', '78-RKSJ-H', '78-RKSJ-V', '78-V', '78ms-RKSJ-H', '78ms-RKSJ-V', '83pv-RKSJ-H', '90ms-RKSJ-H', '90ms-RKSJ-V', '90msp-RKSJ-H', '90msp-RKSJ-V', '90pv-RKSJ-H', '90pv-RKSJ-V', 'Add-H', 'Add-RKSJ-H', 'Add-RKSJ-V', 'Add-V', 'Adobe-CNS1-0', 'Adobe-CNS1-1', 'Adobe-CNS1-2', 'Adobe-CNS1-3', 'Adobe-CNS1-4', 'Adobe-CNS1-5', 'Adobe-CNS1-6', 'Adobe-GB1-0', 'Adobe-GB1-1', 'Adobe-GB1-2', 'Adobe-GB1-3', 'Adobe-GB1-4', 'Adobe-GB1-5', 'Adobe-Japan1-0', 'Adobe-Japan1-1', 'Adobe-Japan1-2', 'Adobe-Japan1-3', 'Adobe-Japan1-4', 'Adobe-Japan1-5', 'Adobe-Japan1-6', 'Adobe-Korea1-0', 'Adobe-Korea1-1', 'Adobe-Korea1-2', 'B5-H', 'B5-V', 'B5pc-H', 'B5pc-V', 'CNS-EUC-H', 'CNS-EUC-V', 'CNS1-H', 'CNS1-V', 'CNS2-H', 'CNS2-V', 'ETHK-B5-H', 'ETHK-B5-V', 'ETen-B5-H', 'ETen-B5-V', 'ETenms-B5-H', 'ETenms-B5-V', 'EUC-H', 'EUC-V', 'Ext-H', 'Ext-RKSJ-H', 'Ext-RKSJ-V', 'Ext-V', 'GB-EUC-H', 'GB-EUC-V', 'GB-H', 'GB-V', 'GBK-EUC-H', 'GBK-EUC-V', 'GBK2K-H', 'GBK2K-V', 'GBKp-EUC-H', 'GBKp-EUC-V', 'GBT-EUC-H', 'GBT-EUC-V', 'GBT-H', 'GBT-V', 'GBTpc-EUC-H', 'GBTpc-EUC-V', 'GBpc-EUC-H', 'GBpc-EUC-V', 'H', 'HKdla-B5-H', 'HKdla-B5-V', 'HKdlb-B5-H', 'HKdlb-B5-V', 'HKgccs-B5-H', 'HKgccs-B5-V', 'HKm314-B5-H', 'HKm314-B5-V', 'HKm471-B5-H', 'HKm471-B5-V', 'HKscs-B5-H', 'HKscs-B5-V', 'Hankaku', 'Hiragana', 'KSC-EUC-H', 'KSC-EUC-V', 'KSC-H', 'KSC-Johab-H', 'KSC-Johab-V', 'KSC-V', 'KSCms-UHC-H', 'KSCms-UHC-HW-H', 'KSCms-UHC-HW-V', 'KSCms-UHC-V', 'KSCpc-EUC-H', 'KSCpc-EUC-V', 'Katakana', 'NWP-H', 'NWP-V', 'RKSJ-H', 'RKSJ-V', 'Roman', 'UniCNS-UCS2-H', 'UniCNS-UCS2-V', 'UniCNS-UTF16-H', 'UniCNS-UTF16-V', 'UniCNS-UTF32-H', 'UniCNS-UTF32-V', 'UniCNS-UTF8-H', 'UniCNS-UTF8-V', 'UniGB-UCS2-H', 'UniGB-UCS2-V', 'UniGB-UTF16-H', 'UniGB-UTF16-V', 'UniGB-UTF32-H', 'UniGB-UTF32-V', 'UniGB-UTF8-H', 'UniGB-UTF8-V', 'UniJIS-UCS2-H', 'UniJIS-UCS2-HW-H', 'UniJIS-UCS2-HW-V', 'UniJIS-UCS2-V', 'UniJIS-UTF16-H', 'UniJIS-UTF16-V', 'UniJIS-UTF32-H', 'UniJIS-UTF32-V', 'UniJIS-UTF8-H', 'UniJIS-UTF8-V', 'UniJIS2004-UTF16-H', 'UniJIS2004-UTF16-V', 'UniJIS2004-UTF32-H', 'UniJIS2004-UTF32-V', 'UniJIS2004-UTF8-H', 'UniJIS2004-UTF8-V', 'UniJISPro-UCS2-HW-V', 'UniJISPro-UCS2-V', 'UniJISPro-UTF8-V', 'UniJISX0213-UTF32-H', 'UniJISX0213-UTF32-V', 'UniJISX02132004-UTF32-H', 'UniJISX02132004-UTF32-V', 'UniKS-UCS2-H', 'UniKS-UCS2-V', 'UniKS-UTF16-H', 'UniKS-UTF16-V', 'UniKS-UTF32-H', 'UniKS-UTF32-V', 'UniKS-UTF8-H', 'UniKS-UTF8-V', 'V', 'WP-Symbol'];
+
+var CMap =
+/*#__PURE__*/
+function () {
+  function CMap() {
+    var builtInCMap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+
+    _classCallCheck(this, CMap);
+
+    this.codespaceRanges = [[], [], [], []];
+    this.numCodespaceRanges = 0;
+    this._map = [];
+    this.name = '';
+    this.vertical = false;
+    this.useCMap = null;
+    this.builtInCMap = builtInCMap;
+  }
+
+  _createClass(CMap, [{
+    key: "addCodespaceRange",
+    value: function addCodespaceRange(n, low, high) {
+      this.codespaceRanges[n - 1].push(low, high);
+      this.numCodespaceRanges++;
+    }
+  }, {
+    key: "mapCidRange",
+    value: function mapCidRange(low, high, dstLow) {
+      while (low <= high) {
+        this._map[low++] = dstLow++;
+      }
+    }
+  }, {
+    key: "mapBfRange",
+    value: function mapBfRange(low, high, dstLow) {
+      var lastByte = dstLow.length - 1;
+
+      while (low <= high) {
+        this._map[low++] = dstLow;
+        dstLow = dstLow.substring(0, lastByte) + String.fromCharCode(dstLow.charCodeAt(lastByte) + 1);
+      }
+    }
+  }, {
+    key: "mapBfRangeToArray",
+    value: function mapBfRangeToArray(low, high, array) {
+      var i = 0,
+          ii = array.length;
+
+      while (low <= high && i < ii) {
+        this._map[low] = array[i++];
+        ++low;
+      }
+    }
+  }, {
+    key: "mapOne",
+    value: function mapOne(src, dst) {
+      this._map[src] = dst;
+    }
+  }, {
+    key: "lookup",
+    value: function lookup(code) {
+      return this._map[code];
+    }
+  }, {
+    key: "contains",
+    value: function contains(code) {
+      return this._map[code] !== undefined;
+    }
+  }, {
+    key: "forEach",
+    value: function forEach(callback) {
+      var map = this._map;
+      var length = map.length;
+
+      if (length <= 0x10000) {
+        for (var i = 0; i < length; i++) {
+          if (map[i] !== undefined) {
+            callback(i, map[i]);
+          }
+        }
+      } else {
+        for (var _i in map) {
+          callback(_i, map[_i]);
+        }
+      }
+    }
+  }, {
+    key: "charCodeOf",
+    value: function charCodeOf(value) {
+      var map = this._map;
+
+      if (map.length <= 0x10000) {
+        return map.indexOf(value);
+      }
+
+      for (var charCode in map) {
+        if (map[charCode] === value) {
+          return charCode | 0;
+        }
+      }
+
+      return -1;
+    }
+  }, {
+    key: "getMap",
+    value: function getMap() {
+      return this._map;
+    }
+  }, {
+    key: "readCharCode",
+    value: function readCharCode(str, offset, out) {
+      var c = 0;
+      var codespaceRanges = this.codespaceRanges;
+
+      for (var n = 0, nn = codespaceRanges.length; n < nn; n++) {
+        c = (c << 8 | str.charCodeAt(offset + n)) >>> 0;
+        var codespaceRange = codespaceRanges[n];
+
+        for (var k = 0, kk = codespaceRange.length; k < kk;) {
+          var low = codespaceRange[k++];
+          var high = codespaceRange[k++];
+
+          if (c >= low && c <= high) {
+            out.charcode = c;
+            out.length = n + 1;
+            return;
+          }
+        }
+      }
+
+      out.charcode = 0;
+      out.length = 1;
+    }
+  }, {
+    key: "length",
+    get: function get() {
+      return this._map.length;
+    }
+  }, {
+    key: "isIdentityCMap",
+    get: function get() {
+      if (!(this.name === 'Identity-H' || this.name === 'Identity-V')) {
+        return false;
+      }
+
+      if (this._map.length !== 0x10000) {
+        return false;
+      }
+
+      for (var i = 0; i < 0x10000; i++) {
+        if (this._map[i] !== i) {
+          return false;
+        }
+      }
+
+      return true;
+    }
+  }]);
+
+  return CMap;
+}();
+
+exports.CMap = CMap;
+
+var IdentityCMap =
+/*#__PURE__*/
+function (_CMap) {
+  _inherits(IdentityCMap, _CMap);
+
+  function IdentityCMap(vertical, n) {
+    var _this;
+
+    _classCallCheck(this, IdentityCMap);
+
+    _this = _possibleConstructorReturn(this, _getPrototypeOf(IdentityCMap).call(this));
+    _this.vertical = vertical;
+
+    _this.addCodespaceRange(n, 0, 0xffff);
+
+    return _this;
+  }
+
+  _createClass(IdentityCMap, [{
+    key: "mapCidRange",
+    value: function mapCidRange(low, high, dstLow) {
+      (0, _util.unreachable)('should not call mapCidRange');
+    }
+  }, {
+    key: "mapBfRange",
+    value: function mapBfRange(low, high, dstLow) {
+      (0, _util.unreachable)('should not call mapBfRange');
+    }
+  }, {
+    key: "mapBfRangeToArray",
+    value: function mapBfRangeToArray(low, high, array) {
+      (0, _util.unreachable)('should not call mapBfRangeToArray');
+    }
+  }, {
+    key: "mapOne",
+    value: function mapOne(src, dst) {
+      (0, _util.unreachable)('should not call mapCidOne');
+    }
+  }, {
+    key: "lookup",
+    value: function lookup(code) {
+      return Number.isInteger(code) && code <= 0xffff ? code : undefined;
+    }
+  }, {
+    key: "contains",
+    value: function contains(code) {
+      return Number.isInteger(code) && code <= 0xffff;
+    }
+  }, {
+    key: "forEach",
+    value: function forEach(callback) {
+      for (var i = 0; i <= 0xffff; i++) {
+        callback(i, i);
+      }
+    }
+  }, {
+    key: "charCodeOf",
+    value: function charCodeOf(value) {
+      return Number.isInteger(value) && value <= 0xffff ? value : -1;
+    }
+  }, {
+    key: "getMap",
+    value: function getMap() {
+      var map = new Array(0x10000);
+
+      for (var i = 0; i <= 0xffff; i++) {
+        map[i] = i;
+      }
+
+      return map;
+    }
+  }, {
+    key: "length",
+    get: function get() {
+      return 0x10000;
+    }
+  }, {
+    key: "isIdentityCMap",
+    get: function get() {
+      (0, _util.unreachable)('should not access .isIdentityCMap');
+    }
+  }]);
+
+  return IdentityCMap;
+}(CMap);
+
+exports.IdentityCMap = IdentityCMap;
+
+var BinaryCMapReader = function BinaryCMapReaderClosure() {
+  function hexToInt(a, size) {
+    var n = 0;
+
+    for (var i = 0; i <= size; i++) {
+      n = n << 8 | a[i];
+    }
+
+    return n >>> 0;
+  }
+
+  function hexToStr(a, size) {
+    if (size === 1) {
+      return String.fromCharCode(a[0], a[1]);
+    }
+
+    if (size === 3) {
+      return String.fromCharCode(a[0], a[1], a[2], a[3]);
+    }
+
+    return String.fromCharCode.apply(null, a.subarray(0, size + 1));
+  }
+
+  function addHex(a, b, size) {
+    var c = 0;
+
+    for (var i = size; i >= 0; i--) {
+      c += a[i] + b[i];
+      a[i] = c & 255;
+      c >>= 8;
+    }
+  }
+
+  function incHex(a, size) {
+    var c = 1;
+
+    for (var i = size; i >= 0 && c > 0; i--) {
+      c += a[i];
+      a[i] = c & 255;
+      c >>= 8;
+    }
+  }
+
+  var MAX_NUM_SIZE = 16;
+  var MAX_ENCODED_NUM_SIZE = 19;
+
+  function BinaryCMapStream(data) {
+    this.buffer = data;
+    this.pos = 0;
+    this.end = data.length;
+    this.tmpBuf = new Uint8Array(MAX_ENCODED_NUM_SIZE);
+  }
+
+  BinaryCMapStream.prototype = {
+    readByte: function readByte() {
+      if (this.pos >= this.end) {
+        return -1;
+      }
+
+      return this.buffer[this.pos++];
+    },
+    readNumber: function readNumber() {
+      var n = 0;
+      var last;
+
+      do {
+        var b = this.readByte();
+
+        if (b < 0) {
+          throw new _util.FormatError('unexpected EOF in bcmap');
+        }
+
+        last = !(b & 0x80);
+        n = n << 7 | b & 0x7F;
+      } while (!last);
+
+      return n;
+    },
+    readSigned: function readSigned() {
+      var n = this.readNumber();
+      return n & 1 ? ~(n >>> 1) : n >>> 1;
+    },
+    readHex: function readHex(num, size) {
+      num.set(this.buffer.subarray(this.pos, this.pos + size + 1));
+      this.pos += size + 1;
+    },
+    readHexNumber: function readHexNumber(num, size) {
+      var last;
+      var stack = this.tmpBuf,
+          sp = 0;
+
+      do {
+        var b = this.readByte();
+
+        if (b < 0) {
+          throw new _util.FormatError('unexpected EOF in bcmap');
+        }
+
+        last = !(b & 0x80);
+        stack[sp++] = b & 0x7F;
+      } while (!last);
+
+      var i = size,
+          buffer = 0,
+          bufferSize = 0;
+
+      while (i >= 0) {
+        while (bufferSize < 8 && stack.length > 0) {
+          buffer = stack[--sp] << bufferSize | buffer;
+          bufferSize += 7;
+        }
+
+        num[i] = buffer & 255;
+        i--;
+        buffer >>= 8;
+        bufferSize -= 8;
+      }
+    },
+    readHexSigned: function readHexSigned(num, size) {
+      this.readHexNumber(num, size);
+      var sign = num[size] & 1 ? 255 : 0;
+      var c = 0;
+
+      for (var i = 0; i <= size; i++) {
+        c = (c & 1) << 8 | num[i];
+        num[i] = c >> 1 ^ sign;
+      }
+    },
+    readString: function readString() {
+      var len = this.readNumber();
+      var s = '';
+
+      for (var i = 0; i < len; i++) {
+        s += String.fromCharCode(this.readNumber());
+      }
+
+      return s;
+    }
+  };
+
+  function processBinaryCMap(data, cMap, extend) {
+    return new Promise(function (resolve, reject) {
+      var stream = new BinaryCMapStream(data);
+      var header = stream.readByte();
+      cMap.vertical = !!(header & 1);
+      var useCMap = null;
+      var start = new Uint8Array(MAX_NUM_SIZE);
+      var end = new Uint8Array(MAX_NUM_SIZE);
+
+      var _char = new Uint8Array(MAX_NUM_SIZE);
+
+      var charCode = new Uint8Array(MAX_NUM_SIZE);
+      var tmp = new Uint8Array(MAX_NUM_SIZE);
+      var code;
+      var b;
+
+      while ((b = stream.readByte()) >= 0) {
+        var type = b >> 5;
+
+        if (type === 7) {
+          switch (b & 0x1F) {
+            case 0:
+              stream.readString();
+              break;
+
+            case 1:
+              useCMap = stream.readString();
+              break;
+          }
+
+          continue;
+        }
+
+        var sequence = !!(b & 0x10);
+        var dataSize = b & 15;
+
+        if (dataSize + 1 > MAX_NUM_SIZE) {
+          throw new Error('processBinaryCMap: Invalid dataSize.');
+        }
+
+        var ucs2DataSize = 1;
+        var subitemsCount = stream.readNumber();
+        var i;
+
+        switch (type) {
+          case 0:
+            stream.readHex(start, dataSize);
+            stream.readHexNumber(end, dataSize);
+            addHex(end, start, dataSize);
+            cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(end, dataSize);
+              stream.readHexNumber(start, dataSize);
+              addHex(start, end, dataSize);
+              stream.readHexNumber(end, dataSize);
+              addHex(end, start, dataSize);
+              cMap.addCodespaceRange(dataSize + 1, hexToInt(start, dataSize), hexToInt(end, dataSize));
+            }
+
+            break;
+
+          case 1:
+            stream.readHex(start, dataSize);
+            stream.readHexNumber(end, dataSize);
+            addHex(end, start, dataSize);
+            stream.readNumber();
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(end, dataSize);
+              stream.readHexNumber(start, dataSize);
+              addHex(start, end, dataSize);
+              stream.readHexNumber(end, dataSize);
+              addHex(end, start, dataSize);
+              stream.readNumber();
+            }
+
+            break;
+
+          case 2:
+            stream.readHex(_char, dataSize);
+            code = stream.readNumber();
+            cMap.mapOne(hexToInt(_char, dataSize), code);
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(_char, dataSize);
+
+              if (!sequence) {
+                stream.readHexNumber(tmp, dataSize);
+                addHex(_char, tmp, dataSize);
+              }
+
+              code = stream.readSigned() + (code + 1);
+              cMap.mapOne(hexToInt(_char, dataSize), code);
+            }
+
+            break;
+
+          case 3:
+            stream.readHex(start, dataSize);
+            stream.readHexNumber(end, dataSize);
+            addHex(end, start, dataSize);
+            code = stream.readNumber();
+            cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(end, dataSize);
+
+              if (!sequence) {
+                stream.readHexNumber(start, dataSize);
+                addHex(start, end, dataSize);
+              } else {
+                start.set(end);
+              }
+
+              stream.readHexNumber(end, dataSize);
+              addHex(end, start, dataSize);
+              code = stream.readNumber();
+              cMap.mapCidRange(hexToInt(start, dataSize), hexToInt(end, dataSize), code);
+            }
+
+            break;
+
+          case 4:
+            stream.readHex(_char, ucs2DataSize);
+            stream.readHex(charCode, dataSize);
+            cMap.mapOne(hexToInt(_char, ucs2DataSize), hexToStr(charCode, dataSize));
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(_char, ucs2DataSize);
+
+              if (!sequence) {
+                stream.readHexNumber(tmp, ucs2DataSize);
+                addHex(_char, tmp, ucs2DataSize);
+              }
+
+              incHex(charCode, dataSize);
+              stream.readHexSigned(tmp, dataSize);
+              addHex(charCode, tmp, dataSize);
+              cMap.mapOne(hexToInt(_char, ucs2DataSize), hexToStr(charCode, dataSize));
+            }
+
+            break;
+
+          case 5:
+            stream.readHex(start, ucs2DataSize);
+            stream.readHexNumber(end, ucs2DataSize);
+            addHex(end, start, ucs2DataSize);
+            stream.readHex(charCode, dataSize);
+            cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
+
+            for (i = 1; i < subitemsCount; i++) {
+              incHex(end, ucs2DataSize);
+
+              if (!sequence) {
+                stream.readHexNumber(start, ucs2DataSize);
+                addHex(start, end, ucs2DataSize);
+              } else {
+                start.set(end);
+              }
+
+              stream.readHexNumber(end, ucs2DataSize);
+              addHex(end, start, ucs2DataSize);
+              stream.readHex(charCode, dataSize);
+              cMap.mapBfRange(hexToInt(start, ucs2DataSize), hexToInt(end, ucs2DataSize), hexToStr(charCode, dataSize));
+            }
+
+            break;
+
+          default:
+            reject(new Error('processBinaryCMap: Unknown type: ' + type));
+            return;
+        }
+      }
+
+      if (useCMap) {
+        resolve(extend(useCMap));
+        return;
+      }
+
+      resolve(cMap);
+    });
+  }
+
+  function BinaryCMapReader() {}
+
+  BinaryCMapReader.prototype = {
+    process: processBinaryCMap
+  };
+  return BinaryCMapReader;
+}();
+
+var CMapFactory = function CMapFactoryClosure() {
+  function strToInt(str) {
+    var a = 0;
+
+    for (var i = 0; i < str.length; i++) {
+      a = a << 8 | str.charCodeAt(i);
+    }
+
+    return a >>> 0;
+  }
+
+  function expectString(obj) {
+    if (!(0, _util.isString)(obj)) {
+      throw new _util.FormatError('Malformed CMap: expected string.');
+    }
+  }
+
+  function expectInt(obj) {
+    if (!Number.isInteger(obj)) {
+      throw new _util.FormatError('Malformed CMap: expected int.');
+    }
+  }
+
+  function parseBfChar(cMap, lexer) {
+    while (true) {
+      var obj = lexer.getObj();
+
+      if ((0, _primitives.isEOF)(obj)) {
+        break;
+      }
+
+      if ((0, _primitives.isCmd)(obj, 'endbfchar')) {
+        return;
+      }
+
+      expectString(obj);
+      var src = strToInt(obj);
+      obj = lexer.getObj();
+      expectString(obj);
+      var dst = obj;
+      cMap.mapOne(src, dst);
+    }
+  }
+
+  function parseBfRange(cMap, lexer) {
+    while (true) {
+      var obj = lexer.getObj();
+
+      if ((0, _primitives.isEOF)(obj)) {
+        break;
+      }
+
+      if ((0, _primitives.isCmd)(obj, 'endbfrange')) {
+        return;
+      }
+
+      expectString(obj);
+      var low = strToInt(obj);
+      obj = lexer.getObj();
+      expectString(obj);
+      var high = strToInt(obj);
+      obj = lexer.getObj();
+
+      if (Number.isInteger(obj) || (0, _util.isString)(obj)) {
+        var dstLow = Number.isInteger(obj) ? String.fromCharCode(obj) : obj;
+        cMap.mapBfRange(low, high, dstLow);
+      } else if ((0, _primitives.isCmd)(obj, '[')) {
+        obj = lexer.getObj();
+        var array = [];
+
+        while (!(0, _primitives.isCmd)(obj, ']') && !(0, _primitives.isEOF)(obj)) {
+          array.push(obj);
+          obj = lexer.getObj();
+        }
+
+        cMap.mapBfRangeToArray(low, high, array);
+      } else {
+        break;
+      }
+    }
+
+    throw new _util.FormatError('Invalid bf range.');
+  }
+
+  function parseCidChar(cMap, lexer) {
+    while (true) {
+      var obj = lexer.getObj();
+
+      if ((0, _primitives.isEOF)(obj)) {
+        break;
+      }
+
+      if ((0, _primitives.isCmd)(obj, 'endcidchar')) {
+        return;
+      }
+
+      expectString(obj);
+      var src = strToInt(obj);
+      obj = lexer.getObj();
+      expectInt(obj);
+      var dst = obj;
+      cMap.mapOne(src, dst);
+    }
+  }
+
+  function parseCidRange(cMap, lexer) {
+    while (true) {
+      var obj = lexer.getObj();
+
+      if ((0, _primitives.isEOF)(obj)) {
+        break;
+      }
+
+      if ((0, _primitives.isCmd)(obj, 'endcidrange')) {
+        return;
+      }
+
+      expectString(obj);
+      var low = strToInt(obj);
+      obj = lexer.getObj();
+      expectString(obj);
+      var high = strToInt(obj);
+      obj = lexer.getObj();
+      expectInt(obj);
+      var dstLow = obj;
+      cMap.mapCidRange(low, high, dstLow);
+    }
+  }
+
+  function parseCodespaceRange(cMap, lexer) {
+    while (true) {
+      var obj = lexer.getObj();
+
+      if ((0, _primitives.isEOF)(obj)) {
+        break;
+      }
+
+      if ((0, _primitives.isCmd)(obj, 'endcodespacerange')) {
+        return;
+      }
+
+      if (!(0, _util.isString)(obj)) {
+        break;
+      }
+
+      var low = strToInt(obj);
+      obj = lexer.getObj();
+
+      if (!(0, _util.isString)(obj)) {
+        break;
+      }
+
+      var high = strToInt(obj);
+      cMap.addCodespaceRange(obj.length, low, high);
+    }
+
+    throw new _util.FormatError('Invalid codespace range.');
+  }
+
+  function parseWMode(cMap, lexer) {
+    var obj = lexer.getObj();
+
+    if (Number.isInteger(obj)) {
+      cMap.vertical = !!obj;
+    }
+  }
+
+  function parseCMapName(cMap, lexer) {
+    var obj = lexer.getObj();
+
+    if ((0, _primitives.isName)(obj) && (0, _util.isString)(obj.name)) {
+      cMap.name = obj.name;
+    }
+  }
+
+  function parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap) {
+    var previous;
+    var embeddedUseCMap;
+
+    objLoop: while (true) {
+      try {
+        var obj = lexer.getObj();
+
+        if ((0, _primitives.isEOF)(obj)) {
+          break;
+        } else if ((0, _primitives.isName)(obj)) {
+          if (obj.name === 'WMode') {
+            parseWMode(cMap, lexer);
+          } else if (obj.name === 'CMapName') {
+            parseCMapName(cMap, lexer);
+          }
+
+          previous = obj;
+        } else if ((0, _primitives.isCmd)(obj)) {
+          switch (obj.cmd) {
+            case 'endcmap':
+              break objLoop;
+
+            case 'usecmap':
+              if ((0, _primitives.isName)(previous)) {
+                embeddedUseCMap = previous.name;
+              }
+
+              break;
+
+            case 'begincodespacerange':
+              parseCodespaceRange(cMap, lexer);
+              break;
+
+            case 'beginbfchar':
+              parseBfChar(cMap, lexer);
+              break;
+
+            case 'begincidchar':
+              parseCidChar(cMap, lexer);
+              break;
+
+            case 'beginbfrange':
+              parseBfRange(cMap, lexer);
+              break;
+
+            case 'begincidrange':
+              parseCidRange(cMap, lexer);
+              break;
+          }
+        }
+      } catch (ex) {
+        if (ex instanceof _core_utils.MissingDataException) {
+          throw ex;
+        }
+
+        (0, _util.warn)('Invalid cMap data: ' + ex);
+        continue;
+      }
+    }
+
+    if (!useCMap && embeddedUseCMap) {
+      useCMap = embeddedUseCMap;
+    }
+
+    if (useCMap) {
+      return extendCMap(cMap, fetchBuiltInCMap, useCMap);
+    }
+
+    return Promise.resolve(cMap);
+  }
+
+  function extendCMap(cMap, fetchBuiltInCMap, useCMap) {
+    return createBuiltInCMap(useCMap, fetchBuiltInCMap).then(function (newCMap) {
+      cMap.useCMap = newCMap;
+
+      if (cMap.numCodespaceRanges === 0) {
+        var useCodespaceRanges = cMap.useCMap.codespaceRanges;
+
+        for (var i = 0; i < useCodespaceRanges.length; i++) {
+          cMap.codespaceRanges[i] = useCodespaceRanges[i].slice();
+        }
+
+        cMap.numCodespaceRanges = cMap.useCMap.numCodespaceRanges;
+      }
+
+      cMap.useCMap.forEach(function (key, value) {
+        if (!cMap.contains(key)) {
+          cMap.mapOne(key, cMap.useCMap.lookup(key));
+        }
+      });
+      return cMap;
+    });
+  }
+
+  function createBuiltInCMap(name, fetchBuiltInCMap) {
+    if (name === 'Identity-H') {
+      return Promise.resolve(new IdentityCMap(false, 2));
+    } else if (name === 'Identity-V') {
+      return Promise.resolve(new IdentityCMap(true, 2));
+    }
+
+    if (!BUILT_IN_CMAPS.includes(name)) {
+      return Promise.reject(new Error('Unknown CMap name: ' + name));
+    }
+
+    if (!fetchBuiltInCMap) {
+      return Promise.reject(new Error('Built-in CMap parameters are not provided.'));
+    }
+
+    return fetchBuiltInCMap(name).then(function (data) {
+      var cMapData = data.cMapData,
+          compressionType = data.compressionType;
+      var cMap = new CMap(true);
+
+      if (compressionType === _util.CMapCompressionType.BINARY) {
+        return new BinaryCMapReader().process(cMapData, cMap, function (useCMap) {
+          return extendCMap(cMap, fetchBuiltInCMap, useCMap);
+        });
+      }
+
+      if (compressionType === _util.CMapCompressionType.NONE) {
+        var lexer = new _parser.Lexer(new _stream.Stream(cMapData));
+        return parseCMap(cMap, lexer, fetchBuiltInCMap, null);
+      }
+
+      return Promise.reject(new Error('TODO: Only BINARY/NONE CMap compression is currently supported.'));
+    });
+  }
+
+  return {
+    create: function create(params) {
+      var encoding = params.encoding;
+      var fetchBuiltInCMap = params.fetchBuiltInCMap;
+      var useCMap = params.useCMap;
+
+      if ((0, _primitives.isName)(encoding)) {
+        return createBuiltInCMap(encoding.name, fetchBuiltInCMap);
+      } else if ((0, _primitives.isStream)(encoding)) {
+        var cMap = new CMap();
+        var lexer = new _parser.Lexer(encoding);
+        return parseCMap(cMap, lexer, fetchBuiltInCMap, useCMap).then(function (parsedCMap) {
+          if (parsedCMap.isIdentityCMap) {
+            return createBuiltInCMap(parsedCMap.name, fetchBuiltInCMap);
+          }
+
+          return parsedCMap;
+        });
+      }
+
+      return Promise.reject(new Error('Encoding required.'));
+    }
+  };
+}();
+
+exports.CMapFactory = CMapFactory;
+
+/***/ }),
+/* 174 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getFontType = getFontType;
+exports.IdentityToUnicodeMap = exports.ToUnicodeMap = exports.FontFlags = exports.Font = exports.ErrorFont = exports.SEAC_ANALYSIS_ENABLED = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _cff_parser = __w_pdfjs_require__(175);
+
+var _glyphlist = __w_pdfjs_require__(178);
+
+var _encodings = __w_pdfjs_require__(177);
+
+var _standard_fonts = __w_pdfjs_require__(179);
+
+var _unicode = __w_pdfjs_require__(180);
+
+var _font_renderer = __w_pdfjs_require__(181);
+
+var _cmap = __w_pdfjs_require__(173);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var _stream = __w_pdfjs_require__(158);
+
+var _type1_parser = __w_pdfjs_require__(182);
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+var PRIVATE_USE_AREAS = [[0xE000, 0xF8FF], [0x100000, 0x10FFFD]];
+var PDF_GLYPH_SPACE_UNITS = 1000;
+var SEAC_ANALYSIS_ENABLED = true;
+exports.SEAC_ANALYSIS_ENABLED = SEAC_ANALYSIS_ENABLED;
+var FontFlags = {
+  FixedPitch: 1,
+  Serif: 2,
+  Symbolic: 4,
+  Script: 8,
+  Nonsymbolic: 32,
+  Italic: 64,
+  AllCap: 65536,
+  SmallCap: 131072,
+  ForceBold: 262144
+};
+exports.FontFlags = FontFlags;
+var MacStandardGlyphOrdering = ['.notdef', '.null', 'nonmarkingreturn', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', 'nonbreakingspace', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'Lslash', 'lslash', 'Scaron', 'scaron', 'Zcaron', 'zcaron', 'brokenbar', 'Eth', 'eth', 'Yacute', 'yacute', 'Thorn', 'thorn', 'minus', 'multiply', 'onesuperior', 'twosuperior', 'threesuperior', 'onehalf', 'onequarter', 'threequarters', 'franc', 'Gbreve', 'gbreve', 'Idotaccent', 'Scedilla', 'scedilla', 'Cacute', 'cacute', 'Ccaron', 'ccaron', 'dcroat'];
+
+function adjustWidths(properties) {
+  if (!properties.fontMatrix) {
+    return;
+  }
+
+  if (properties.fontMatrix[0] === _util.FONT_IDENTITY_MATRIX[0]) {
+    return;
+  }
+
+  var scale = 0.001 / properties.fontMatrix[0];
+  var glyphsWidths = properties.widths;
+
+  for (var glyph in glyphsWidths) {
+    glyphsWidths[glyph] *= scale;
+  }
+
+  properties.defaultWidth *= scale;
+}
+
+function adjustToUnicode(properties, builtInEncoding) {
+  if (properties.hasIncludedToUnicodeMap) {
+    return;
+  }
+
+  if (properties.hasEncoding) {
+    return;
+  }
+
+  if (builtInEncoding === properties.defaultEncoding) {
+    return;
+  }
+
+  if (properties.toUnicode instanceof IdentityToUnicodeMap) {
+    return;
+  }
+
+  var toUnicode = [],
+      glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+
+  for (var charCode in builtInEncoding) {
+    var glyphName = builtInEncoding[charCode];
+    var unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
+
+    if (unicode !== -1) {
+      toUnicode[charCode] = String.fromCharCode(unicode);
+    }
+  }
+
+  properties.toUnicode.amend(toUnicode);
+}
+
+function getFontType(type, subtype) {
+  switch (type) {
+    case 'Type1':
+      return subtype === 'Type1C' ? _util.FontType.TYPE1C : _util.FontType.TYPE1;
+
+    case 'CIDFontType0':
+      return subtype === 'CIDFontType0C' ? _util.FontType.CIDFONTTYPE0C : _util.FontType.CIDFONTTYPE0;
+
+    case 'OpenType':
+      return _util.FontType.OPENTYPE;
+
+    case 'TrueType':
+      return _util.FontType.TRUETYPE;
+
+    case 'CIDFontType2':
+      return _util.FontType.CIDFONTTYPE2;
+
+    case 'MMType1':
+      return _util.FontType.MMTYPE1;
+
+    case 'Type0':
+      return _util.FontType.TYPE0;
+
+    default:
+      return _util.FontType.UNKNOWN;
+  }
+}
+
+function recoverGlyphName(name, glyphsUnicodeMap) {
+  if (glyphsUnicodeMap[name] !== undefined) {
+    return name;
+  }
+
+  var unicode = (0, _unicode.getUnicodeForGlyph)(name, glyphsUnicodeMap);
+
+  if (unicode !== -1) {
+    for (var key in glyphsUnicodeMap) {
+      if (glyphsUnicodeMap[key] === unicode) {
+        return key;
+      }
+    }
+  }
+
+  (0, _util.info)('Unable to recover a standard glyph name for: ' + name);
+  return name;
+}
+
+var Glyph = function GlyphClosure() {
+  function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
+    this.fontChar = fontChar;
+    this.unicode = unicode;
+    this.accent = accent;
+    this.width = width;
+    this.vmetric = vmetric;
+    this.operatorListId = operatorListId;
+    this.isSpace = isSpace;
+    this.isInFont = isInFont;
+  }
+
+  Glyph.prototype.matchesForCache = function (fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont) {
+    return this.fontChar === fontChar && this.unicode === unicode && this.accent === accent && this.width === width && this.vmetric === vmetric && this.operatorListId === operatorListId && this.isSpace === isSpace && this.isInFont === isInFont;
+  };
+
+  return Glyph;
+}();
+
+var ToUnicodeMap = function ToUnicodeMapClosure() {
+  function ToUnicodeMap() {
+    var cmap = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : [];
+    this._map = cmap;
+  }
+
+  ToUnicodeMap.prototype = {
+    get length() {
+      return this._map.length;
+    },
+
+    forEach: function forEach(callback) {
+      for (var charCode in this._map) {
+        callback(charCode, this._map[charCode].charCodeAt(0));
+      }
+    },
+    has: function has(i) {
+      return this._map[i] !== undefined;
+    },
+    get: function get(i) {
+      return this._map[i];
+    },
+    charCodeOf: function charCodeOf(value) {
+      var map = this._map;
+
+      if (map.length <= 0x10000) {
+        return map.indexOf(value);
+      }
+
+      for (var charCode in map) {
+        if (map[charCode] === value) {
+          return charCode | 0;
+        }
+      }
+
+      return -1;
+    },
+    amend: function amend(map) {
+      for (var charCode in map) {
+        this._map[charCode] = map[charCode];
+      }
+    }
+  };
+  return ToUnicodeMap;
+}();
+
+exports.ToUnicodeMap = ToUnicodeMap;
+
+var IdentityToUnicodeMap = function IdentityToUnicodeMapClosure() {
+  function IdentityToUnicodeMap(firstChar, lastChar) {
+    this.firstChar = firstChar;
+    this.lastChar = lastChar;
+  }
+
+  IdentityToUnicodeMap.prototype = {
+    get length() {
+      return this.lastChar + 1 - this.firstChar;
+    },
+
+    forEach: function forEach(callback) {
+      for (var i = this.firstChar, ii = this.lastChar; i <= ii; i++) {
+        callback(i, i);
+      }
+    },
+    has: function has(i) {
+      return this.firstChar <= i && i <= this.lastChar;
+    },
+    get: function get(i) {
+      if (this.firstChar <= i && i <= this.lastChar) {
+        return String.fromCharCode(i);
+      }
+
+      return undefined;
+    },
+    charCodeOf: function charCodeOf(v) {
+      return Number.isInteger(v) && v >= this.firstChar && v <= this.lastChar ? v : -1;
+    },
+    amend: function amend(map) {
+      (0, _util.unreachable)('Should not call amend()');
+    }
+  };
+  return IdentityToUnicodeMap;
+}();
+
+exports.IdentityToUnicodeMap = IdentityToUnicodeMap;
+
+var OpenTypeFileBuilder = function OpenTypeFileBuilderClosure() {
+  function writeInt16(dest, offset, num) {
+    dest[offset] = num >> 8 & 0xFF;
+    dest[offset + 1] = num & 0xFF;
+  }
+
+  function writeInt32(dest, offset, num) {
+    dest[offset] = num >> 24 & 0xFF;
+    dest[offset + 1] = num >> 16 & 0xFF;
+    dest[offset + 2] = num >> 8 & 0xFF;
+    dest[offset + 3] = num & 0xFF;
+  }
+
+  function writeData(dest, offset, data) {
+    var i, ii;
+
+    if (data instanceof Uint8Array) {
+      dest.set(data, offset);
+    } else if (typeof data === 'string') {
+      for (i = 0, ii = data.length; i < ii; i++) {
+        dest[offset++] = data.charCodeAt(i) & 0xFF;
+      }
+    } else {
+      for (i = 0, ii = data.length; i < ii; i++) {
+        dest[offset++] = data[i] & 0xFF;
+      }
+    }
+  }
+
+  function OpenTypeFileBuilder(sfnt) {
+    this.sfnt = sfnt;
+    this.tables = Object.create(null);
+  }
+
+  OpenTypeFileBuilder.getSearchParams = function OpenTypeFileBuilder_getSearchParams(entriesCount, entrySize) {
+    var maxPower2 = 1,
+        log2 = 0;
+
+    while ((maxPower2 ^ entriesCount) > maxPower2) {
+      maxPower2 <<= 1;
+      log2++;
+    }
+
+    var searchRange = maxPower2 * entrySize;
+    return {
+      range: searchRange,
+      entry: log2,
+      rangeShift: entrySize * entriesCount - searchRange
+    };
+  };
+
+  var OTF_HEADER_SIZE = 12;
+  var OTF_TABLE_ENTRY_SIZE = 16;
+  OpenTypeFileBuilder.prototype = {
+    toArray: function OpenTypeFileBuilder_toArray() {
+      var sfnt = this.sfnt;
+      var tables = this.tables;
+      var tablesNames = Object.keys(tables);
+      tablesNames.sort();
+      var numTables = tablesNames.length;
+      var i, j, jj, table, tableName;
+      var offset = OTF_HEADER_SIZE + numTables * OTF_TABLE_ENTRY_SIZE;
+      var tableOffsets = [offset];
+
+      for (i = 0; i < numTables; i++) {
+        table = tables[tablesNames[i]];
+        var paddedLength = (table.length + 3 & ~3) >>> 0;
+        offset += paddedLength;
+        tableOffsets.push(offset);
+      }
+
+      var file = new Uint8Array(offset);
+
+      for (i = 0; i < numTables; i++) {
+        table = tables[tablesNames[i]];
+        writeData(file, tableOffsets[i], table);
+      }
+
+      if (sfnt === 'true') {
+        sfnt = (0, _util.string32)(0x00010000);
+      }
+
+      file[0] = sfnt.charCodeAt(0) & 0xFF;
+      file[1] = sfnt.charCodeAt(1) & 0xFF;
+      file[2] = sfnt.charCodeAt(2) & 0xFF;
+      file[3] = sfnt.charCodeAt(3) & 0xFF;
+      writeInt16(file, 4, numTables);
+      var searchParams = OpenTypeFileBuilder.getSearchParams(numTables, 16);
+      writeInt16(file, 6, searchParams.range);
+      writeInt16(file, 8, searchParams.entry);
+      writeInt16(file, 10, searchParams.rangeShift);
+      offset = OTF_HEADER_SIZE;
+
+      for (i = 0; i < numTables; i++) {
+        tableName = tablesNames[i];
+        file[offset] = tableName.charCodeAt(0) & 0xFF;
+        file[offset + 1] = tableName.charCodeAt(1) & 0xFF;
+        file[offset + 2] = tableName.charCodeAt(2) & 0xFF;
+        file[offset + 3] = tableName.charCodeAt(3) & 0xFF;
+        var checksum = 0;
+
+        for (j = tableOffsets[i], jj = tableOffsets[i + 1]; j < jj; j += 4) {
+          var quad = (0, _util.readUint32)(file, j);
+          checksum = checksum + quad >>> 0;
+        }
+
+        writeInt32(file, offset + 4, checksum);
+        writeInt32(file, offset + 8, tableOffsets[i]);
+        writeInt32(file, offset + 12, tables[tableName].length);
+        offset += OTF_TABLE_ENTRY_SIZE;
+      }
+
+      return file;
+    },
+    addTable: function OpenTypeFileBuilder_addTable(tag, data) {
+      if (tag in this.tables) {
+        throw new Error('Table ' + tag + ' already exists');
+      }
+
+      this.tables[tag] = data;
+    }
+  };
+  return OpenTypeFileBuilder;
+}();
+
+var Font = function FontClosure() {
+  function Font(name, file, properties) {
+    var charCode;
+    this.name = name;
+    this.loadedName = properties.loadedName;
+    this.isType3Font = properties.isType3Font;
+    this.sizes = [];
+    this.missingFile = false;
+    this.glyphCache = Object.create(null);
+    this.isSerifFont = !!(properties.flags & FontFlags.Serif);
+    this.isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
+    this.isMonospace = !!(properties.flags & FontFlags.FixedPitch);
+    var type = properties.type;
+    var subtype = properties.subtype;
+    this.type = type;
+    this.subtype = subtype;
+    this.fallbackName = this.isMonospace ? 'monospace' : this.isSerifFont ? 'serif' : 'sans-serif';
+    this.differences = properties.differences;
+    this.widths = properties.widths;
+    this.defaultWidth = properties.defaultWidth;
+    this.composite = properties.composite;
+    this.wideChars = properties.wideChars;
+    this.cMap = properties.cMap;
+    this.ascent = properties.ascent / PDF_GLYPH_SPACE_UNITS;
+    this.descent = properties.descent / PDF_GLYPH_SPACE_UNITS;
+    this.fontMatrix = properties.fontMatrix;
+    this.bbox = properties.bbox;
+    this.defaultEncoding = properties.defaultEncoding;
+    this.toUnicode = properties.toUnicode;
+    this.fallbackToUnicode = properties.fallbackToUnicode || new ToUnicodeMap();
+    this.toFontChar = [];
+
+    if (properties.type === 'Type3') {
+      for (charCode = 0; charCode < 256; charCode++) {
+        this.toFontChar[charCode] = this.differences[charCode] || properties.defaultEncoding[charCode];
+      }
+
+      this.fontType = _util.FontType.TYPE3;
+      return;
+    }
+
+    this.cidEncoding = properties.cidEncoding;
+    this.vertical = properties.vertical;
+
+    if (this.vertical) {
+      this.vmetrics = properties.vmetrics;
+      this.defaultVMetrics = properties.defaultVMetrics;
+    }
+
+    if (!file || file.isEmpty) {
+      if (file) {
+        (0, _util.warn)('Font file is empty in "' + name + '" (' + this.loadedName + ')');
+      }
+
+      this.fallbackToSystemFont();
+      return;
+    }
+
+    var _getFontFileType = getFontFileType(file, properties);
+
+    var _getFontFileType2 = _slicedToArray(_getFontFileType, 2);
+
+    type = _getFontFileType2[0];
+    subtype = _getFontFileType2[1];
+
+    if (type !== this.type || subtype !== this.subtype) {
+      (0, _util.info)('Inconsistent font file Type/SubType, expected: ' + "".concat(this.type, "/").concat(this.subtype, " but found: ").concat(type, "/").concat(subtype, "."));
+    }
+
+    try {
+      var data;
+
+      switch (type) {
+        case 'MMType1':
+          (0, _util.info)('MMType1 font (' + name + '), falling back to Type1.');
+
+        case 'Type1':
+        case 'CIDFontType0':
+          this.mimetype = 'font/opentype';
+          var cff = subtype === 'Type1C' || subtype === 'CIDFontType0C' ? new CFFFont(file, properties) : new Type1Font(name, file, properties);
+          adjustWidths(properties);
+          data = this.convert(name, cff, properties);
+          break;
+
+        case 'OpenType':
+        case 'TrueType':
+        case 'CIDFontType2':
+          this.mimetype = 'font/opentype';
+          data = this.checkAndRepair(name, file, properties);
+
+          if (this.isOpenType) {
+            adjustWidths(properties);
+            type = 'OpenType';
+          }
+
+          break;
+
+        default:
+          throw new _util.FormatError("Font ".concat(type, " is not supported"));
+      }
+    } catch (e) {
+      (0, _util.warn)(e);
+      this.fallbackToSystemFont();
+      return;
+    }
+
+    this.data = data;
+    this.fontType = getFontType(type, subtype);
+    this.fontMatrix = properties.fontMatrix;
+    this.widths = properties.widths;
+    this.defaultWidth = properties.defaultWidth;
+    this.toUnicode = properties.toUnicode;
+    this.encoding = properties.baseEncoding;
+    this.seacMap = properties.seacMap;
+  }
+
+  Font.getFontID = function () {
+    var ID = 1;
+    return function Font_getFontID() {
+      return String(ID++);
+    };
+  }();
+
+  function int16(b0, b1) {
+    return (b0 << 8) + b1;
+  }
+
+  function writeSignedInt16(bytes, index, value) {
+    bytes[index + 1] = value;
+    bytes[index] = value >>> 8;
+  }
+
+  function signedInt16(b0, b1) {
+    var value = (b0 << 8) + b1;
+    return value & 1 << 15 ? value - 0x10000 : value;
+  }
+
+  function int32(b0, b1, b2, b3) {
+    return (b0 << 24) + (b1 << 16) + (b2 << 8) + b3;
+  }
+
+  function string16(value) {
+    return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
+  }
+
+  function safeString16(value) {
+    value = value > 0x7FFF ? 0x7FFF : value < -0x8000 ? -0x8000 : value;
+    return String.fromCharCode(value >> 8 & 0xff, value & 0xff);
+  }
+
+  function isTrueTypeFile(file) {
+    var header = file.peekBytes(4);
+    return (0, _util.readUint32)(header, 0) === 0x00010000 || (0, _util.bytesToString)(header) === 'true';
+  }
+
+  function isTrueTypeCollectionFile(file) {
+    var header = file.peekBytes(4);
+    return (0, _util.bytesToString)(header) === 'ttcf';
+  }
+
+  function isOpenTypeFile(file) {
+    var header = file.peekBytes(4);
+    return (0, _util.bytesToString)(header) === 'OTTO';
+  }
+
+  function isType1File(file) {
+    var header = file.peekBytes(2);
+
+    if (header[0] === 0x25 && header[1] === 0x21) {
+      return true;
+    }
+
+    if (header[0] === 0x80 && header[1] === 0x01) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function isCFFFile(file) {
+    var header = file.peekBytes(4);
+
+    if (header[0] >= 1 && header[3] >= 1 && header[3] <= 4) {
+      return true;
+    }
+
+    return false;
+  }
+
+  function getFontFileType(file, _ref) {
+    var type = _ref.type,
+        subtype = _ref.subtype,
+        composite = _ref.composite;
+    var fileType, fileSubtype;
+
+    if (isTrueTypeFile(file) || isTrueTypeCollectionFile(file)) {
+      if (composite) {
+        fileType = 'CIDFontType2';
+      } else {
+        fileType = 'TrueType';
+      }
+    } else if (isOpenTypeFile(file)) {
+      if (composite) {
+        fileType = 'CIDFontType2';
+      } else {
+        fileType = 'OpenType';
+      }
+    } else if (isType1File(file)) {
+      if (composite) {
+        fileType = 'CIDFontType0';
+      } else {
+        fileType = type === 'MMType1' ? 'MMType1' : 'Type1';
+      }
+    } else if (isCFFFile(file)) {
+      if (composite) {
+        fileType = 'CIDFontType0';
+        fileSubtype = 'CIDFontType0C';
+      } else {
+        fileType = type === 'MMType1' ? 'MMType1' : 'Type1';
+        fileSubtype = 'Type1C';
+      }
+    } else {
+      (0, _util.warn)('getFontFileType: Unable to detect correct font file Type/Subtype.');
+      fileType = type;
+      fileSubtype = subtype;
+    }
+
+    return [fileType, fileSubtype];
+  }
+
+  function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
+    var toFontChar = [],
+        unicode;
+
+    for (var i = 0, ii = encoding.length; i < ii; i++) {
+      unicode = (0, _unicode.getUnicodeForGlyph)(encoding[i], glyphsUnicodeMap);
+
+      if (unicode !== -1) {
+        toFontChar[i] = unicode;
+      }
+    }
+
+    for (var charCode in differences) {
+      unicode = (0, _unicode.getUnicodeForGlyph)(differences[charCode], glyphsUnicodeMap);
+
+      if (unicode !== -1) {
+        toFontChar[+charCode] = unicode;
+      }
+    }
+
+    return toFontChar;
+  }
+
+  function adjustMapping(charCodeToGlyphId, hasGlyph, newGlyphZeroId) {
+    var newMap = Object.create(null);
+    var toFontChar = [];
+    var privateUseAreaIndex = 0;
+    var nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
+    var privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
+
+    for (var originalCharCode in charCodeToGlyphId) {
+      originalCharCode |= 0;
+      var glyphId = charCodeToGlyphId[originalCharCode];
+
+      if (!hasGlyph(glyphId)) {
+        continue;
+      }
+
+      if (nextAvailableFontCharCode > privateUseOffetEnd) {
+        privateUseAreaIndex++;
+
+        if (privateUseAreaIndex >= PRIVATE_USE_AREAS.length) {
+          (0, _util.warn)('Ran out of space in font private use area.');
+          break;
+        }
+
+        nextAvailableFontCharCode = PRIVATE_USE_AREAS[privateUseAreaIndex][0];
+        privateUseOffetEnd = PRIVATE_USE_AREAS[privateUseAreaIndex][1];
+      }
+
+      var fontCharCode = nextAvailableFontCharCode++;
+
+      if (glyphId === 0) {
+        glyphId = newGlyphZeroId;
+      }
+
+      newMap[fontCharCode] = glyphId;
+      toFontChar[originalCharCode] = fontCharCode;
+    }
+
+    return {
+      toFontChar: toFontChar,
+      charCodeToGlyphId: newMap,
+      nextAvailableFontCharCode: nextAvailableFontCharCode
+    };
+  }
+
+  function getRanges(glyphs, numGlyphs) {
+    var codes = [];
+
+    for (var charCode in glyphs) {
+      if (glyphs[charCode] >= numGlyphs) {
+        continue;
+      }
+
+      codes.push({
+        fontCharCode: charCode | 0,
+        glyphId: glyphs[charCode]
+      });
+    }
+
+    if (codes.length === 0) {
+      codes.push({
+        fontCharCode: 0,
+        glyphId: 0
+      });
+    }
+
+    codes.sort(function fontGetRangesSort(a, b) {
+      return a.fontCharCode - b.fontCharCode;
+    });
+    var ranges = [];
+    var length = codes.length;
+
+    for (var n = 0; n < length;) {
+      var start = codes[n].fontCharCode;
+      var codeIndices = [codes[n].glyphId];
+      ++n;
+      var end = start;
+
+      while (n < length && end + 1 === codes[n].fontCharCode) {
+        codeIndices.push(codes[n].glyphId);
+        ++end;
+        ++n;
+
+        if (end === 0xFFFF) {
+          break;
+        }
+      }
+
+      ranges.push([start, end, codeIndices]);
+    }
+
+    return ranges;
+  }
+
+  function createCmapTable(glyphs, numGlyphs) {
+    var ranges = getRanges(glyphs, numGlyphs);
+    var numTables = ranges[ranges.length - 1][1] > 0xFFFF ? 2 : 1;
+    var cmap = '\x00\x00' + string16(numTables) + '\x00\x03' + '\x00\x01' + (0, _util.string32)(4 + numTables * 8);
+    var i, ii, j, jj;
+
+    for (i = ranges.length - 1; i >= 0; --i) {
+      if (ranges[i][0] <= 0xFFFF) {
+        break;
+      }
+    }
+
+    var bmpLength = i + 1;
+
+    if (ranges[i][0] < 0xFFFF && ranges[i][1] === 0xFFFF) {
+      ranges[i][1] = 0xFFFE;
+    }
+
+    var trailingRangesCount = ranges[i][1] < 0xFFFF ? 1 : 0;
+    var segCount = bmpLength + trailingRangesCount;
+    var searchParams = OpenTypeFileBuilder.getSearchParams(segCount, 2);
+    var startCount = '';
+    var endCount = '';
+    var idDeltas = '';
+    var idRangeOffsets = '';
+    var glyphsIds = '';
+    var bias = 0;
+    var range, start, end, codes;
+
+    for (i = 0, ii = bmpLength; i < ii; i++) {
+      range = ranges[i];
+      start = range[0];
+      end = range[1];
+      startCount += string16(start);
+      endCount += string16(end);
+      codes = range[2];
+      var contiguous = true;
+
+      for (j = 1, jj = codes.length; j < jj; ++j) {
+        if (codes[j] !== codes[j - 1] + 1) {
+          contiguous = false;
+          break;
+        }
+      }
+
+      if (!contiguous) {
+        var offset = (segCount - i) * 2 + bias * 2;
+        bias += end - start + 1;
+        idDeltas += string16(0);
+        idRangeOffsets += string16(offset);
+
+        for (j = 0, jj = codes.length; j < jj; ++j) {
+          glyphsIds += string16(codes[j]);
+        }
+      } else {
+        var startCode = codes[0];
+        idDeltas += string16(startCode - start & 0xFFFF);
+        idRangeOffsets += string16(0);
+      }
+    }
+
+    if (trailingRangesCount > 0) {
+      endCount += '\xFF\xFF';
+      startCount += '\xFF\xFF';
+      idDeltas += '\x00\x01';
+      idRangeOffsets += '\x00\x00';
+    }
+
+    var format314 = '\x00\x00' + string16(2 * segCount) + string16(searchParams.range) + string16(searchParams.entry) + string16(searchParams.rangeShift) + endCount + '\x00\x00' + startCount + idDeltas + idRangeOffsets + glyphsIds;
+    var format31012 = '';
+    var header31012 = '';
+
+    if (numTables > 1) {
+      cmap += '\x00\x03' + '\x00\x0A' + (0, _util.string32)(4 + numTables * 8 + 4 + format314.length);
+      format31012 = '';
+
+      for (i = 0, ii = ranges.length; i < ii; i++) {
+        range = ranges[i];
+        start = range[0];
+        codes = range[2];
+        var code = codes[0];
+
+        for (j = 1, jj = codes.length; j < jj; ++j) {
+          if (codes[j] !== codes[j - 1] + 1) {
+            end = range[0] + j - 1;
+            format31012 += (0, _util.string32)(start) + (0, _util.string32)(end) + (0, _util.string32)(code);
+            start = end + 1;
+            code = codes[j];
+          }
+        }
+
+        format31012 += (0, _util.string32)(start) + (0, _util.string32)(range[1]) + (0, _util.string32)(code);
+      }
+
+      header31012 = '\x00\x0C' + '\x00\x00' + (0, _util.string32)(format31012.length + 16) + '\x00\x00\x00\x00' + (0, _util.string32)(format31012.length / 12);
+    }
+
+    return cmap + '\x00\x04' + string16(format314.length + 4) + format314 + header31012 + format31012;
+  }
+
+  function validateOS2Table(os2) {
+    var stream = new _stream.Stream(os2.data);
+    var version = stream.getUint16();
+    stream.getBytes(60);
+    var selection = stream.getUint16();
+
+    if (version < 4 && selection & 0x0300) {
+      return false;
+    }
+
+    var firstChar = stream.getUint16();
+    var lastChar = stream.getUint16();
+
+    if (firstChar > lastChar) {
+      return false;
+    }
+
+    stream.getBytes(6);
+    var usWinAscent = stream.getUint16();
+
+    if (usWinAscent === 0) {
+      return false;
+    }
+
+    os2.data[8] = os2.data[9] = 0;
+    return true;
+  }
+
+  function createOS2Table(properties, charstrings, override) {
+    override = override || {
+      unitsPerEm: 0,
+      yMax: 0,
+      yMin: 0,
+      ascent: 0,
+      descent: 0
+    };
+    var ulUnicodeRange1 = 0;
+    var ulUnicodeRange2 = 0;
+    var ulUnicodeRange3 = 0;
+    var ulUnicodeRange4 = 0;
+    var firstCharIndex = null;
+    var lastCharIndex = 0;
+
+    if (charstrings) {
+      for (var code in charstrings) {
+        code |= 0;
+
+        if (firstCharIndex > code || !firstCharIndex) {
+          firstCharIndex = code;
+        }
+
+        if (lastCharIndex < code) {
+          lastCharIndex = code;
+        }
+
+        var position = (0, _unicode.getUnicodeRangeFor)(code);
+
+        if (position < 32) {
+          ulUnicodeRange1 |= 1 << position;
+        } else if (position < 64) {
+          ulUnicodeRange2 |= 1 << position - 32;
+        } else if (position < 96) {
+          ulUnicodeRange3 |= 1 << position - 64;
+        } else if (position < 123) {
+          ulUnicodeRange4 |= 1 << position - 96;
+        } else {
+          throw new _util.FormatError('Unicode ranges Bits > 123 are reserved for internal usage');
+        }
+      }
+
+      if (lastCharIndex > 0xFFFF) {
+        lastCharIndex = 0xFFFF;
+      }
+    } else {
+      firstCharIndex = 0;
+      lastCharIndex = 255;
+    }
+
+    var bbox = properties.bbox || [0, 0, 0, 0];
+    var unitsPerEm = override.unitsPerEm || 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0];
+    var scale = properties.ascentScaled ? 1.0 : unitsPerEm / PDF_GLYPH_SPACE_UNITS;
+    var typoAscent = override.ascent || Math.round(scale * (properties.ascent || bbox[3]));
+    var typoDescent = override.descent || Math.round(scale * (properties.descent || bbox[1]));
+
+    if (typoDescent > 0 && properties.descent > 0 && bbox[1] < 0) {
+      typoDescent = -typoDescent;
+    }
+
+    var winAscent = override.yMax || typoAscent;
+    var winDescent = -override.yMin || -typoDescent;
+    return '\x00\x03' + '\x02\x24' + '\x01\xF4' + '\x00\x05' + '\x00\x00' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x00\x8C' + '\x02\x8A' + '\x02\xBB' + '\x00\x00' + '\x01\xDF' + '\x00\x31' + '\x01\x02' + '\x00\x00' + '\x00\x00\x06' + String.fromCharCode(properties.fixedPitch ? 0x09 : 0x00) + '\x00\x00\x00\x00\x00\x00' + (0, _util.string32)(ulUnicodeRange1) + (0, _util.string32)(ulUnicodeRange2) + (0, _util.string32)(ulUnicodeRange3) + (0, _util.string32)(ulUnicodeRange4) + '\x2A\x32\x31\x2A' + string16(properties.italicAngle ? 1 : 0) + string16(firstCharIndex || properties.firstChar) + string16(lastCharIndex || properties.lastChar) + string16(typoAscent) + string16(typoDescent) + '\x00\x64' + string16(winAscent) + string16(winDescent) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + string16(properties.xHeight) + string16(properties.capHeight) + string16(0) + string16(firstCharIndex || properties.firstChar) + '\x00\x03';
+  }
+
+  function createPostTable(properties) {
+    var angle = Math.floor(properties.italicAngle * Math.pow(2, 16));
+    return '\x00\x03\x00\x00' + (0, _util.string32)(angle) + '\x00\x00' + '\x00\x00' + (0, _util.string32)(properties.fixedPitch) + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00' + '\x00\x00\x00\x00';
+  }
+
+  function createNameTable(name, proto) {
+    if (!proto) {
+      proto = [[], []];
+    }
+
+    var strings = [proto[0][0] || 'Original licence', proto[0][1] || name, proto[0][2] || 'Unknown', proto[0][3] || 'uniqueID', proto[0][4] || name, proto[0][5] || 'Version 0.11', proto[0][6] || '', proto[0][7] || 'Unknown', proto[0][8] || 'Unknown', proto[0][9] || 'Unknown'];
+    var stringsUnicode = [];
+    var i, ii, j, jj, str;
+
+    for (i = 0, ii = strings.length; i < ii; i++) {
+      str = proto[1][i] || strings[i];
+      var strBufUnicode = [];
+
+      for (j = 0, jj = str.length; j < jj; j++) {
+        strBufUnicode.push(string16(str.charCodeAt(j)));
+      }
+
+      stringsUnicode.push(strBufUnicode.join(''));
+    }
+
+    var names = [strings, stringsUnicode];
+    var platforms = ['\x00\x01', '\x00\x03'];
+    var encodings = ['\x00\x00', '\x00\x01'];
+    var languages = ['\x00\x00', '\x04\x09'];
+    var namesRecordCount = strings.length * platforms.length;
+    var nameTable = '\x00\x00' + string16(namesRecordCount) + string16(namesRecordCount * 12 + 6);
+    var strOffset = 0;
+
+    for (i = 0, ii = platforms.length; i < ii; i++) {
+      var strs = names[i];
+
+      for (j = 0, jj = strs.length; j < jj; j++) {
+        str = strs[j];
+        var nameRecord = platforms[i] + encodings[i] + languages[i] + string16(j) + string16(str.length) + string16(strOffset);
+        nameTable += nameRecord;
+        strOffset += str.length;
+      }
+    }
+
+    nameTable += strings.join('') + stringsUnicode.join('');
+    return nameTable;
+  }
+
+  Font.prototype = {
+    name: null,
+    font: null,
+    mimetype: null,
+    encoding: null,
+    disableFontFace: false,
+
+    get renderer() {
+      var renderer = _font_renderer.FontRendererFactory.create(this, SEAC_ANALYSIS_ENABLED);
+
+      return (0, _util.shadow)(this, 'renderer', renderer);
+    },
+
+    exportData: function Font_exportData() {
+      var data = {};
+
+      for (var i in this) {
+        if (this.hasOwnProperty(i)) {
+          data[i] = this[i];
+        }
+      }
+
+      return data;
+    },
+    fallbackToSystemFont: function Font_fallbackToSystemFont() {
+      var _this = this;
+
+      this.missingFile = true;
+      var charCode, unicode;
+      var name = this.name;
+      var type = this.type;
+      var subtype = this.subtype;
+      var fontName = name.replace(/[,_]/g, '-');
+      var stdFontMap = (0, _standard_fonts.getStdFontMap)(),
+          nonStdFontMap = (0, _standard_fonts.getNonStdFontMap)();
+      var isStandardFont = !!stdFontMap[fontName] || !!(nonStdFontMap[fontName] && stdFontMap[nonStdFontMap[fontName]]);
+      fontName = stdFontMap[fontName] || nonStdFontMap[fontName] || fontName;
+      this.bold = fontName.search(/bold/gi) !== -1;
+      this.italic = fontName.search(/oblique/gi) !== -1 || fontName.search(/italic/gi) !== -1;
+      this.black = name.search(/Black/g) !== -1;
+      this.remeasure = Object.keys(this.widths).length > 0;
+
+      if (isStandardFont && type === 'CIDFontType2' && this.cidEncoding.startsWith('Identity-')) {
+        var GlyphMapForStandardFonts = (0, _standard_fonts.getGlyphMapForStandardFonts)();
+        var map = [];
+
+        for (charCode in GlyphMapForStandardFonts) {
+          map[+charCode] = GlyphMapForStandardFonts[charCode];
+        }
+
+        if (/Arial-?Black/i.test(name)) {
+          var SupplementalGlyphMapForArialBlack = (0, _standard_fonts.getSupplementalGlyphMapForArialBlack)();
+
+          for (charCode in SupplementalGlyphMapForArialBlack) {
+            map[+charCode] = SupplementalGlyphMapForArialBlack[charCode];
+          }
+        } else if (/Calibri/i.test(name)) {
+          var SupplementalGlyphMapForCalibri = (0, _standard_fonts.getSupplementalGlyphMapForCalibri)();
+
+          for (charCode in SupplementalGlyphMapForCalibri) {
+            map[+charCode] = SupplementalGlyphMapForCalibri[charCode];
+          }
+        }
+
+        var isIdentityUnicode = this.toUnicode instanceof IdentityToUnicodeMap;
+
+        if (!isIdentityUnicode) {
+          this.toUnicode.forEach(function (charCode, unicodeCharCode) {
+            map[+charCode] = unicodeCharCode;
+          });
+        }
+
+        this.toFontChar = map;
+        this.toUnicode = new ToUnicodeMap(map);
+      } else if (/Symbol/i.test(fontName)) {
+        this.toFontChar = buildToFontChar(_encodings.SymbolSetEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences);
+      } else if (/Dingbats/i.test(fontName)) {
+        if (/Wingdings/i.test(name)) {
+          (0, _util.warn)('Non-embedded Wingdings font, falling back to ZapfDingbats.');
+        }
+
+        this.toFontChar = buildToFontChar(_encodings.ZapfDingbatsEncoding, (0, _glyphlist.getDingbatsGlyphsUnicode)(), this.differences);
+      } else if (isStandardFont) {
+        this.toFontChar = buildToFontChar(this.defaultEncoding, (0, _glyphlist.getGlyphsUnicode)(), this.differences);
+      } else {
+        var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+        this.toUnicode.forEach(function (charCode, unicodeCharCode) {
+          if (!_this.composite) {
+            var glyphName = _this.differences[charCode] || _this.defaultEncoding[charCode];
+            unicode = (0, _unicode.getUnicodeForGlyph)(glyphName, glyphsUnicodeMap);
+
+            if (unicode !== -1) {
+              unicodeCharCode = unicode;
+            }
+          }
+
+          _this.toFontChar[charCode] = unicodeCharCode;
+        });
+      }
+
+      this.loadedName = fontName.split('-')[0];
+      this.fontType = getFontType(type, subtype);
+    },
+    checkAndRepair: function Font_checkAndRepair(name, font, properties) {
+      var VALID_TABLES = ['OS/2', 'cmap', 'head', 'hhea', 'hmtx', 'maxp', 'name', 'post', 'loca', 'glyf', 'fpgm', 'prep', 'cvt ', 'CFF '];
+
+      function readTables(file, numTables) {
+        var tables = Object.create(null);
+        tables['OS/2'] = null;
+        tables['cmap'] = null;
+        tables['head'] = null;
+        tables['hhea'] = null;
+        tables['hmtx'] = null;
+        tables['maxp'] = null;
+        tables['name'] = null;
+        tables['post'] = null;
+
+        for (var i = 0; i < numTables; i++) {
+          var table = readTableEntry(font);
+
+          if (!VALID_TABLES.includes(table.tag)) {
+            continue;
+          }
+
+          if (table.length === 0) {
+            continue;
+          }
+
+          tables[table.tag] = table;
+        }
+
+        return tables;
+      }
+
+      function readTableEntry(file) {
+        var tag = (0, _util.bytesToString)(file.getBytes(4));
+        var checksum = file.getInt32() >>> 0;
+        var offset = file.getInt32() >>> 0;
+        var length = file.getInt32() >>> 0;
+        var previousPosition = file.pos;
+        file.pos = file.start ? file.start : 0;
+        file.skip(offset);
+        var data = file.getBytes(length);
+        file.pos = previousPosition;
+
+        if (tag === 'head') {
+          data[8] = data[9] = data[10] = data[11] = 0;
+          data[17] |= 0x20;
+        }
+
+        return {
+          tag: tag,
+          checksum: checksum,
+          length: length,
+          offset: offset,
+          data: data
+        };
+      }
+
+      function readOpenTypeHeader(ttf) {
+        return {
+          version: (0, _util.bytesToString)(ttf.getBytes(4)),
+          numTables: ttf.getUint16(),
+          searchRange: ttf.getUint16(),
+          entrySelector: ttf.getUint16(),
+          rangeShift: ttf.getUint16()
+        };
+      }
+
+      function readTrueTypeCollectionHeader(ttc) {
+        var ttcTag = (0, _util.bytesToString)(ttc.getBytes(4));
+        (0, _util.assert)(ttcTag === 'ttcf', 'Must be a TrueType Collection font.');
+        var majorVersion = ttc.getUint16();
+        var minorVersion = ttc.getUint16();
+        var numFonts = ttc.getInt32() >>> 0;
+        var offsetTable = [];
+
+        for (var i = 0; i < numFonts; i++) {
+          offsetTable.push(ttc.getInt32() >>> 0);
+        }
+
+        var header = {
+          ttcTag: ttcTag,
+          majorVersion: majorVersion,
+          minorVersion: minorVersion,
+          numFonts: numFonts,
+          offsetTable: offsetTable
+        };
+
+        switch (majorVersion) {
+          case 1:
+            return header;
+
+          case 2:
+            header.dsigTag = ttc.getInt32() >>> 0;
+            header.dsigLength = ttc.getInt32() >>> 0;
+            header.dsigOffset = ttc.getInt32() >>> 0;
+            return header;
+        }
+
+        throw new _util.FormatError("Invalid TrueType Collection majorVersion: ".concat(majorVersion, "."));
+      }
+
+      function readTrueTypeCollectionData(ttc, fontName) {
+        var _readTrueTypeCollecti = readTrueTypeCollectionHeader(ttc),
+            numFonts = _readTrueTypeCollecti.numFonts,
+            offsetTable = _readTrueTypeCollecti.offsetTable;
+
+        for (var i = 0; i < numFonts; i++) {
+          ttc.pos = (ttc.start || 0) + offsetTable[i];
+          var potentialHeader = readOpenTypeHeader(ttc);
+          var potentialTables = readTables(ttc, potentialHeader.numTables);
+
+          if (!potentialTables['name']) {
+            throw new _util.FormatError('TrueType Collection font must contain a "name" table.');
+          }
+
+          var nameTable = readNameTable(potentialTables['name']);
+
+          for (var j = 0, jj = nameTable.length; j < jj; j++) {
+            for (var k = 0, kk = nameTable[j].length; k < kk; k++) {
+              var nameEntry = nameTable[j][k];
+
+              if (nameEntry && nameEntry.replace(/\s/g, '') === fontName) {
+                return {
+                  header: potentialHeader,
+                  tables: potentialTables
+                };
+              }
+            }
+          }
+        }
+
+        throw new _util.FormatError("TrueType Collection does not contain \"".concat(fontName, "\" font."));
+      }
+
+      function readCmapTable(cmap, font, isSymbolicFont, hasEncoding) {
+        if (!cmap) {
+          (0, _util.warn)('No cmap table available.');
+          return {
+            platformId: -1,
+            encodingId: -1,
+            mappings: [],
+            hasShortCmap: false
+          };
+        }
+
+        var segment;
+        var start = (font.start ? font.start : 0) + cmap.offset;
+        font.pos = start;
+        font.getUint16();
+        var numTables = font.getUint16();
+        var potentialTable;
+        var canBreak = false;
+
+        for (var i = 0; i < numTables; i++) {
+          var platformId = font.getUint16();
+          var encodingId = font.getUint16();
+          var offset = font.getInt32() >>> 0;
+          var useTable = false;
+
+          if (potentialTable && potentialTable.platformId === platformId && potentialTable.encodingId === encodingId) {
+            continue;
+          }
+
+          if (platformId === 0 && encodingId === 0) {
+            useTable = true;
+          } else if (platformId === 1 && encodingId === 0) {
+            useTable = true;
+          } else if (platformId === 3 && encodingId === 1 && (hasEncoding || !potentialTable)) {
+            useTable = true;
+
+            if (!isSymbolicFont) {
+              canBreak = true;
+            }
+          } else if (isSymbolicFont && platformId === 3 && encodingId === 0) {
+            useTable = true;
+            canBreak = true;
+          }
+
+          if (useTable) {
+            potentialTable = {
+              platformId: platformId,
+              encodingId: encodingId,
+              offset: offset
+            };
+          }
+
+          if (canBreak) {
+            break;
+          }
+        }
+
+        if (potentialTable) {
+          font.pos = start + potentialTable.offset;
+        }
+
+        if (!potentialTable || font.peekByte() === -1) {
+          (0, _util.warn)('Could not find a preferred cmap table.');
+          return {
+            platformId: -1,
+            encodingId: -1,
+            mappings: [],
+            hasShortCmap: false
+          };
+        }
+
+        var format = font.getUint16();
+        font.getUint16();
+        font.getUint16();
+        var hasShortCmap = false;
+        var mappings = [];
+        var j, glyphId;
+
+        if (format === 0) {
+          for (j = 0; j < 256; j++) {
+            var index = font.getByte();
+
+            if (!index) {
+              continue;
+            }
+
+            mappings.push({
+              charCode: j,
+              glyphId: index
+            });
+          }
+
+          hasShortCmap = true;
+        } else if (format === 4) {
+          var segCount = font.getUint16() >> 1;
+          font.getBytes(6);
+          var segIndex,
+              segments = [];
+
+          for (segIndex = 0; segIndex < segCount; segIndex++) {
+            segments.push({
+              end: font.getUint16()
+            });
+          }
+
+          font.getUint16();
+
+          for (segIndex = 0; segIndex < segCount; segIndex++) {
+            segments[segIndex].start = font.getUint16();
+          }
+
+          for (segIndex = 0; segIndex < segCount; segIndex++) {
+            segments[segIndex].delta = font.getUint16();
+          }
+
+          var offsetsCount = 0;
+
+          for (segIndex = 0; segIndex < segCount; segIndex++) {
+            segment = segments[segIndex];
+            var rangeOffset = font.getUint16();
+
+            if (!rangeOffset) {
+              segment.offsetIndex = -1;
+              continue;
+            }
+
+            var offsetIndex = (rangeOffset >> 1) - (segCount - segIndex);
+            segment.offsetIndex = offsetIndex;
+            offsetsCount = Math.max(offsetsCount, offsetIndex + segment.end - segment.start + 1);
+          }
+
+          var offsets = [];
+
+          for (j = 0; j < offsetsCount; j++) {
+            offsets.push(font.getUint16());
+          }
+
+          for (segIndex = 0; segIndex < segCount; segIndex++) {
+            segment = segments[segIndex];
+            start = segment.start;
+            var end = segment.end;
+            var delta = segment.delta;
+            offsetIndex = segment.offsetIndex;
+
+            for (j = start; j <= end; j++) {
+              if (j === 0xFFFF) {
+                continue;
+              }
+
+              glyphId = offsetIndex < 0 ? j : offsets[offsetIndex + j - start];
+              glyphId = glyphId + delta & 0xFFFF;
+              mappings.push({
+                charCode: j,
+                glyphId: glyphId
+              });
+            }
+          }
+        } else if (format === 6) {
+          var firstCode = font.getUint16();
+          var entryCount = font.getUint16();
+
+          for (j = 0; j < entryCount; j++) {
+            glyphId = font.getUint16();
+            var charCode = firstCode + j;
+            mappings.push({
+              charCode: charCode,
+              glyphId: glyphId
+            });
+          }
+        } else {
+          (0, _util.warn)('cmap table has unsupported format: ' + format);
+          return {
+            platformId: -1,
+            encodingId: -1,
+            mappings: [],
+            hasShortCmap: false
+          };
+        }
+
+        mappings.sort(function (a, b) {
+          return a.charCode - b.charCode;
+        });
+
+        for (i = 1; i < mappings.length; i++) {
+          if (mappings[i - 1].charCode === mappings[i].charCode) {
+            mappings.splice(i, 1);
+            i--;
+          }
+        }
+
+        return {
+          platformId: potentialTable.platformId,
+          encodingId: potentialTable.encodingId,
+          mappings: mappings,
+          hasShortCmap: hasShortCmap
+        };
+      }
+
+      function sanitizeMetrics(font, header, metrics, numGlyphs, dupFirstEntry) {
+        if (!header) {
+          if (metrics) {
+            metrics.data = null;
+          }
+
+          return;
+        }
+
+        font.pos = (font.start ? font.start : 0) + header.offset;
+        font.pos += 4;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 2;
+        font.pos += 8;
+        font.pos += 2;
+        var numOfMetrics = font.getUint16();
+
+        if (numOfMetrics > numGlyphs) {
+          (0, _util.info)('The numOfMetrics (' + numOfMetrics + ') should not be ' + 'greater than the numGlyphs (' + numGlyphs + ')');
+          numOfMetrics = numGlyphs;
+          header.data[34] = (numOfMetrics & 0xff00) >> 8;
+          header.data[35] = numOfMetrics & 0x00ff;
+        }
+
+        var numOfSidebearings = numGlyphs - numOfMetrics;
+        var numMissing = numOfSidebearings - (metrics.length - numOfMetrics * 4 >> 1);
+
+        if (numMissing > 0) {
+          var entries = new Uint8Array(metrics.length + numMissing * 2);
+          entries.set(metrics.data);
+
+          if (dupFirstEntry) {
+            entries[metrics.length] = metrics.data[2];
+            entries[metrics.length + 1] = metrics.data[3];
+          }
+
+          metrics.data = entries;
+        }
+      }
+
+      function sanitizeGlyph(source, sourceStart, sourceEnd, dest, destStart, hintsValid) {
+        var glyphProfile = {
+          length: 0,
+          sizeOfInstructions: 0
+        };
+
+        if (sourceEnd - sourceStart <= 12) {
+          return glyphProfile;
+        }
+
+        var glyf = source.subarray(sourceStart, sourceEnd);
+        var contoursCount = signedInt16(glyf[0], glyf[1]);
+
+        if (contoursCount < 0) {
+          contoursCount = -1;
+          writeSignedInt16(glyf, 0, contoursCount);
+          dest.set(glyf, destStart);
+          glyphProfile.length = glyf.length;
+          return glyphProfile;
+        }
+
+        var i,
+            j = 10,
+            flagsCount = 0;
+
+        for (i = 0; i < contoursCount; i++) {
+          var endPoint = glyf[j] << 8 | glyf[j + 1];
+          flagsCount = endPoint + 1;
+          j += 2;
+        }
+
+        var instructionsStart = j;
+        var instructionsLength = glyf[j] << 8 | glyf[j + 1];
+        glyphProfile.sizeOfInstructions = instructionsLength;
+        j += 2 + instructionsLength;
+        var instructionsEnd = j;
+        var coordinatesLength = 0;
+
+        for (i = 0; i < flagsCount; i++) {
+          var flag = glyf[j++];
+
+          if (flag & 0xC0) {
+            glyf[j - 1] = flag & 0x3F;
+          }
+
+          var xyLength = (flag & 2 ? 1 : flag & 16 ? 0 : 2) + (flag & 4 ? 1 : flag & 32 ? 0 : 2);
+          coordinatesLength += xyLength;
+
+          if (flag & 8) {
+            var repeat = glyf[j++];
+            i += repeat;
+            coordinatesLength += repeat * xyLength;
+          }
+        }
+
+        if (coordinatesLength === 0) {
+          return glyphProfile;
+        }
+
+        var glyphDataLength = j + coordinatesLength;
+
+        if (glyphDataLength > glyf.length) {
+          return glyphProfile;
+        }
+
+        if (!hintsValid && instructionsLength > 0) {
+          dest.set(glyf.subarray(0, instructionsStart), destStart);
+          dest.set([0, 0], destStart + instructionsStart);
+          dest.set(glyf.subarray(instructionsEnd, glyphDataLength), destStart + instructionsStart + 2);
+          glyphDataLength -= instructionsLength;
+
+          if (glyf.length - glyphDataLength > 3) {
+            glyphDataLength = glyphDataLength + 3 & ~3;
+          }
+
+          glyphProfile.length = glyphDataLength;
+          return glyphProfile;
+        }
+
+        if (glyf.length - glyphDataLength > 3) {
+          glyphDataLength = glyphDataLength + 3 & ~3;
+          dest.set(glyf.subarray(0, glyphDataLength), destStart);
+          glyphProfile.length = glyphDataLength;
+          return glyphProfile;
+        }
+
+        dest.set(glyf, destStart);
+        glyphProfile.length = glyf.length;
+        return glyphProfile;
+      }
+
+      function sanitizeHead(head, numGlyphs, locaLength) {
+        var data = head.data;
+        var version = int32(data[0], data[1], data[2], data[3]);
+
+        if (version >> 16 !== 1) {
+          (0, _util.info)('Attempting to fix invalid version in head table: ' + version);
+          data[0] = 0;
+          data[1] = 1;
+          data[2] = 0;
+          data[3] = 0;
+        }
+
+        var indexToLocFormat = int16(data[50], data[51]);
+
+        if (indexToLocFormat < 0 || indexToLocFormat > 1) {
+          (0, _util.info)('Attempting to fix invalid indexToLocFormat in head table: ' + indexToLocFormat);
+          var numGlyphsPlusOne = numGlyphs + 1;
+
+          if (locaLength === numGlyphsPlusOne << 1) {
+            data[50] = 0;
+            data[51] = 0;
+          } else if (locaLength === numGlyphsPlusOne << 2) {
+            data[50] = 0;
+            data[51] = 1;
+          } else {
+            throw new _util.FormatError('Could not fix indexToLocFormat: ' + indexToLocFormat);
+          }
+        }
+      }
+
+      function sanitizeGlyphLocations(loca, glyf, numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions) {
+        var itemSize, itemDecode, itemEncode;
+
+        if (isGlyphLocationsLong) {
+          itemSize = 4;
+
+          itemDecode = function fontItemDecodeLong(data, offset) {
+            return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
+          };
+
+          itemEncode = function fontItemEncodeLong(data, offset, value) {
+            data[offset] = value >>> 24 & 0xFF;
+            data[offset + 1] = value >> 16 & 0xFF;
+            data[offset + 2] = value >> 8 & 0xFF;
+            data[offset + 3] = value & 0xFF;
+          };
+        } else {
+          itemSize = 2;
+
+          itemDecode = function fontItemDecode(data, offset) {
+            return data[offset] << 9 | data[offset + 1] << 1;
+          };
+
+          itemEncode = function fontItemEncode(data, offset, value) {
+            data[offset] = value >> 9 & 0xFF;
+            data[offset + 1] = value >> 1 & 0xFF;
+          };
+        }
+
+        var numGlyphsOut = dupFirstEntry ? numGlyphs + 1 : numGlyphs;
+        var locaData = loca.data;
+        var locaDataSize = itemSize * (1 + numGlyphsOut);
+        locaData = new Uint8Array(locaDataSize);
+        locaData.set(loca.data.subarray(0, locaDataSize));
+        loca.data = locaData;
+        var oldGlyfData = glyf.data;
+        var oldGlyfDataLength = oldGlyfData.length;
+        var newGlyfData = new Uint8Array(oldGlyfDataLength);
+        var startOffset = itemDecode(locaData, 0);
+        var writeOffset = 0;
+        var missingGlyphs = Object.create(null);
+        itemEncode(locaData, 0, writeOffset);
+        var i, j;
+
+        for (i = 0, j = itemSize; i < numGlyphs; i++, j += itemSize) {
+          var endOffset = itemDecode(locaData, j);
+
+          if (endOffset === 0) {
+            endOffset = startOffset;
+          }
+
+          if (endOffset > oldGlyfDataLength && (oldGlyfDataLength + 3 & ~3) === endOffset) {
+            endOffset = oldGlyfDataLength;
+          }
+
+          if (endOffset > oldGlyfDataLength) {
+            startOffset = endOffset;
+          }
+
+          var glyphProfile = sanitizeGlyph(oldGlyfData, startOffset, endOffset, newGlyfData, writeOffset, hintsValid);
+          var newLength = glyphProfile.length;
+
+          if (newLength === 0) {
+            missingGlyphs[i] = true;
+          }
+
+          if (glyphProfile.sizeOfInstructions > maxSizeOfInstructions) {
+            maxSizeOfInstructions = glyphProfile.sizeOfInstructions;
+          }
+
+          writeOffset += newLength;
+          itemEncode(locaData, j, writeOffset);
+          startOffset = endOffset;
+        }
+
+        if (writeOffset === 0) {
+          var simpleGlyph = new Uint8Array([0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 49, 0]);
+
+          for (i = 0, j = itemSize; i < numGlyphsOut; i++, j += itemSize) {
+            itemEncode(locaData, j, simpleGlyph.length);
+          }
+
+          glyf.data = simpleGlyph;
+        } else if (dupFirstEntry) {
+          var firstEntryLength = itemDecode(locaData, itemSize);
+
+          if (newGlyfData.length > firstEntryLength + writeOffset) {
+            glyf.data = newGlyfData.subarray(0, firstEntryLength + writeOffset);
+          } else {
+            glyf.data = new Uint8Array(firstEntryLength + writeOffset);
+            glyf.data.set(newGlyfData.subarray(0, writeOffset));
+          }
+
+          glyf.data.set(newGlyfData.subarray(0, firstEntryLength), writeOffset);
+          itemEncode(loca.data, locaData.length - itemSize, writeOffset + firstEntryLength);
+        } else {
+          glyf.data = newGlyfData.subarray(0, writeOffset);
+        }
+
+        return {
+          missingGlyphs: missingGlyphs,
+          maxSizeOfInstructions: maxSizeOfInstructions
+        };
+      }
+
+      function readPostScriptTable(post, properties, maxpNumGlyphs) {
+        var start = (font.start ? font.start : 0) + post.offset;
+        font.pos = start;
+        var length = post.length,
+            end = start + length;
+        var version = font.getInt32();
+        font.getBytes(28);
+        var glyphNames;
+        var valid = true;
+        var i;
+
+        switch (version) {
+          case 0x00010000:
+            glyphNames = MacStandardGlyphOrdering;
+            break;
+
+          case 0x00020000:
+            var numGlyphs = font.getUint16();
+
+            if (numGlyphs !== maxpNumGlyphs) {
+              valid = false;
+              break;
+            }
+
+            var glyphNameIndexes = [];
+
+            for (i = 0; i < numGlyphs; ++i) {
+              var index = font.getUint16();
+
+              if (index >= 32768) {
+                valid = false;
+                break;
+              }
+
+              glyphNameIndexes.push(index);
+            }
+
+            if (!valid) {
+              break;
+            }
+
+            var customNames = [];
+            var strBuf = [];
+
+            while (font.pos < end) {
+              var stringLength = font.getByte();
+              strBuf.length = stringLength;
+
+              for (i = 0; i < stringLength; ++i) {
+                strBuf[i] = String.fromCharCode(font.getByte());
+              }
+
+              customNames.push(strBuf.join(''));
+            }
+
+            glyphNames = [];
+
+            for (i = 0; i < numGlyphs; ++i) {
+              var j = glyphNameIndexes[i];
+
+              if (j < 258) {
+                glyphNames.push(MacStandardGlyphOrdering[j]);
+                continue;
+              }
+
+              glyphNames.push(customNames[j - 258]);
+            }
+
+            break;
+
+          case 0x00030000:
+            break;
+
+          default:
+            (0, _util.warn)('Unknown/unsupported post table version ' + version);
+            valid = false;
+
+            if (properties.defaultEncoding) {
+              glyphNames = properties.defaultEncoding;
+            }
+
+            break;
+        }
+
+        properties.glyphNames = glyphNames;
+        return valid;
+      }
+
+      function readNameTable(nameTable) {
+        var start = (font.start ? font.start : 0) + nameTable.offset;
+        font.pos = start;
+        var names = [[], []];
+        var length = nameTable.length,
+            end = start + length;
+        var format = font.getUint16();
+        var FORMAT_0_HEADER_LENGTH = 6;
+
+        if (format !== 0 || length < FORMAT_0_HEADER_LENGTH) {
+          return names;
+        }
+
+        var numRecords = font.getUint16();
+        var stringsStart = font.getUint16();
+        var records = [];
+        var NAME_RECORD_LENGTH = 12;
+        var i, ii;
+
+        for (i = 0; i < numRecords && font.pos + NAME_RECORD_LENGTH <= end; i++) {
+          var r = {
+            platform: font.getUint16(),
+            encoding: font.getUint16(),
+            language: font.getUint16(),
+            name: font.getUint16(),
+            length: font.getUint16(),
+            offset: font.getUint16()
+          };
+
+          if (r.platform === 1 && r.encoding === 0 && r.language === 0 || r.platform === 3 && r.encoding === 1 && r.language === 0x409) {
+            records.push(r);
+          }
+        }
+
+        for (i = 0, ii = records.length; i < ii; i++) {
+          var record = records[i];
+
+          if (record.length <= 0) {
+            continue;
+          }
+
+          var pos = start + stringsStart + record.offset;
+
+          if (pos + record.length > end) {
+            continue;
+          }
+
+          font.pos = pos;
+          var nameIndex = record.name;
+
+          if (record.encoding) {
+            var str = '';
+
+            for (var j = 0, jj = record.length; j < jj; j += 2) {
+              str += String.fromCharCode(font.getUint16());
+            }
+
+            names[1][nameIndex] = str;
+          } else {
+            names[0][nameIndex] = (0, _util.bytesToString)(font.getBytes(record.length));
+          }
+        }
+
+        return names;
+      }
+
+      var TTOpsStackDeltas = [0, 0, 0, 0, 0, 0, 0, 0, -2, -2, -2, -2, 0, 0, -2, -5, -1, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, -1, -1, 1, -1, -999, 0, 1, 0, -1, -2, 0, -1, -2, -1, -1, 0, -1, -1, 0, 0, -999, -999, -1, -1, -1, -1, -2, -999, -2, -2, -999, 0, -2, -2, 0, 0, -2, 0, -2, 0, 0, 0, -2, -1, -1, 1, 1, 0, 0, -1, -1, -1, -1, -1, -1, -1, 0, 0, -1, 0, -1, -1, 0, -999, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2, -999, -999, -999, -999, -999, -1, -1, -2, -2, 0, 0, 0, 0, -1, -1, -999, -2, -2, 0, 0, -1, -2, -2, 0, 0, 0, -1, -1, -1, -2];
+
+      function sanitizeTTProgram(table, ttContext) {
+        var data = table.data;
+        var i = 0,
+            j,
+            n,
+            b,
+            funcId,
+            pc,
+            lastEndf = 0,
+            lastDeff = 0;
+        var stack = [];
+        var callstack = [];
+        var functionsCalled = [];
+        var tooComplexToFollowFunctions = ttContext.tooComplexToFollowFunctions;
+        var inFDEF = false,
+            ifLevel = 0,
+            inELSE = 0;
+
+        for (var ii = data.length; i < ii;) {
+          var op = data[i++];
+
+          if (op === 0x40) {
+            n = data[i++];
+
+            if (inFDEF || inELSE) {
+              i += n;
+            } else {
+              for (j = 0; j < n; j++) {
+                stack.push(data[i++]);
+              }
+            }
+          } else if (op === 0x41) {
+            n = data[i++];
+
+            if (inFDEF || inELSE) {
+              i += n * 2;
+            } else {
+              for (j = 0; j < n; j++) {
+                b = data[i++];
+                stack.push(b << 8 | data[i++]);
+              }
+            }
+          } else if ((op & 0xF8) === 0xB0) {
+            n = op - 0xB0 + 1;
+
+            if (inFDEF || inELSE) {
+              i += n;
+            } else {
+              for (j = 0; j < n; j++) {
+                stack.push(data[i++]);
+              }
+            }
+          } else if ((op & 0xF8) === 0xB8) {
+            n = op - 0xB8 + 1;
+
+            if (inFDEF || inELSE) {
+              i += n * 2;
+            } else {
+              for (j = 0; j < n; j++) {
+                b = data[i++];
+                stack.push(b << 8 | data[i++]);
+              }
+            }
+          } else if (op === 0x2B && !tooComplexToFollowFunctions) {
+            if (!inFDEF && !inELSE) {
+              funcId = stack[stack.length - 1];
+
+              if (isNaN(funcId)) {
+                (0, _util.info)('TT: CALL empty stack (or invalid entry).');
+              } else {
+                ttContext.functionsUsed[funcId] = true;
+
+                if (funcId in ttContext.functionsStackDeltas) {
+                  var newStackLength = stack.length + ttContext.functionsStackDeltas[funcId];
+
+                  if (newStackLength < 0) {
+                    (0, _util.warn)('TT: CALL invalid functions stack delta.');
+                    ttContext.hintsValid = false;
+                    return;
+                  }
+
+                  stack.length = newStackLength;
+                } else if (funcId in ttContext.functionsDefined && !functionsCalled.includes(funcId)) {
+                  callstack.push({
+                    data: data,
+                    i: i,
+                    stackTop: stack.length - 1
+                  });
+                  functionsCalled.push(funcId);
+                  pc = ttContext.functionsDefined[funcId];
+
+                  if (!pc) {
+                    (0, _util.warn)('TT: CALL non-existent function');
+                    ttContext.hintsValid = false;
+                    return;
+                  }
+
+                  data = pc.data;
+                  i = pc.i;
+                }
+              }
+            }
+          } else if (op === 0x2C && !tooComplexToFollowFunctions) {
+            if (inFDEF || inELSE) {
+              (0, _util.warn)('TT: nested FDEFs not allowed');
+              tooComplexToFollowFunctions = true;
+            }
+
+            inFDEF = true;
+            lastDeff = i;
+            funcId = stack.pop();
+            ttContext.functionsDefined[funcId] = {
+              data: data,
+              i: i
+            };
+          } else if (op === 0x2D) {
+            if (inFDEF) {
+              inFDEF = false;
+              lastEndf = i;
+            } else {
+              pc = callstack.pop();
+
+              if (!pc) {
+                (0, _util.warn)('TT: ENDF bad stack');
+                ttContext.hintsValid = false;
+                return;
+              }
+
+              funcId = functionsCalled.pop();
+              data = pc.data;
+              i = pc.i;
+              ttContext.functionsStackDeltas[funcId] = stack.length - pc.stackTop;
+            }
+          } else if (op === 0x89) {
+            if (inFDEF || inELSE) {
+              (0, _util.warn)('TT: nested IDEFs not allowed');
+              tooComplexToFollowFunctions = true;
+            }
+
+            inFDEF = true;
+            lastDeff = i;
+          } else if (op === 0x58) {
+            ++ifLevel;
+          } else if (op === 0x1B) {
+            inELSE = ifLevel;
+          } else if (op === 0x59) {
+            if (inELSE === ifLevel) {
+              inELSE = 0;
+            }
+
+            --ifLevel;
+          } else if (op === 0x1C) {
+            if (!inFDEF && !inELSE) {
+              var offset = stack[stack.length - 1];
+
+              if (offset > 0) {
+                i += offset - 1;
+              }
+            }
+          }
+
+          if (!inFDEF && !inELSE) {
+            var stackDelta = op <= 0x8E ? TTOpsStackDeltas[op] : op >= 0xC0 && op <= 0xDF ? -1 : op >= 0xE0 ? -2 : 0;
+
+            if (op >= 0x71 && op <= 0x75) {
+              n = stack.pop();
+
+              if (!isNaN(n)) {
+                stackDelta = -n * 2;
+              }
+            }
+
+            while (stackDelta < 0 && stack.length > 0) {
+              stack.pop();
+              stackDelta++;
+            }
+
+            while (stackDelta > 0) {
+              stack.push(NaN);
+              stackDelta--;
+            }
+          }
+        }
+
+        ttContext.tooComplexToFollowFunctions = tooComplexToFollowFunctions;
+        var content = [data];
+
+        if (i > data.length) {
+          content.push(new Uint8Array(i - data.length));
+        }
+
+        if (lastDeff > lastEndf) {
+          (0, _util.warn)('TT: complementing a missing function tail');
+          content.push(new Uint8Array([0x22, 0x2D]));
+        }
+
+        foldTTTable(table, content);
+      }
+
+      function checkInvalidFunctions(ttContext, maxFunctionDefs) {
+        if (ttContext.tooComplexToFollowFunctions) {
+          return;
+        }
+
+        if (ttContext.functionsDefined.length > maxFunctionDefs) {
+          (0, _util.warn)('TT: more functions defined than expected');
+          ttContext.hintsValid = false;
+          return;
+        }
+
+        for (var j = 0, jj = ttContext.functionsUsed.length; j < jj; j++) {
+          if (j > maxFunctionDefs) {
+            (0, _util.warn)('TT: invalid function id: ' + j);
+            ttContext.hintsValid = false;
+            return;
+          }
+
+          if (ttContext.functionsUsed[j] && !ttContext.functionsDefined[j]) {
+            (0, _util.warn)('TT: undefined function: ' + j);
+            ttContext.hintsValid = false;
+            return;
+          }
+        }
+      }
+
+      function foldTTTable(table, content) {
+        if (content.length > 1) {
+          var newLength = 0;
+          var j, jj;
+
+          for (j = 0, jj = content.length; j < jj; j++) {
+            newLength += content[j].length;
+          }
+
+          newLength = newLength + 3 & ~3;
+          var result = new Uint8Array(newLength);
+          var pos = 0;
+
+          for (j = 0, jj = content.length; j < jj; j++) {
+            result.set(content[j], pos);
+            pos += content[j].length;
+          }
+
+          table.data = result;
+          table.length = newLength;
+        }
+      }
+
+      function sanitizeTTPrograms(fpgm, prep, cvt, maxFunctionDefs) {
+        var ttContext = {
+          functionsDefined: [],
+          functionsUsed: [],
+          functionsStackDeltas: [],
+          tooComplexToFollowFunctions: false,
+          hintsValid: true
+        };
+
+        if (fpgm) {
+          sanitizeTTProgram(fpgm, ttContext);
+        }
+
+        if (prep) {
+          sanitizeTTProgram(prep, ttContext);
+        }
+
+        if (fpgm) {
+          checkInvalidFunctions(ttContext, maxFunctionDefs);
+        }
+
+        if (cvt && cvt.length & 1) {
+          var cvtData = new Uint8Array(cvt.length + 1);
+          cvtData.set(cvt.data);
+          cvt.data = cvtData;
+        }
+
+        return ttContext.hintsValid;
+      }
+
+      font = new _stream.Stream(new Uint8Array(font.getBytes()));
+      var header, tables;
+
+      if (isTrueTypeCollectionFile(font)) {
+        var ttcData = readTrueTypeCollectionData(font, this.name);
+        header = ttcData.header;
+        tables = ttcData.tables;
+      } else {
+        header = readOpenTypeHeader(font);
+        tables = readTables(font, header.numTables);
+      }
+
+      var cff, cffFile;
+      var isTrueType = !tables['CFF '];
+
+      if (!isTrueType) {
+        var isComposite = properties.composite && ((properties.cidToGidMap || []).length > 0 || !(properties.cMap instanceof _cmap.IdentityCMap));
+
+        if (header.version === 'OTTO' && !isComposite || !tables['head'] || !tables['hhea'] || !tables['maxp'] || !tables['post']) {
+          cffFile = new _stream.Stream(tables['CFF '].data);
+          cff = new CFFFont(cffFile, properties);
+          adjustWidths(properties);
+          return this.convert(name, cff, properties);
+        }
+
+        delete tables['glyf'];
+        delete tables['loca'];
+        delete tables['fpgm'];
+        delete tables['prep'];
+        delete tables['cvt '];
+        this.isOpenType = true;
+      } else {
+        if (!tables['loca']) {
+          throw new _util.FormatError('Required "loca" table is not found');
+        }
+
+        if (!tables['glyf']) {
+          (0, _util.warn)('Required "glyf" table is not found -- trying to recover.');
+          tables['glyf'] = {
+            tag: 'glyf',
+            data: new Uint8Array(0)
+          };
+        }
+
+        this.isOpenType = false;
+      }
+
+      if (!tables['maxp']) {
+        throw new _util.FormatError('Required "maxp" table is not found');
+      }
+
+      font.pos = (font.start || 0) + tables['maxp'].offset;
+      var version = font.getInt32();
+      var numGlyphs = font.getUint16();
+      var numGlyphsOut = numGlyphs + 1;
+      var dupFirstEntry = true;
+
+      if (numGlyphsOut > 0xFFFF) {
+        dupFirstEntry = false;
+        numGlyphsOut = numGlyphs;
+        (0, _util.warn)('Not enough space in glyfs to duplicate first glyph.');
+      }
+
+      var maxFunctionDefs = 0;
+      var maxSizeOfInstructions = 0;
+
+      if (version >= 0x00010000 && tables['maxp'].length >= 22) {
+        font.pos += 8;
+        var maxZones = font.getUint16();
+
+        if (maxZones > 2) {
+          tables['maxp'].data[14] = 0;
+          tables['maxp'].data[15] = 2;
+        }
+
+        font.pos += 4;
+        maxFunctionDefs = font.getUint16();
+        font.pos += 4;
+        maxSizeOfInstructions = font.getUint16();
+      }
+
+      tables['maxp'].data[4] = numGlyphsOut >> 8;
+      tables['maxp'].data[5] = numGlyphsOut & 255;
+      var hintsValid = sanitizeTTPrograms(tables['fpgm'], tables['prep'], tables['cvt '], maxFunctionDefs);
+
+      if (!hintsValid) {
+        delete tables['fpgm'];
+        delete tables['prep'];
+        delete tables['cvt '];
+      }
+
+      sanitizeMetrics(font, tables['hhea'], tables['hmtx'], numGlyphsOut, dupFirstEntry);
+
+      if (!tables['head']) {
+        throw new _util.FormatError('Required "head" table is not found');
+      }
+
+      sanitizeHead(tables['head'], numGlyphs, isTrueType ? tables['loca'].length : 0);
+      var missingGlyphs = Object.create(null);
+
+      if (isTrueType) {
+        var isGlyphLocationsLong = int16(tables['head'].data[50], tables['head'].data[51]);
+        var glyphsInfo = sanitizeGlyphLocations(tables['loca'], tables['glyf'], numGlyphs, isGlyphLocationsLong, hintsValid, dupFirstEntry, maxSizeOfInstructions);
+        missingGlyphs = glyphsInfo.missingGlyphs;
+
+        if (version >= 0x00010000 && tables['maxp'].length >= 22) {
+          tables['maxp'].data[26] = glyphsInfo.maxSizeOfInstructions >> 8;
+          tables['maxp'].data[27] = glyphsInfo.maxSizeOfInstructions & 255;
+        }
+      }
+
+      if (!tables['hhea']) {
+        throw new _util.FormatError('Required "hhea" table is not found');
+      }
+
+      if (tables['hhea'].data[10] === 0 && tables['hhea'].data[11] === 0) {
+        tables['hhea'].data[10] = 0xFF;
+        tables['hhea'].data[11] = 0xFF;
+      }
+
+      var metricsOverride = {
+        unitsPerEm: int16(tables['head'].data[18], tables['head'].data[19]),
+        yMax: int16(tables['head'].data[42], tables['head'].data[43]),
+        yMin: signedInt16(tables['head'].data[38], tables['head'].data[39]),
+        ascent: int16(tables['hhea'].data[4], tables['hhea'].data[5]),
+        descent: signedInt16(tables['hhea'].data[6], tables['hhea'].data[7])
+      };
+      this.ascent = metricsOverride.ascent / metricsOverride.unitsPerEm;
+      this.descent = metricsOverride.descent / metricsOverride.unitsPerEm;
+
+      if (tables['post']) {
+        readPostScriptTable(tables['post'], properties, numGlyphs);
+      }
+
+      tables['post'] = {
+        tag: 'post',
+        data: createPostTable(properties)
+      };
+      var charCodeToGlyphId = [],
+          charCode;
+
+      function hasGlyph(glyphId) {
+        return !missingGlyphs[glyphId];
+      }
+
+      if (properties.composite) {
+        var cidToGidMap = properties.cidToGidMap || [];
+        var isCidToGidMapEmpty = cidToGidMap.length === 0;
+        properties.cMap.forEach(function (charCode, cid) {
+          if (cid > 0xffff) {
+            throw new _util.FormatError('Max size of CID is 65,535');
+          }
+
+          var glyphId = -1;
+
+          if (isCidToGidMapEmpty) {
+            glyphId = cid;
+          } else if (cidToGidMap[cid] !== undefined) {
+            glyphId = cidToGidMap[cid];
+          }
+
+          if (glyphId >= 0 && glyphId < numGlyphs && hasGlyph(glyphId)) {
+            charCodeToGlyphId[charCode] = glyphId;
+          }
+        });
+      } else {
+        var cmapTable = readCmapTable(tables['cmap'], font, this.isSymbolicFont, properties.hasEncoding);
+        var cmapPlatformId = cmapTable.platformId;
+        var cmapEncodingId = cmapTable.encodingId;
+        var cmapMappings = cmapTable.mappings;
+        var cmapMappingsLength = cmapMappings.length;
+
+        if (properties.hasEncoding && (cmapPlatformId === 3 && cmapEncodingId === 1 || cmapPlatformId === 1 && cmapEncodingId === 0) || cmapPlatformId === -1 && cmapEncodingId === -1 && !!(0, _encodings.getEncoding)(properties.baseEncodingName)) {
+          var baseEncoding = [];
+
+          if (properties.baseEncodingName === 'MacRomanEncoding' || properties.baseEncodingName === 'WinAnsiEncoding') {
+            baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName);
+          }
+
+          var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+
+          for (charCode = 0; charCode < 256; charCode++) {
+            var glyphName, standardGlyphName;
+
+            if (this.differences && charCode in this.differences) {
+              glyphName = this.differences[charCode];
+            } else if (charCode in baseEncoding && baseEncoding[charCode] !== '') {
+              glyphName = baseEncoding[charCode];
+            } else {
+              glyphName = _encodings.StandardEncoding[charCode];
+            }
+
+            if (!glyphName) {
+              continue;
+            }
+
+            standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
+            var unicodeOrCharCode;
+
+            if (cmapPlatformId === 3 && cmapEncodingId === 1) {
+              unicodeOrCharCode = glyphsUnicodeMap[standardGlyphName];
+            } else if (cmapPlatformId === 1 && cmapEncodingId === 0) {
+              unicodeOrCharCode = _encodings.MacRomanEncoding.indexOf(standardGlyphName);
+            }
+
+            var found = false;
+
+            for (var i = 0; i < cmapMappingsLength; ++i) {
+              if (cmapMappings[i].charCode !== unicodeOrCharCode) {
+                continue;
+              }
+
+              charCodeToGlyphId[charCode] = cmapMappings[i].glyphId;
+              found = true;
+              break;
+            }
+
+            if (!found && properties.glyphNames) {
+              var glyphId = properties.glyphNames.indexOf(glyphName);
+
+              if (glyphId === -1 && standardGlyphName !== glyphName) {
+                glyphId = properties.glyphNames.indexOf(standardGlyphName);
+              }
+
+              if (glyphId > 0 && hasGlyph(glyphId)) {
+                charCodeToGlyphId[charCode] = glyphId;
+              }
+            }
+          }
+        } else if (cmapPlatformId === 0 && cmapEncodingId === 0) {
+          for (var _i2 = 0; _i2 < cmapMappingsLength; ++_i2) {
+            charCodeToGlyphId[cmapMappings[_i2].charCode] = cmapMappings[_i2].glyphId;
+          }
+        } else {
+          for (var _i3 = 0; _i3 < cmapMappingsLength; ++_i3) {
+            charCode = cmapMappings[_i3].charCode;
+
+            if (cmapPlatformId === 3 && charCode >= 0xF000 && charCode <= 0xF0FF) {
+              charCode &= 0xFF;
+            }
+
+            charCodeToGlyphId[charCode] = cmapMappings[_i3].glyphId;
+          }
+        }
+      }
+
+      if (charCodeToGlyphId.length === 0) {
+        charCodeToGlyphId[0] = 0;
+      }
+
+      var glyphZeroId = numGlyphsOut - 1;
+
+      if (!dupFirstEntry) {
+        glyphZeroId = 0;
+      }
+
+      var newMapping = adjustMapping(charCodeToGlyphId, hasGlyph, glyphZeroId);
+      this.toFontChar = newMapping.toFontChar;
+      tables['cmap'] = {
+        tag: 'cmap',
+        data: createCmapTable(newMapping.charCodeToGlyphId, numGlyphsOut)
+      };
+
+      if (!tables['OS/2'] || !validateOS2Table(tables['OS/2'])) {
+        tables['OS/2'] = {
+          tag: 'OS/2',
+          data: createOS2Table(properties, newMapping.charCodeToGlyphId, metricsOverride)
+        };
+      }
+
+      if (!isTrueType) {
+        try {
+          cffFile = new _stream.Stream(tables['CFF '].data);
+          var parser = new _cff_parser.CFFParser(cffFile, properties, SEAC_ANALYSIS_ENABLED);
+          cff = parser.parse();
+          cff.duplicateFirstGlyph();
+          var compiler = new _cff_parser.CFFCompiler(cff);
+          tables['CFF '].data = compiler.compile();
+        } catch (e) {
+          (0, _util.warn)('Failed to compile font ' + properties.loadedName);
+        }
+      }
+
+      if (!tables['name']) {
+        tables['name'] = {
+          tag: 'name',
+          data: createNameTable(this.name)
+        };
+      } else {
+        var namePrototype = readNameTable(tables['name']);
+        tables['name'].data = createNameTable(name, namePrototype);
+      }
+
+      var builder = new OpenTypeFileBuilder(header.version);
+
+      for (var tableTag in tables) {
+        builder.addTable(tableTag, tables[tableTag].data);
+      }
+
+      return builder.toArray();
+    },
+    convert: function Font_convert(fontName, font, properties) {
+      properties.fixedPitch = false;
+
+      if (properties.builtInEncoding) {
+        adjustToUnicode(properties, properties.builtInEncoding);
+      }
+
+      var glyphZeroId = 1;
+
+      if (font instanceof CFFFont) {
+        glyphZeroId = font.numGlyphs - 1;
+      }
+
+      var mapping = font.getGlyphMapping(properties);
+      var newMapping = adjustMapping(mapping, font.hasGlyphId.bind(font), glyphZeroId);
+      this.toFontChar = newMapping.toFontChar;
+      var numGlyphs = font.numGlyphs;
+
+      function getCharCodes(charCodeToGlyphId, glyphId) {
+        var charCodes = null;
+
+        for (var charCode in charCodeToGlyphId) {
+          if (glyphId === charCodeToGlyphId[charCode]) {
+            if (!charCodes) {
+              charCodes = [];
+            }
+
+            charCodes.push(charCode | 0);
+          }
+        }
+
+        return charCodes;
+      }
+
+      function createCharCode(charCodeToGlyphId, glyphId) {
+        for (var charCode in charCodeToGlyphId) {
+          if (glyphId === charCodeToGlyphId[charCode]) {
+            return charCode | 0;
+          }
+        }
+
+        newMapping.charCodeToGlyphId[newMapping.nextAvailableFontCharCode] = glyphId;
+        return newMapping.nextAvailableFontCharCode++;
+      }
+
+      var seacs = font.seacs;
+
+      if (SEAC_ANALYSIS_ENABLED && seacs && seacs.length) {
+        var matrix = properties.fontMatrix || _util.FONT_IDENTITY_MATRIX;
+        var charset = font.getCharset();
+        var seacMap = Object.create(null);
+
+        for (var glyphId in seacs) {
+          glyphId |= 0;
+          var seac = seacs[glyphId];
+          var baseGlyphName = _encodings.StandardEncoding[seac[2]];
+          var accentGlyphName = _encodings.StandardEncoding[seac[3]];
+          var baseGlyphId = charset.indexOf(baseGlyphName);
+          var accentGlyphId = charset.indexOf(accentGlyphName);
+
+          if (baseGlyphId < 0 || accentGlyphId < 0) {
+            continue;
+          }
+
+          var accentOffset = {
+            x: seac[0] * matrix[0] + seac[1] * matrix[2] + matrix[4],
+            y: seac[0] * matrix[1] + seac[1] * matrix[3] + matrix[5]
+          };
+          var charCodes = getCharCodes(mapping, glyphId);
+
+          if (!charCodes) {
+            continue;
+          }
+
+          for (var i = 0, ii = charCodes.length; i < ii; i++) {
+            var charCode = charCodes[i];
+            var charCodeToGlyphId = newMapping.charCodeToGlyphId;
+            var baseFontCharCode = createCharCode(charCodeToGlyphId, baseGlyphId);
+            var accentFontCharCode = createCharCode(charCodeToGlyphId, accentGlyphId);
+            seacMap[charCode] = {
+              baseFontCharCode: baseFontCharCode,
+              accentFontCharCode: accentFontCharCode,
+              accentOffset: accentOffset
+            };
+          }
+        }
+
+        properties.seacMap = seacMap;
+      }
+
+      var unitsPerEm = 1 / (properties.fontMatrix || _util.FONT_IDENTITY_MATRIX)[0];
+      var builder = new OpenTypeFileBuilder('\x4F\x54\x54\x4F');
+      builder.addTable('CFF ', font.data);
+      builder.addTable('OS/2', createOS2Table(properties, newMapping.charCodeToGlyphId));
+      builder.addTable('cmap', createCmapTable(newMapping.charCodeToGlyphId, numGlyphs));
+      builder.addTable('head', '\x00\x01\x00\x00' + '\x00\x00\x10\x00' + '\x00\x00\x00\x00' + '\x5F\x0F\x3C\xF5' + '\x00\x00' + safeString16(unitsPerEm) + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00\x00\x00\x9e\x0b\x7e\x27' + '\x00\x00' + safeString16(properties.descent) + '\x0F\xFF' + safeString16(properties.ascent) + string16(properties.italicAngle ? 2 : 0) + '\x00\x11' + '\x00\x00' + '\x00\x00' + '\x00\x00');
+      builder.addTable('hhea', '\x00\x01\x00\x00' + safeString16(properties.ascent) + safeString16(properties.descent) + '\x00\x00' + '\xFF\xFF' + '\x00\x00' + '\x00\x00' + '\x00\x00' + safeString16(properties.capHeight) + safeString16(Math.tan(properties.italicAngle) * properties.xHeight) + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + '\x00\x00' + string16(numGlyphs));
+      builder.addTable('hmtx', function fontFieldsHmtx() {
+        var charstrings = font.charstrings;
+        var cffWidths = font.cff ? font.cff.widths : null;
+        var hmtx = '\x00\x00\x00\x00';
+
+        for (var i = 1, ii = numGlyphs; i < ii; i++) {
+          var width = 0;
+
+          if (charstrings) {
+            var charstring = charstrings[i - 1];
+            width = 'width' in charstring ? charstring.width : 0;
+          } else if (cffWidths) {
+            width = Math.ceil(cffWidths[i] || 0);
+          }
+
+          hmtx += string16(width) + string16(0);
+        }
+
+        return hmtx;
+      }());
+      builder.addTable('maxp', '\x00\x00\x50\x00' + string16(numGlyphs));
+      builder.addTable('name', createNameTable(fontName));
+      builder.addTable('post', createPostTable(properties));
+      return builder.toArray();
+    },
+
+    get spaceWidth() {
+      if ('_shadowWidth' in this) {
+        return this._shadowWidth;
+      }
+
+      var possibleSpaceReplacements = ['space', 'minus', 'one', 'i', 'I'];
+      var width;
+
+      for (var i = 0, ii = possibleSpaceReplacements.length; i < ii; i++) {
+        var glyphName = possibleSpaceReplacements[i];
+
+        if (glyphName in this.widths) {
+          width = this.widths[glyphName];
+          break;
+        }
+
+        var glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+        var glyphUnicode = glyphsUnicodeMap[glyphName];
+        var charcode = 0;
+
+        if (this.composite) {
+          if (this.cMap.contains(glyphUnicode)) {
+            charcode = this.cMap.lookup(glyphUnicode);
+          }
+        }
+
+        if (!charcode && this.toUnicode) {
+          charcode = this.toUnicode.charCodeOf(glyphUnicode);
+        }
+
+        if (charcode <= 0) {
+          charcode = glyphUnicode;
+        }
+
+        width = this.widths[charcode];
+
+        if (width) {
+          break;
+        }
+      }
+
+      width = width || this.defaultWidth;
+      this._shadowWidth = width;
+      return width;
+    },
+
+    charToGlyph: function Font_charToGlyph(charcode, isSpace) {
+      var fontCharCode, width, operatorListId;
+      var widthCode = charcode;
+
+      if (this.cMap && this.cMap.contains(charcode)) {
+        widthCode = this.cMap.lookup(charcode);
+      }
+
+      width = this.widths[widthCode];
+      width = (0, _util.isNum)(width) ? width : this.defaultWidth;
+      var vmetric = this.vmetrics && this.vmetrics[widthCode];
+      var unicode = this.toUnicode.get(charcode) || this.fallbackToUnicode.get(charcode) || charcode;
+
+      if (typeof unicode === 'number') {
+        unicode = String.fromCharCode(unicode);
+      }
+
+      var isInFont = charcode in this.toFontChar;
+      fontCharCode = this.toFontChar[charcode] || charcode;
+
+      if (this.missingFile) {
+        fontCharCode = (0, _unicode.mapSpecialUnicodeValues)(fontCharCode);
+      }
+
+      if (this.isType3Font) {
+        operatorListId = fontCharCode;
+      }
+
+      var accent = null;
+
+      if (this.seacMap && this.seacMap[charcode]) {
+        isInFont = true;
+        var seac = this.seacMap[charcode];
+        fontCharCode = seac.baseFontCharCode;
+        accent = {
+          fontChar: String.fromCodePoint(seac.accentFontCharCode),
+          offset: seac.accentOffset
+        };
+      }
+
+      var fontChar = typeof fontCharCode === 'number' ? String.fromCodePoint(fontCharCode) : '';
+      var glyph = this.glyphCache[charcode];
+
+      if (!glyph || !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont)) {
+        glyph = new Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, isSpace, isInFont);
+        this.glyphCache[charcode] = glyph;
+      }
+
+      return glyph;
+    },
+    charsToGlyphs: function Font_charsToGlyphs(chars) {
+      var charsCache = this.charsCache;
+      var glyphs, glyph, charcode;
+
+      if (charsCache) {
+        glyphs = charsCache[chars];
+
+        if (glyphs) {
+          return glyphs;
+        }
+      }
+
+      if (!charsCache) {
+        charsCache = this.charsCache = Object.create(null);
+      }
+
+      glyphs = [];
+      var charsCacheKey = chars;
+      var i = 0,
+          ii;
+
+      if (this.cMap) {
+        var c = Object.create(null);
+
+        while (i < chars.length) {
+          this.cMap.readCharCode(chars, i, c);
+          charcode = c.charcode;
+          var length = c.length;
+          i += length;
+          var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20;
+          glyph = this.charToGlyph(charcode, isSpace);
+          glyphs.push(glyph);
+        }
+      } else {
+        for (i = 0, ii = chars.length; i < ii; ++i) {
+          charcode = chars.charCodeAt(i);
+          glyph = this.charToGlyph(charcode, charcode === 0x20);
+          glyphs.push(glyph);
+        }
+      }
+
+      return charsCache[charsCacheKey] = glyphs;
+    },
+
+    get glyphCacheValues() {
+      return Object.values(this.glyphCache);
+    }
+
+  };
+  return Font;
+}();
+
+exports.Font = Font;
+
+var ErrorFont = function ErrorFontClosure() {
+  function ErrorFont(error) {
+    this.error = error;
+    this.loadedName = 'g_font_error';
+    this.missingFile = true;
+  }
+
+  ErrorFont.prototype = {
+    charsToGlyphs: function ErrorFont_charsToGlyphs() {
+      return [];
+    },
+    exportData: function ErrorFont_exportData() {
+      return {
+        error: this.error
+      };
+    }
+  };
+  return ErrorFont;
+}();
+
+exports.ErrorFont = ErrorFont;
+
+function type1FontGlyphMapping(properties, builtInEncoding, glyphNames) {
+  var charCodeToGlyphId = Object.create(null);
+  var glyphId, charCode, baseEncoding;
+  var isSymbolicFont = !!(properties.flags & FontFlags.Symbolic);
+
+  if (properties.baseEncodingName) {
+    baseEncoding = (0, _encodings.getEncoding)(properties.baseEncodingName);
+
+    for (charCode = 0; charCode < baseEncoding.length; charCode++) {
+      glyphId = glyphNames.indexOf(baseEncoding[charCode]);
+
+      if (glyphId >= 0) {
+        charCodeToGlyphId[charCode] = glyphId;
+      } else {
+        charCodeToGlyphId[charCode] = 0;
+      }
+    }
+  } else if (isSymbolicFont) {
+    for (charCode in builtInEncoding) {
+      charCodeToGlyphId[charCode] = builtInEncoding[charCode];
+    }
+  } else {
+    baseEncoding = _encodings.StandardEncoding;
+
+    for (charCode = 0; charCode < baseEncoding.length; charCode++) {
+      glyphId = glyphNames.indexOf(baseEncoding[charCode]);
+
+      if (glyphId >= 0) {
+        charCodeToGlyphId[charCode] = glyphId;
+      } else {
+        charCodeToGlyphId[charCode] = 0;
+      }
+    }
+  }
+
+  var differences = properties.differences,
+      glyphsUnicodeMap;
+
+  if (differences) {
+    for (charCode in differences) {
+      var glyphName = differences[charCode];
+      glyphId = glyphNames.indexOf(glyphName);
+
+      if (glyphId === -1) {
+        if (!glyphsUnicodeMap) {
+          glyphsUnicodeMap = (0, _glyphlist.getGlyphsUnicode)();
+        }
+
+        var standardGlyphName = recoverGlyphName(glyphName, glyphsUnicodeMap);
+
+        if (standardGlyphName !== glyphName) {
+          glyphId = glyphNames.indexOf(standardGlyphName);
+        }
+      }
+
+      if (glyphId >= 0) {
+        charCodeToGlyphId[charCode] = glyphId;
+      } else {
+        charCodeToGlyphId[charCode] = 0;
+      }
+    }
+  }
+
+  return charCodeToGlyphId;
+}
+
+var Type1Font = function Type1FontClosure() {
+  function findBlock(streamBytes, signature, startIndex) {
+    var streamBytesLength = streamBytes.length;
+    var signatureLength = signature.length;
+    var scanLength = streamBytesLength - signatureLength;
+    var i = startIndex,
+        j,
+        found = false;
+
+    while (i < scanLength) {
+      j = 0;
+
+      while (j < signatureLength && streamBytes[i + j] === signature[j]) {
+        j++;
+      }
+
+      if (j >= signatureLength) {
+        i += j;
+
+        while (i < streamBytesLength && (0, _util.isSpace)(streamBytes[i])) {
+          i++;
+        }
+
+        found = true;
+        break;
+      }
+
+      i++;
+    }
+
+    return {
+      found: found,
+      length: i
+    };
+  }
+
+  function getHeaderBlock(stream, suggestedLength) {
+    var EEXEC_SIGNATURE = [0x65, 0x65, 0x78, 0x65, 0x63];
+    var streamStartPos = stream.pos;
+    var headerBytes, headerBytesLength, block;
+
+    try {
+      headerBytes = stream.getBytes(suggestedLength);
+      headerBytesLength = headerBytes.length;
+    } catch (ex) {
+      if (ex instanceof _core_utils.MissingDataException) {
+        throw ex;
+      }
+    }
+
+    if (headerBytesLength === suggestedLength) {
+      block = findBlock(headerBytes, EEXEC_SIGNATURE, suggestedLength - 2 * EEXEC_SIGNATURE.length);
+
+      if (block.found && block.length === suggestedLength) {
+        return {
+          stream: new _stream.Stream(headerBytes),
+          length: suggestedLength
+        };
+      }
+    }
+
+    (0, _util.warn)('Invalid "Length1" property in Type1 font -- trying to recover.');
+    stream.pos = streamStartPos;
+    var SCAN_BLOCK_LENGTH = 2048;
+    var actualLength;
+
+    while (true) {
+      var scanBytes = stream.peekBytes(SCAN_BLOCK_LENGTH);
+      block = findBlock(scanBytes, EEXEC_SIGNATURE, 0);
+
+      if (block.length === 0) {
+        break;
+      }
+
+      stream.pos += block.length;
+
+      if (block.found) {
+        actualLength = stream.pos - streamStartPos;
+        break;
+      }
+    }
+
+    stream.pos = streamStartPos;
+
+    if (actualLength) {
+      return {
+        stream: new _stream.Stream(stream.getBytes(actualLength)),
+        length: actualLength
+      };
+    }
+
+    (0, _util.warn)('Unable to recover "Length1" property in Type1 font -- using as is.');
+    return {
+      stream: new _stream.Stream(stream.getBytes(suggestedLength)),
+      length: suggestedLength
+    };
+  }
+
+  function getEexecBlock(stream, suggestedLength) {
+    var eexecBytes = stream.getBytes();
+    return {
+      stream: new _stream.Stream(eexecBytes),
+      length: eexecBytes.length
+    };
+  }
+
+  function Type1Font(name, file, properties) {
+    var PFB_HEADER_SIZE = 6;
+    var headerBlockLength = properties.length1;
+    var eexecBlockLength = properties.length2;
+    var pfbHeader = file.peekBytes(PFB_HEADER_SIZE);
+    var pfbHeaderPresent = pfbHeader[0] === 0x80 && pfbHeader[1] === 0x01;
+
+    if (pfbHeaderPresent) {
+      file.skip(PFB_HEADER_SIZE);
+      headerBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
+    }
+
+    var headerBlock = getHeaderBlock(file, headerBlockLength);
+    var headerBlockParser = new _type1_parser.Type1Parser(headerBlock.stream, false, SEAC_ANALYSIS_ENABLED);
+    headerBlockParser.extractFontHeader(properties);
+
+    if (pfbHeaderPresent) {
+      pfbHeader = file.getBytes(PFB_HEADER_SIZE);
+      eexecBlockLength = pfbHeader[5] << 24 | pfbHeader[4] << 16 | pfbHeader[3] << 8 | pfbHeader[2];
+    }
+
+    var eexecBlock = getEexecBlock(file, eexecBlockLength);
+    var eexecBlockParser = new _type1_parser.Type1Parser(eexecBlock.stream, true, SEAC_ANALYSIS_ENABLED);
+    var data = eexecBlockParser.extractFontProgram();
+
+    for (var info in data.properties) {
+      properties[info] = data.properties[info];
+    }
+
+    var charstrings = data.charstrings;
+    var type2Charstrings = this.getType2Charstrings(charstrings);
+    var subrs = this.getType2Subrs(data.subrs);
+    this.charstrings = charstrings;
+    this.data = this.wrap(name, type2Charstrings, this.charstrings, subrs, properties);
+    this.seacs = this.getSeacs(data.charstrings);
+  }
+
+  Type1Font.prototype = {
+    get numGlyphs() {
+      return this.charstrings.length + 1;
+    },
+
+    getCharset: function Type1Font_getCharset() {
+      var charset = ['.notdef'];
+      var charstrings = this.charstrings;
+
+      for (var glyphId = 0; glyphId < charstrings.length; glyphId++) {
+        charset.push(charstrings[glyphId].glyphName);
+      }
+
+      return charset;
+    },
+    getGlyphMapping: function Type1Font_getGlyphMapping(properties) {
+      var charstrings = this.charstrings;
+      var glyphNames = ['.notdef'],
+          glyphId;
+
+      for (glyphId = 0; glyphId < charstrings.length; glyphId++) {
+        glyphNames.push(charstrings[glyphId].glyphName);
+      }
+
+      var encoding = properties.builtInEncoding;
+
+      if (encoding) {
+        var builtInEncoding = Object.create(null);
+
+        for (var charCode in encoding) {
+          glyphId = glyphNames.indexOf(encoding[charCode]);
+
+          if (glyphId >= 0) {
+            builtInEncoding[charCode] = glyphId;
+          }
+        }
+      }
+
+      return type1FontGlyphMapping(properties, builtInEncoding, glyphNames);
+    },
+    hasGlyphId: function Type1Font_hasGlyphID(id) {
+      if (id < 0 || id >= this.numGlyphs) {
+        return false;
+      }
+
+      if (id === 0) {
+        return true;
+      }
+
+      var glyph = this.charstrings[id - 1];
+      return glyph.charstring.length > 0;
+    },
+    getSeacs: function Type1Font_getSeacs(charstrings) {
+      var i, ii;
+      var seacMap = [];
+
+      for (i = 0, ii = charstrings.length; i < ii; i++) {
+        var charstring = charstrings[i];
+
+        if (charstring.seac) {
+          seacMap[i + 1] = charstring.seac;
+        }
+      }
+
+      return seacMap;
+    },
+    getType2Charstrings: function Type1Font_getType2Charstrings(type1Charstrings) {
+      var type2Charstrings = [];
+
+      for (var i = 0, ii = type1Charstrings.length; i < ii; i++) {
+        type2Charstrings.push(type1Charstrings[i].charstring);
+      }
+
+      return type2Charstrings;
+    },
+    getType2Subrs: function Type1Font_getType2Subrs(type1Subrs) {
+      var bias = 0;
+      var count = type1Subrs.length;
+
+      if (count < 1133) {
+        bias = 107;
+      } else if (count < 33769) {
+        bias = 1131;
+      } else {
+        bias = 32768;
+      }
+
+      var type2Subrs = [];
+      var i;
+
+      for (i = 0; i < bias; i++) {
+        type2Subrs.push([0x0B]);
+      }
+
+      for (i = 0; i < count; i++) {
+        type2Subrs.push(type1Subrs[i]);
+      }
+
+      return type2Subrs;
+    },
+    wrap: function Type1Font_wrap(name, glyphs, charstrings, subrs, properties) {
+      var cff = new _cff_parser.CFF();
+      cff.header = new _cff_parser.CFFHeader(1, 0, 4, 4);
+      cff.names = [name];
+      var topDict = new _cff_parser.CFFTopDict();
+      topDict.setByName('version', 391);
+      topDict.setByName('Notice', 392);
+      topDict.setByName('FullName', 393);
+      topDict.setByName('FamilyName', 394);
+      topDict.setByName('Weight', 395);
+      topDict.setByName('Encoding', null);
+      topDict.setByName('FontMatrix', properties.fontMatrix);
+      topDict.setByName('FontBBox', properties.bbox);
+      topDict.setByName('charset', null);
+      topDict.setByName('CharStrings', null);
+      topDict.setByName('Private', null);
+      cff.topDict = topDict;
+      var strings = new _cff_parser.CFFStrings();
+      strings.add('Version 0.11');
+      strings.add('See original notice');
+      strings.add(name);
+      strings.add(name);
+      strings.add('Medium');
+      cff.strings = strings;
+      cff.globalSubrIndex = new _cff_parser.CFFIndex();
+      var count = glyphs.length;
+      var charsetArray = ['.notdef'];
+      var i, ii;
+
+      for (i = 0; i < count; i++) {
+        var glyphName = charstrings[i].glyphName;
+
+        var index = _cff_parser.CFFStandardStrings.indexOf(glyphName);
+
+        if (index === -1) {
+          strings.add(glyphName);
+        }
+
+        charsetArray.push(glyphName);
+      }
+
+      cff.charset = new _cff_parser.CFFCharset(false, 0, charsetArray);
+      var charStringsIndex = new _cff_parser.CFFIndex();
+      charStringsIndex.add([0x8B, 0x0E]);
+
+      for (i = 0; i < count; i++) {
+        charStringsIndex.add(glyphs[i]);
+      }
+
+      cff.charStrings = charStringsIndex;
+      var privateDict = new _cff_parser.CFFPrivateDict();
+      privateDict.setByName('Subrs', null);
+      var fields = ['BlueValues', 'OtherBlues', 'FamilyBlues', 'FamilyOtherBlues', 'StemSnapH', 'StemSnapV', 'BlueShift', 'BlueFuzz', 'BlueScale', 'LanguageGroup', 'ExpansionFactor', 'ForceBold', 'StdHW', 'StdVW'];
+
+      for (i = 0, ii = fields.length; i < ii; i++) {
+        var field = fields[i];
+
+        if (!(field in properties.privateData)) {
+          continue;
+        }
+
+        var value = properties.privateData[field];
+
+        if (Array.isArray(value)) {
+          for (var j = value.length - 1; j > 0; j--) {
+            value[j] -= value[j - 1];
+          }
+        }
+
+        privateDict.setByName(field, value);
+      }
+
+      cff.topDict.privateDict = privateDict;
+      var subrIndex = new _cff_parser.CFFIndex();
+
+      for (i = 0, ii = subrs.length; i < ii; i++) {
+        subrIndex.add(subrs[i]);
+      }
+
+      privateDict.subrsIndex = subrIndex;
+      var compiler = new _cff_parser.CFFCompiler(cff);
+      return compiler.compile();
+    }
+  };
+  return Type1Font;
+}();
+
+var CFFFont = function CFFFontClosure() {
+  function CFFFont(file, properties) {
+    this.properties = properties;
+    var parser = new _cff_parser.CFFParser(file, properties, SEAC_ANALYSIS_ENABLED);
+    this.cff = parser.parse();
+    this.cff.duplicateFirstGlyph();
+    var compiler = new _cff_parser.CFFCompiler(this.cff);
+    this.seacs = this.cff.seacs;
+
+    try {
+      this.data = compiler.compile();
+    } catch (e) {
+      (0, _util.warn)('Failed to compile font ' + properties.loadedName);
+      this.data = file;
+    }
+  }
+
+  CFFFont.prototype = {
+    get numGlyphs() {
+      return this.cff.charStrings.count;
+    },
+
+    getCharset: function CFFFont_getCharset() {
+      return this.cff.charset.charset;
+    },
+    getGlyphMapping: function CFFFont_getGlyphMapping() {
+      var cff = this.cff;
+      var properties = this.properties;
+      var charsets = cff.charset.charset;
+      var charCodeToGlyphId;
+      var glyphId;
+
+      if (properties.composite) {
+        charCodeToGlyphId = Object.create(null);
+        var charCode;
+
+        if (cff.isCIDFont) {
+          for (glyphId = 0; glyphId < charsets.length; glyphId++) {
+            var cid = charsets[glyphId];
+            charCode = properties.cMap.charCodeOf(cid);
+            charCodeToGlyphId[charCode] = glyphId;
+          }
+        } else {
+          for (glyphId = 0; glyphId < cff.charStrings.count; glyphId++) {
+            charCode = properties.cMap.charCodeOf(glyphId);
+            charCodeToGlyphId[charCode] = glyphId;
+          }
+        }
+
+        return charCodeToGlyphId;
+      }
+
+      var encoding = cff.encoding ? cff.encoding.encoding : null;
+      charCodeToGlyphId = type1FontGlyphMapping(properties, encoding, charsets);
+      return charCodeToGlyphId;
+    },
+    hasGlyphId: function CFFFont_hasGlyphID(id) {
+      return this.cff.hasGlyphId(id);
+    }
+  };
+  return CFFFont;
+}();
+
+/***/ }),
+/* 175 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.CFFFDSelect = exports.CFFCompiler = exports.CFFPrivateDict = exports.CFFTopDict = exports.CFFCharset = exports.CFFIndex = exports.CFFStrings = exports.CFFHeader = exports.CFF = exports.CFFParser = exports.CFFStandardStrings = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _charsets = __w_pdfjs_require__(176);
+
+var _encodings = __w_pdfjs_require__(177);
+
+var MAX_SUBR_NESTING = 10;
+var CFFStandardStrings = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall', '001.000', '001.001', '001.002', '001.003', 'Black', 'Bold', 'Book', 'Light', 'Medium', 'Regular', 'Roman', 'Semibold'];
+exports.CFFStandardStrings = CFFStandardStrings;
+var NUM_STANDARD_CFF_STRINGS = 391;
+
+var CFFParser = function CFFParserClosure() {
+  var CharstringValidationData = [null, {
+    id: 'hstem',
+    min: 2,
+    stackClearing: true,
+    stem: true
+  }, null, {
+    id: 'vstem',
+    min: 2,
+    stackClearing: true,
+    stem: true
+  }, {
+    id: 'vmoveto',
+    min: 1,
+    stackClearing: true
+  }, {
+    id: 'rlineto',
+    min: 2,
+    resetStack: true
+  }, {
+    id: 'hlineto',
+    min: 1,
+    resetStack: true
+  }, {
+    id: 'vlineto',
+    min: 1,
+    resetStack: true
+  }, {
+    id: 'rrcurveto',
+    min: 6,
+    resetStack: true
+  }, null, {
+    id: 'callsubr',
+    min: 1,
+    undefStack: true
+  }, {
+    id: 'return',
+    min: 0,
+    undefStack: true
+  }, null, null, {
+    id: 'endchar',
+    min: 0,
+    stackClearing: true
+  }, null, null, null, {
+    id: 'hstemhm',
+    min: 2,
+    stackClearing: true,
+    stem: true
+  }, {
+    id: 'hintmask',
+    min: 0,
+    stackClearing: true
+  }, {
+    id: 'cntrmask',
+    min: 0,
+    stackClearing: true
+  }, {
+    id: 'rmoveto',
+    min: 2,
+    stackClearing: true
+  }, {
+    id: 'hmoveto',
+    min: 1,
+    stackClearing: true
+  }, {
+    id: 'vstemhm',
+    min: 2,
+    stackClearing: true,
+    stem: true
+  }, {
+    id: 'rcurveline',
+    min: 8,
+    resetStack: true
+  }, {
+    id: 'rlinecurve',
+    min: 8,
+    resetStack: true
+  }, {
+    id: 'vvcurveto',
+    min: 4,
+    resetStack: true
+  }, {
+    id: 'hhcurveto',
+    min: 4,
+    resetStack: true
+  }, null, {
+    id: 'callgsubr',
+    min: 1,
+    undefStack: true
+  }, {
+    id: 'vhcurveto',
+    min: 4,
+    resetStack: true
+  }, {
+    id: 'hvcurveto',
+    min: 4,
+    resetStack: true
+  }];
+  var CharstringValidationData12 = [null, null, null, {
+    id: 'and',
+    min: 2,
+    stackDelta: -1
+  }, {
+    id: 'or',
+    min: 2,
+    stackDelta: -1
+  }, {
+    id: 'not',
+    min: 1,
+    stackDelta: 0
+  }, null, null, null, {
+    id: 'abs',
+    min: 1,
+    stackDelta: 0
+  }, {
+    id: 'add',
+    min: 2,
+    stackDelta: -1,
+    stackFn: function stack_div(stack, index) {
+      stack[index - 2] = stack[index - 2] + stack[index - 1];
+    }
+  }, {
+    id: 'sub',
+    min: 2,
+    stackDelta: -1,
+    stackFn: function stack_div(stack, index) {
+      stack[index - 2] = stack[index - 2] - stack[index - 1];
+    }
+  }, {
+    id: 'div',
+    min: 2,
+    stackDelta: -1,
+    stackFn: function stack_div(stack, index) {
+      stack[index - 2] = stack[index - 2] / stack[index - 1];
+    }
+  }, null, {
+    id: 'neg',
+    min: 1,
+    stackDelta: 0,
+    stackFn: function stack_div(stack, index) {
+      stack[index - 1] = -stack[index - 1];
+    }
+  }, {
+    id: 'eq',
+    min: 2,
+    stackDelta: -1
+  }, null, null, {
+    id: 'drop',
+    min: 1,
+    stackDelta: -1
+  }, null, {
+    id: 'put',
+    min: 2,
+    stackDelta: -2
+  }, {
+    id: 'get',
+    min: 1,
+    stackDelta: 0
+  }, {
+    id: 'ifelse',
+    min: 4,
+    stackDelta: -3
+  }, {
+    id: 'random',
+    min: 0,
+    stackDelta: 1
+  }, {
+    id: 'mul',
+    min: 2,
+    stackDelta: -1,
+    stackFn: function stack_div(stack, index) {
+      stack[index - 2] = stack[index - 2] * stack[index - 1];
+    }
+  }, null, {
+    id: 'sqrt',
+    min: 1,
+    stackDelta: 0
+  }, {
+    id: 'dup',
+    min: 1,
+    stackDelta: 1
+  }, {
+    id: 'exch',
+    min: 2,
+    stackDelta: 0
+  }, {
+    id: 'index',
+    min: 2,
+    stackDelta: 0
+  }, {
+    id: 'roll',
+    min: 3,
+    stackDelta: -2
+  }, null, null, null, {
+    id: 'hflex',
+    min: 7,
+    resetStack: true
+  }, {
+    id: 'flex',
+    min: 13,
+    resetStack: true
+  }, {
+    id: 'hflex1',
+    min: 9,
+    resetStack: true
+  }, {
+    id: 'flex1',
+    min: 11,
+    resetStack: true
+  }];
+
+  function CFFParser(file, properties, seacAnalysisEnabled) {
+    this.bytes = file.getBytes();
+    this.properties = properties;
+    this.seacAnalysisEnabled = !!seacAnalysisEnabled;
+  }
+
+  CFFParser.prototype = {
+    parse: function CFFParser_parse() {
+      var properties = this.properties;
+      var cff = new CFF();
+      this.cff = cff;
+      var header = this.parseHeader();
+      var nameIndex = this.parseIndex(header.endPos);
+      var topDictIndex = this.parseIndex(nameIndex.endPos);
+      var stringIndex = this.parseIndex(topDictIndex.endPos);
+      var globalSubrIndex = this.parseIndex(stringIndex.endPos);
+      var topDictParsed = this.parseDict(topDictIndex.obj.get(0));
+      var topDict = this.createDict(CFFTopDict, topDictParsed, cff.strings);
+      cff.header = header.obj;
+      cff.names = this.parseNameIndex(nameIndex.obj);
+      cff.strings = this.parseStringIndex(stringIndex.obj);
+      cff.topDict = topDict;
+      cff.globalSubrIndex = globalSubrIndex.obj;
+      this.parsePrivateDict(cff.topDict);
+      cff.isCIDFont = topDict.hasName('ROS');
+      var charStringOffset = topDict.getByName('CharStrings');
+      var charStringIndex = this.parseIndex(charStringOffset).obj;
+      var fontMatrix = topDict.getByName('FontMatrix');
+
+      if (fontMatrix) {
+        properties.fontMatrix = fontMatrix;
+      }
+
+      var fontBBox = topDict.getByName('FontBBox');
+
+      if (fontBBox) {
+        properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
+        properties.descent = Math.min(fontBBox[1], fontBBox[3]);
+        properties.ascentScaled = true;
+      }
+
+      var charset, encoding;
+
+      if (cff.isCIDFont) {
+        var fdArrayIndex = this.parseIndex(topDict.getByName('FDArray')).obj;
+
+        for (var i = 0, ii = fdArrayIndex.count; i < ii; ++i) {
+          var dictRaw = fdArrayIndex.get(i);
+          var fontDict = this.createDict(CFFTopDict, this.parseDict(dictRaw), cff.strings);
+          this.parsePrivateDict(fontDict);
+          cff.fdArray.push(fontDict);
+        }
+
+        encoding = null;
+        charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, true);
+        cff.fdSelect = this.parseFDSelect(topDict.getByName('FDSelect'), charStringIndex.count);
+      } else {
+        charset = this.parseCharsets(topDict.getByName('charset'), charStringIndex.count, cff.strings, false);
+        encoding = this.parseEncoding(topDict.getByName('Encoding'), properties, cff.strings, charset.charset);
+      }
+
+      cff.charset = charset;
+      cff.encoding = encoding;
+      var charStringsAndSeacs = this.parseCharStrings({
+        charStrings: charStringIndex,
+        localSubrIndex: topDict.privateDict.subrsIndex,
+        globalSubrIndex: globalSubrIndex.obj,
+        fdSelect: cff.fdSelect,
+        fdArray: cff.fdArray,
+        privateDict: topDict.privateDict
+      });
+      cff.charStrings = charStringsAndSeacs.charStrings;
+      cff.seacs = charStringsAndSeacs.seacs;
+      cff.widths = charStringsAndSeacs.widths;
+      return cff;
+    },
+    parseHeader: function CFFParser_parseHeader() {
+      var bytes = this.bytes;
+      var bytesLength = bytes.length;
+      var offset = 0;
+
+      while (offset < bytesLength && bytes[offset] !== 1) {
+        ++offset;
+      }
+
+      if (offset >= bytesLength) {
+        throw new _util.FormatError('Invalid CFF header');
+      }
+
+      if (offset !== 0) {
+        (0, _util.info)('cff data is shifted');
+        bytes = bytes.subarray(offset);
+        this.bytes = bytes;
+      }
+
+      var major = bytes[0];
+      var minor = bytes[1];
+      var hdrSize = bytes[2];
+      var offSize = bytes[3];
+      var header = new CFFHeader(major, minor, hdrSize, offSize);
+      return {
+        obj: header,
+        endPos: hdrSize
+      };
+    },
+    parseDict: function CFFParser_parseDict(dict) {
+      var pos = 0;
+
+      function parseOperand() {
+        var value = dict[pos++];
+
+        if (value === 30) {
+          return parseFloatOperand();
+        } else if (value === 28) {
+          value = dict[pos++];
+          value = (value << 24 | dict[pos++] << 16) >> 16;
+          return value;
+        } else if (value === 29) {
+          value = dict[pos++];
+          value = value << 8 | dict[pos++];
+          value = value << 8 | dict[pos++];
+          value = value << 8 | dict[pos++];
+          return value;
+        } else if (value >= 32 && value <= 246) {
+          return value - 139;
+        } else if (value >= 247 && value <= 250) {
+          return (value - 247) * 256 + dict[pos++] + 108;
+        } else if (value >= 251 && value <= 254) {
+          return -((value - 251) * 256) - dict[pos++] - 108;
+        }
+
+        (0, _util.warn)('CFFParser_parseDict: "' + value + '" is a reserved command.');
+        return NaN;
+      }
+
+      function parseFloatOperand() {
+        var str = '';
+        var eof = 15;
+        var lookup = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', 'E', 'E-', null, '-'];
+        var length = dict.length;
+
+        while (pos < length) {
+          var b = dict[pos++];
+          var b1 = b >> 4;
+          var b2 = b & 15;
+
+          if (b1 === eof) {
+            break;
+          }
+
+          str += lookup[b1];
+
+          if (b2 === eof) {
+            break;
+          }
+
+          str += lookup[b2];
+        }
+
+        return parseFloat(str);
+      }
+
+      var operands = [];
+      var entries = [];
+      pos = 0;
+      var end = dict.length;
+
+      while (pos < end) {
+        var b = dict[pos];
+
+        if (b <= 21) {
+          if (b === 12) {
+            b = b << 8 | dict[++pos];
+          }
+
+          entries.push([b, operands]);
+          operands = [];
+          ++pos;
+        } else {
+          operands.push(parseOperand());
+        }
+      }
+
+      return entries;
+    },
+    parseIndex: function CFFParser_parseIndex(pos) {
+      var cffIndex = new CFFIndex();
+      var bytes = this.bytes;
+      var count = bytes[pos++] << 8 | bytes[pos++];
+      var offsets = [];
+      var end = pos;
+      var i, ii;
+
+      if (count !== 0) {
+        var offsetSize = bytes[pos++];
+        var startPos = pos + (count + 1) * offsetSize - 1;
+
+        for (i = 0, ii = count + 1; i < ii; ++i) {
+          var offset = 0;
+
+          for (var j = 0; j < offsetSize; ++j) {
+            offset <<= 8;
+            offset += bytes[pos++];
+          }
+
+          offsets.push(startPos + offset);
+        }
+
+        end = offsets[count];
+      }
+
+      for (i = 0, ii = offsets.length - 1; i < ii; ++i) {
+        var offsetStart = offsets[i];
+        var offsetEnd = offsets[i + 1];
+        cffIndex.add(bytes.subarray(offsetStart, offsetEnd));
+      }
+
+      return {
+        obj: cffIndex,
+        endPos: end
+      };
+    },
+    parseNameIndex: function CFFParser_parseNameIndex(index) {
+      var names = [];
+
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var name = index.get(i);
+        names.push((0, _util.bytesToString)(name));
+      }
+
+      return names;
+    },
+    parseStringIndex: function CFFParser_parseStringIndex(index) {
+      var strings = new CFFStrings();
+
+      for (var i = 0, ii = index.count; i < ii; ++i) {
+        var data = index.get(i);
+        strings.add((0, _util.bytesToString)(data));
+      }
+
+      return strings;
+    },
+    createDict: function CFFParser_createDict(Type, dict, strings) {
+      var cffDict = new Type(strings);
+
+      for (var i = 0, ii = dict.length; i < ii; ++i) {
+        var pair = dict[i];
+        var key = pair[0];
+        var value = pair[1];
+        cffDict.setByKey(key, value);
+      }
+
+      return cffDict;
+    },
+    parseCharString: function CFFParser_parseCharString(state, data, localSubrIndex, globalSubrIndex) {
+      if (!data || state.callDepth > MAX_SUBR_NESTING) {
+        return false;
+      }
+
+      var stackSize = state.stackSize;
+      var stack = state.stack;
+      var length = data.length;
+
+      for (var j = 0; j < length;) {
+        var value = data[j++];
+        var validationCommand = null;
+
+        if (value === 12) {
+          var q = data[j++];
+
+          if (q === 0) {
+            data[j - 2] = 139;
+            data[j - 1] = 22;
+            stackSize = 0;
+          } else {
+            validationCommand = CharstringValidationData12[q];
+          }
+        } else if (value === 28) {
+          stack[stackSize] = (data[j] << 24 | data[j + 1] << 16) >> 16;
+          j += 2;
+          stackSize++;
+        } else if (value === 14) {
+          if (stackSize >= 4) {
+            stackSize -= 4;
+
+            if (this.seacAnalysisEnabled) {
+              state.seac = stack.slice(stackSize, stackSize + 4);
+              return false;
+            }
+          }
+
+          validationCommand = CharstringValidationData[value];
+        } else if (value >= 32 && value <= 246) {
+          stack[stackSize] = value - 139;
+          stackSize++;
+        } else if (value >= 247 && value <= 254) {
+          stack[stackSize] = value < 251 ? (value - 247 << 8) + data[j] + 108 : -(value - 251 << 8) - data[j] - 108;
+          j++;
+          stackSize++;
+        } else if (value === 255) {
+          stack[stackSize] = (data[j] << 24 | data[j + 1] << 16 | data[j + 2] << 8 | data[j + 3]) / 65536;
+          j += 4;
+          stackSize++;
+        } else if (value === 19 || value === 20) {
+          state.hints += stackSize >> 1;
+          j += state.hints + 7 >> 3;
+          stackSize %= 2;
+          validationCommand = CharstringValidationData[value];
+        } else if (value === 10 || value === 29) {
+          var subrsIndex;
+
+          if (value === 10) {
+            subrsIndex = localSubrIndex;
+          } else {
+            subrsIndex = globalSubrIndex;
+          }
+
+          if (!subrsIndex) {
+            validationCommand = CharstringValidationData[value];
+            (0, _util.warn)('Missing subrsIndex for ' + validationCommand.id);
+            return false;
+          }
+
+          var bias = 32768;
+
+          if (subrsIndex.count < 1240) {
+            bias = 107;
+          } else if (subrsIndex.count < 33900) {
+            bias = 1131;
+          }
+
+          var subrNumber = stack[--stackSize] + bias;
+
+          if (subrNumber < 0 || subrNumber >= subrsIndex.count || isNaN(subrNumber)) {
+            validationCommand = CharstringValidationData[value];
+            (0, _util.warn)('Out of bounds subrIndex for ' + validationCommand.id);
+            return false;
+          }
+
+          state.stackSize = stackSize;
+          state.callDepth++;
+          var valid = this.parseCharString(state, subrsIndex.get(subrNumber), localSubrIndex, globalSubrIndex);
+
+          if (!valid) {
+            return false;
+          }
+
+          state.callDepth--;
+          stackSize = state.stackSize;
+          continue;
+        } else if (value === 11) {
+          state.stackSize = stackSize;
+          return true;
+        } else {
+          validationCommand = CharstringValidationData[value];
+        }
+
+        if (validationCommand) {
+          if (validationCommand.stem) {
+            state.hints += stackSize >> 1;
+
+            if (value === 3 || value === 23) {
+              state.hasVStems = true;
+            } else if (state.hasVStems && (value === 1 || value === 18)) {
+              (0, _util.warn)('CFF stem hints are in wrong order');
+              data[j - 1] = value === 1 ? 3 : 23;
+            }
+          }
+
+          if ('min' in validationCommand) {
+            if (!state.undefStack && stackSize < validationCommand.min) {
+              (0, _util.warn)('Not enough parameters for ' + validationCommand.id + '; actual: ' + stackSize + ', expected: ' + validationCommand.min);
+              return false;
+            }
+          }
+
+          if (state.firstStackClearing && validationCommand.stackClearing) {
+            state.firstStackClearing = false;
+            stackSize -= validationCommand.min;
+
+            if (stackSize >= 2 && validationCommand.stem) {
+              stackSize %= 2;
+            } else if (stackSize > 1) {
+              (0, _util.warn)('Found too many parameters for stack-clearing command');
+            }
+
+            if (stackSize > 0 && stack[stackSize - 1] >= 0) {
+              state.width = stack[stackSize - 1];
+            }
+          }
+
+          if ('stackDelta' in validationCommand) {
+            if ('stackFn' in validationCommand) {
+              validationCommand.stackFn(stack, stackSize);
+            }
+
+            stackSize += validationCommand.stackDelta;
+          } else if (validationCommand.stackClearing) {
+            stackSize = 0;
+          } else if (validationCommand.resetStack) {
+            stackSize = 0;
+            state.undefStack = false;
+          } else if (validationCommand.undefStack) {
+            stackSize = 0;
+            state.undefStack = true;
+            state.firstStackClearing = false;
+          }
+        }
+      }
+
+      state.stackSize = stackSize;
+      return true;
+    },
+    parseCharStrings: function parseCharStrings(_ref) {
+      var charStrings = _ref.charStrings,
+          localSubrIndex = _ref.localSubrIndex,
+          globalSubrIndex = _ref.globalSubrIndex,
+          fdSelect = _ref.fdSelect,
+          fdArray = _ref.fdArray,
+          privateDict = _ref.privateDict;
+      var seacs = [];
+      var widths = [];
+      var count = charStrings.count;
+
+      for (var i = 0; i < count; i++) {
+        var charstring = charStrings.get(i);
+        var state = {
+          callDepth: 0,
+          stackSize: 0,
+          stack: [],
+          undefStack: true,
+          hints: 0,
+          firstStackClearing: true,
+          seac: null,
+          width: null,
+          hasVStems: false
+        };
+        var valid = true;
+        var localSubrToUse = null;
+        var privateDictToUse = privateDict;
+
+        if (fdSelect && fdArray.length) {
+          var fdIndex = fdSelect.getFDIndex(i);
+
+          if (fdIndex === -1) {
+            (0, _util.warn)('Glyph index is not in fd select.');
+            valid = false;
+          }
+
+          if (fdIndex >= fdArray.length) {
+            (0, _util.warn)('Invalid fd index for glyph index.');
+            valid = false;
+          }
+
+          if (valid) {
+            privateDictToUse = fdArray[fdIndex].privateDict;
+            localSubrToUse = privateDictToUse.subrsIndex;
+          }
+        } else if (localSubrIndex) {
+          localSubrToUse = localSubrIndex;
+        }
+
+        if (valid) {
+          valid = this.parseCharString(state, charstring, localSubrToUse, globalSubrIndex);
+        }
+
+        if (state.width !== null) {
+          var nominalWidth = privateDictToUse.getByName('nominalWidthX');
+          widths[i] = nominalWidth + state.width;
+        } else {
+          var defaultWidth = privateDictToUse.getByName('defaultWidthX');
+          widths[i] = defaultWidth;
+        }
+
+        if (state.seac !== null) {
+          seacs[i] = state.seac;
+        }
+
+        if (!valid) {
+          charStrings.set(i, new Uint8Array([14]));
+        }
+      }
+
+      return {
+        charStrings: charStrings,
+        seacs: seacs,
+        widths: widths
+      };
+    },
+    emptyPrivateDictionary: function CFFParser_emptyPrivateDictionary(parentDict) {
+      var privateDict = this.createDict(CFFPrivateDict, [], parentDict.strings);
+      parentDict.setByKey(18, [0, 0]);
+      parentDict.privateDict = privateDict;
+    },
+    parsePrivateDict: function CFFParser_parsePrivateDict(parentDict) {
+      if (!parentDict.hasName('Private')) {
+        this.emptyPrivateDictionary(parentDict);
+        return;
+      }
+
+      var privateOffset = parentDict.getByName('Private');
+
+      if (!Array.isArray(privateOffset) || privateOffset.length !== 2) {
+        parentDict.removeByName('Private');
+        return;
+      }
+
+      var size = privateOffset[0];
+      var offset = privateOffset[1];
+
+      if (size === 0 || offset >= this.bytes.length) {
+        this.emptyPrivateDictionary(parentDict);
+        return;
+      }
+
+      var privateDictEnd = offset + size;
+      var dictData = this.bytes.subarray(offset, privateDictEnd);
+      var dict = this.parseDict(dictData);
+      var privateDict = this.createDict(CFFPrivateDict, dict, parentDict.strings);
+      parentDict.privateDict = privateDict;
+
+      if (!privateDict.getByName('Subrs')) {
+        return;
+      }
+
+      var subrsOffset = privateDict.getByName('Subrs');
+      var relativeOffset = offset + subrsOffset;
+
+      if (subrsOffset === 0 || relativeOffset >= this.bytes.length) {
+        this.emptyPrivateDictionary(parentDict);
+        return;
+      }
+
+      var subrsIndex = this.parseIndex(relativeOffset);
+      privateDict.subrsIndex = subrsIndex.obj;
+    },
+    parseCharsets: function CFFParser_parseCharsets(pos, length, strings, cid) {
+      if (pos === 0) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.ISO_ADOBE, _charsets.ISOAdobeCharset);
+      } else if (pos === 1) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT, _charsets.ExpertCharset);
+      } else if (pos === 2) {
+        return new CFFCharset(true, CFFCharsetPredefinedTypes.EXPERT_SUBSET, _charsets.ExpertSubsetCharset);
+      }
+
+      var bytes = this.bytes;
+      var start = pos;
+      var format = bytes[pos++];
+      var charset = ['.notdef'];
+      var id, count, i;
+      length -= 1;
+
+      switch (format) {
+        case 0:
+          for (i = 0; i < length; i++) {
+            id = bytes[pos++] << 8 | bytes[pos++];
+            charset.push(cid ? id : strings.get(id));
+          }
+
+          break;
+
+        case 1:
+          while (charset.length <= length) {
+            id = bytes[pos++] << 8 | bytes[pos++];
+            count = bytes[pos++];
+
+            for (i = 0; i <= count; i++) {
+              charset.push(cid ? id++ : strings.get(id++));
+            }
+          }
+
+          break;
+
+        case 2:
+          while (charset.length <= length) {
+            id = bytes[pos++] << 8 | bytes[pos++];
+            count = bytes[pos++] << 8 | bytes[pos++];
+
+            for (i = 0; i <= count; i++) {
+              charset.push(cid ? id++ : strings.get(id++));
+            }
+          }
+
+          break;
+
+        default:
+          throw new _util.FormatError('Unknown charset format');
+      }
+
+      var end = pos;
+      var raw = bytes.subarray(start, end);
+      return new CFFCharset(false, format, charset, raw);
+    },
+    parseEncoding: function CFFParser_parseEncoding(pos, properties, strings, charset) {
+      var encoding = Object.create(null);
+      var bytes = this.bytes;
+      var predefined = false;
+      var format, i, ii;
+      var raw = null;
+
+      function readSupplement() {
+        var supplementsCount = bytes[pos++];
+
+        for (i = 0; i < supplementsCount; i++) {
+          var code = bytes[pos++];
+          var sid = (bytes[pos++] << 8) + (bytes[pos++] & 0xff);
+          encoding[code] = charset.indexOf(strings.get(sid));
+        }
+      }
+
+      if (pos === 0 || pos === 1) {
+        predefined = true;
+        format = pos;
+        var baseEncoding = pos ? _encodings.ExpertEncoding : _encodings.StandardEncoding;
+
+        for (i = 0, ii = charset.length; i < ii; i++) {
+          var index = baseEncoding.indexOf(charset[i]);
+
+          if (index !== -1) {
+            encoding[index] = i;
+          }
+        }
+      } else {
+        var dataStart = pos;
+        format = bytes[pos++];
+
+        switch (format & 0x7f) {
+          case 0:
+            var glyphsCount = bytes[pos++];
+
+            for (i = 1; i <= glyphsCount; i++) {
+              encoding[bytes[pos++]] = i;
+            }
+
+            break;
+
+          case 1:
+            var rangesCount = bytes[pos++];
+            var gid = 1;
+
+            for (i = 0; i < rangesCount; i++) {
+              var start = bytes[pos++];
+              var left = bytes[pos++];
+
+              for (var j = start; j <= start + left; j++) {
+                encoding[j] = gid++;
+              }
+            }
+
+            break;
+
+          default:
+            throw new _util.FormatError("Unknown encoding format: ".concat(format, " in CFF"));
+        }
+
+        var dataEnd = pos;
+
+        if (format & 0x80) {
+          bytes[dataStart] &= 0x7f;
+          readSupplement();
+        }
+
+        raw = bytes.subarray(dataStart, dataEnd);
+      }
+
+      format = format & 0x7f;
+      return new CFFEncoding(predefined, format, encoding, raw);
+    },
+    parseFDSelect: function CFFParser_parseFDSelect(pos, length) {
+      var bytes = this.bytes;
+      var format = bytes[pos++];
+      var fdSelect = [];
+      var i;
+
+      switch (format) {
+        case 0:
+          for (i = 0; i < length; ++i) {
+            var id = bytes[pos++];
+            fdSelect.push(id);
+          }
+
+          break;
+
+        case 3:
+          var rangesCount = bytes[pos++] << 8 | bytes[pos++];
+
+          for (i = 0; i < rangesCount; ++i) {
+            var first = bytes[pos++] << 8 | bytes[pos++];
+
+            if (i === 0 && first !== 0) {
+              (0, _util.warn)('parseFDSelect: The first range must have a first GID of 0' + ' -- trying to recover.');
+              first = 0;
+            }
+
+            var fdIndex = bytes[pos++];
+            var next = bytes[pos] << 8 | bytes[pos + 1];
+
+            for (var j = first; j < next; ++j) {
+              fdSelect.push(fdIndex);
+            }
+          }
+
+          pos += 2;
+          break;
+
+        default:
+          throw new _util.FormatError("parseFDSelect: Unknown format \"".concat(format, "\"."));
+      }
+
+      if (fdSelect.length !== length) {
+        throw new _util.FormatError('parseFDSelect: Invalid font data.');
+      }
+
+      return new CFFFDSelect(format, fdSelect);
+    }
+  };
+  return CFFParser;
+}();
+
+exports.CFFParser = CFFParser;
+
+var CFF = function CFFClosure() {
+  function CFF() {
+    this.header = null;
+    this.names = [];
+    this.topDict = null;
+    this.strings = new CFFStrings();
+    this.globalSubrIndex = null;
+    this.encoding = null;
+    this.charset = null;
+    this.charStrings = null;
+    this.fdArray = [];
+    this.fdSelect = null;
+    this.isCIDFont = false;
+  }
+
+  CFF.prototype = {
+    duplicateFirstGlyph: function CFF_duplicateFirstGlyph() {
+      if (this.charStrings.count >= 65535) {
+        (0, _util.warn)('Not enough space in charstrings to duplicate first glyph.');
+        return;
+      }
+
+      var glyphZero = this.charStrings.get(0);
+      this.charStrings.add(glyphZero);
+
+      if (this.isCIDFont) {
+        this.fdSelect.fdSelect.push(this.fdSelect.fdSelect[0]);
+      }
+    },
+    hasGlyphId: function CFF_hasGlyphID(id) {
+      if (id < 0 || id >= this.charStrings.count) {
+        return false;
+      }
+
+      var glyph = this.charStrings.get(id);
+      return glyph.length > 0;
+    }
+  };
+  return CFF;
+}();
+
+exports.CFF = CFF;
+
+var CFFHeader = function CFFHeaderClosure() {
+  function CFFHeader(major, minor, hdrSize, offSize) {
+    this.major = major;
+    this.minor = minor;
+    this.hdrSize = hdrSize;
+    this.offSize = offSize;
+  }
+
+  return CFFHeader;
+}();
+
+exports.CFFHeader = CFFHeader;
+
+var CFFStrings = function CFFStringsClosure() {
+  function CFFStrings() {
+    this.strings = [];
+  }
+
+  CFFStrings.prototype = {
+    get: function CFFStrings_get(index) {
+      if (index >= 0 && index <= NUM_STANDARD_CFF_STRINGS - 1) {
+        return CFFStandardStrings[index];
+      }
+
+      if (index - NUM_STANDARD_CFF_STRINGS <= this.strings.length) {
+        return this.strings[index - NUM_STANDARD_CFF_STRINGS];
+      }
+
+      return CFFStandardStrings[0];
+    },
+    getSID: function CFFStrings_getSID(str) {
+      var index = CFFStandardStrings.indexOf(str);
+
+      if (index !== -1) {
+        return index;
+      }
+
+      index = this.strings.indexOf(str);
+
+      if (index !== -1) {
+        return index + NUM_STANDARD_CFF_STRINGS;
+      }
+
+      return -1;
+    },
+    add: function CFFStrings_add(value) {
+      this.strings.push(value);
+    },
+
+    get count() {
+      return this.strings.length;
+    }
+
+  };
+  return CFFStrings;
+}();
+
+exports.CFFStrings = CFFStrings;
+
+var CFFIndex = function CFFIndexClosure() {
+  function CFFIndex() {
+    this.objects = [];
+    this.length = 0;
+  }
+
+  CFFIndex.prototype = {
+    add: function CFFIndex_add(data) {
+      this.length += data.length;
+      this.objects.push(data);
+    },
+    set: function CFFIndex_set(index, data) {
+      this.length += data.length - this.objects[index].length;
+      this.objects[index] = data;
+    },
+    get: function CFFIndex_get(index) {
+      return this.objects[index];
+    },
+
+    get count() {
+      return this.objects.length;
+    }
+
+  };
+  return CFFIndex;
+}();
+
+exports.CFFIndex = CFFIndex;
+
+var CFFDict = function CFFDictClosure() {
+  function CFFDict(tables, strings) {
+    this.keyToNameMap = tables.keyToNameMap;
+    this.nameToKeyMap = tables.nameToKeyMap;
+    this.defaults = tables.defaults;
+    this.types = tables.types;
+    this.opcodes = tables.opcodes;
+    this.order = tables.order;
+    this.strings = strings;
+    this.values = Object.create(null);
+  }
+
+  CFFDict.prototype = {
+    setByKey: function CFFDict_setByKey(key, value) {
+      if (!(key in this.keyToNameMap)) {
+        return false;
+      }
+
+      var valueLength = value.length;
+
+      if (valueLength === 0) {
+        return true;
+      }
+
+      for (var i = 0; i < valueLength; i++) {
+        if (isNaN(value[i])) {
+          (0, _util.warn)('Invalid CFFDict value: "' + value + '" for key "' + key + '".');
+          return true;
+        }
+      }
+
+      var type = this.types[key];
+
+      if (type === 'num' || type === 'sid' || type === 'offset') {
+        value = value[0];
+      }
+
+      this.values[key] = value;
+      return true;
+    },
+    setByName: function CFFDict_setByName(name, value) {
+      if (!(name in this.nameToKeyMap)) {
+        throw new _util.FormatError("Invalid dictionary name \"".concat(name, "\""));
+      }
+
+      this.values[this.nameToKeyMap[name]] = value;
+    },
+    hasName: function CFFDict_hasName(name) {
+      return this.nameToKeyMap[name] in this.values;
+    },
+    getByName: function CFFDict_getByName(name) {
+      if (!(name in this.nameToKeyMap)) {
+        throw new _util.FormatError("Invalid dictionary name ".concat(name, "\""));
+      }
+
+      var key = this.nameToKeyMap[name];
+
+      if (!(key in this.values)) {
+        return this.defaults[key];
+      }
+
+      return this.values[key];
+    },
+    removeByName: function CFFDict_removeByName(name) {
+      delete this.values[this.nameToKeyMap[name]];
+    }
+  };
+
+  CFFDict.createTables = function CFFDict_createTables(layout) {
+    var tables = {
+      keyToNameMap: {},
+      nameToKeyMap: {},
+      defaults: {},
+      types: {},
+      opcodes: {},
+      order: []
+    };
+
+    for (var i = 0, ii = layout.length; i < ii; ++i) {
+      var entry = layout[i];
+      var key = Array.isArray(entry[0]) ? (entry[0][0] << 8) + entry[0][1] : entry[0];
+      tables.keyToNameMap[key] = entry[1];
+      tables.nameToKeyMap[entry[1]] = key;
+      tables.types[key] = entry[2];
+      tables.defaults[key] = entry[3];
+      tables.opcodes[key] = Array.isArray(entry[0]) ? entry[0] : [entry[0]];
+      tables.order.push(key);
+    }
+
+    return tables;
+  };
+
+  return CFFDict;
+}();
+
+var CFFTopDict = function CFFTopDictClosure() {
+  var layout = [[[12, 30], 'ROS', ['sid', 'sid', 'num'], null], [[12, 20], 'SyntheticBase', 'num', null], [0, 'version', 'sid', null], [1, 'Notice', 'sid', null], [[12, 0], 'Copyright', 'sid', null], [2, 'FullName', 'sid', null], [3, 'FamilyName', 'sid', null], [4, 'Weight', 'sid', null], [[12, 1], 'isFixedPitch', 'num', 0], [[12, 2], 'ItalicAngle', 'num', 0], [[12, 3], 'UnderlinePosition', 'num', -100], [[12, 4], 'UnderlineThickness', 'num', 50], [[12, 5], 'PaintType', 'num', 0], [[12, 6], 'CharstringType', 'num', 2], [[12, 7], 'FontMatrix', ['num', 'num', 'num', 'num', 'num', 'num'], [0.001, 0, 0, 0.001, 0, 0]], [13, 'UniqueID', 'num', null], [5, 'FontBBox', ['num', 'num', 'num', 'num'], [0, 0, 0, 0]], [[12, 8], 'StrokeWidth', 'num', 0], [14, 'XUID', 'array', null], [15, 'charset', 'offset', 0], [16, 'Encoding', 'offset', 0], [17, 'CharStrings', 'offset', 0], [18, 'Private', ['offset', 'offset'], null], [[12, 21], 'PostScript', 'sid', null], [[12, 22], 'BaseFontName', 'sid', null], [[12, 23], 'BaseFontBlend', 'delta', null], [[12, 31], 'CIDFontVersion', 'num', 0], [[12, 32], 'CIDFontRevision', 'num', 0], [[12, 33], 'CIDFontType', 'num', 0], [[12, 34], 'CIDCount', 'num', 8720], [[12, 35], 'UIDBase', 'num', null], [[12, 37], 'FDSelect', 'offset', null], [[12, 36], 'FDArray', 'offset', null], [[12, 38], 'FontName', 'sid', null]];
+  var tables = null;
+
+  function CFFTopDict(strings) {
+    if (tables === null) {
+      tables = CFFDict.createTables(layout);
+    }
+
+    CFFDict.call(this, tables, strings);
+    this.privateDict = null;
+  }
+
+  CFFTopDict.prototype = Object.create(CFFDict.prototype);
+  return CFFTopDict;
+}();
+
+exports.CFFTopDict = CFFTopDict;
+
+var CFFPrivateDict = function CFFPrivateDictClosure() {
+  var layout = [[6, 'BlueValues', 'delta', null], [7, 'OtherBlues', 'delta', null], [8, 'FamilyBlues', 'delta', null], [9, 'FamilyOtherBlues', 'delta', null], [[12, 9], 'BlueScale', 'num', 0.039625], [[12, 10], 'BlueShift', 'num', 7], [[12, 11], 'BlueFuzz', 'num', 1], [10, 'StdHW', 'num', null], [11, 'StdVW', 'num', null], [[12, 12], 'StemSnapH', 'delta', null], [[12, 13], 'StemSnapV', 'delta', null], [[12, 14], 'ForceBold', 'num', 0], [[12, 17], 'LanguageGroup', 'num', 0], [[12, 18], 'ExpansionFactor', 'num', 0.06], [[12, 19], 'initialRandomSeed', 'num', 0], [20, 'defaultWidthX', 'num', 0], [21, 'nominalWidthX', 'num', 0], [19, 'Subrs', 'offset', null]];
+  var tables = null;
+
+  function CFFPrivateDict(strings) {
+    if (tables === null) {
+      tables = CFFDict.createTables(layout);
+    }
+
+    CFFDict.call(this, tables, strings);
+    this.subrsIndex = null;
+  }
+
+  CFFPrivateDict.prototype = Object.create(CFFDict.prototype);
+  return CFFPrivateDict;
+}();
+
+exports.CFFPrivateDict = CFFPrivateDict;
+var CFFCharsetPredefinedTypes = {
+  ISO_ADOBE: 0,
+  EXPERT: 1,
+  EXPERT_SUBSET: 2
+};
+
+var CFFCharset = function CFFCharsetClosure() {
+  function CFFCharset(predefined, format, charset, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.charset = charset;
+    this.raw = raw;
+  }
+
+  return CFFCharset;
+}();
+
+exports.CFFCharset = CFFCharset;
+
+var CFFEncoding = function CFFEncodingClosure() {
+  function CFFEncoding(predefined, format, encoding, raw) {
+    this.predefined = predefined;
+    this.format = format;
+    this.encoding = encoding;
+    this.raw = raw;
+  }
+
+  return CFFEncoding;
+}();
+
+var CFFFDSelect = function CFFFDSelectClosure() {
+  function CFFFDSelect(format, fdSelect) {
+    this.format = format;
+    this.fdSelect = fdSelect;
+  }
+
+  CFFFDSelect.prototype = {
+    getFDIndex: function CFFFDSelect_get(glyphIndex) {
+      if (glyphIndex < 0 || glyphIndex >= this.fdSelect.length) {
+        return -1;
+      }
+
+      return this.fdSelect[glyphIndex];
+    }
+  };
+  return CFFFDSelect;
+}();
+
+exports.CFFFDSelect = CFFFDSelect;
+
+var CFFOffsetTracker = function CFFOffsetTrackerClosure() {
+  function CFFOffsetTracker() {
+    this.offsets = Object.create(null);
+  }
+
+  CFFOffsetTracker.prototype = {
+    isTracking: function CFFOffsetTracker_isTracking(key) {
+      return key in this.offsets;
+    },
+    track: function CFFOffsetTracker_track(key, location) {
+      if (key in this.offsets) {
+        throw new _util.FormatError("Already tracking location of ".concat(key));
+      }
+
+      this.offsets[key] = location;
+    },
+    offset: function CFFOffsetTracker_offset(value) {
+      for (var key in this.offsets) {
+        this.offsets[key] += value;
+      }
+    },
+    setEntryLocation: function CFFOffsetTracker_setEntryLocation(key, values, output) {
+      if (!(key in this.offsets)) {
+        throw new _util.FormatError("Not tracking location of ".concat(key));
+      }
+
+      var data = output.data;
+      var dataOffset = this.offsets[key];
+      var size = 5;
+
+      for (var i = 0, ii = values.length; i < ii; ++i) {
+        var offset0 = i * size + dataOffset;
+        var offset1 = offset0 + 1;
+        var offset2 = offset0 + 2;
+        var offset3 = offset0 + 3;
+        var offset4 = offset0 + 4;
+
+        if (data[offset0] !== 0x1d || data[offset1] !== 0 || data[offset2] !== 0 || data[offset3] !== 0 || data[offset4] !== 0) {
+          throw new _util.FormatError('writing to an offset that is not empty');
+        }
+
+        var value = values[i];
+        data[offset0] = 0x1d;
+        data[offset1] = value >> 24 & 0xFF;
+        data[offset2] = value >> 16 & 0xFF;
+        data[offset3] = value >> 8 & 0xFF;
+        data[offset4] = value & 0xFF;
+      }
+    }
+  };
+  return CFFOffsetTracker;
+}();
+
+var CFFCompiler = function CFFCompilerClosure() {
+  function CFFCompiler(cff) {
+    this.cff = cff;
+  }
+
+  CFFCompiler.prototype = {
+    compile: function CFFCompiler_compile() {
+      var cff = this.cff;
+      var output = {
+        data: [],
+        length: 0,
+        add: function CFFCompiler_add(data) {
+          this.data = this.data.concat(data);
+          this.length = this.data.length;
+        }
+      };
+      var header = this.compileHeader(cff.header);
+      output.add(header);
+      var nameIndex = this.compileNameIndex(cff.names);
+      output.add(nameIndex);
+
+      if (cff.isCIDFont) {
+        if (cff.topDict.hasName('FontMatrix')) {
+          var base = cff.topDict.getByName('FontMatrix');
+          cff.topDict.removeByName('FontMatrix');
+
+          for (var i = 0, ii = cff.fdArray.length; i < ii; i++) {
+            var subDict = cff.fdArray[i];
+            var matrix = base.slice(0);
+
+            if (subDict.hasName('FontMatrix')) {
+              matrix = _util.Util.transform(matrix, subDict.getByName('FontMatrix'));
+            }
+
+            subDict.setByName('FontMatrix', matrix);
+          }
+        }
+      }
+
+      cff.topDict.setByName('charset', 0);
+      var compiled = this.compileTopDicts([cff.topDict], output.length, cff.isCIDFont);
+      output.add(compiled.output);
+      var topDictTracker = compiled.trackers[0];
+      var stringIndex = this.compileStringIndex(cff.strings.strings);
+      output.add(stringIndex);
+      var globalSubrIndex = this.compileIndex(cff.globalSubrIndex);
+      output.add(globalSubrIndex);
+
+      if (cff.encoding && cff.topDict.hasName('Encoding')) {
+        if (cff.encoding.predefined) {
+          topDictTracker.setEntryLocation('Encoding', [cff.encoding.format], output);
+        } else {
+          var encoding = this.compileEncoding(cff.encoding);
+          topDictTracker.setEntryLocation('Encoding', [output.length], output);
+          output.add(encoding);
+        }
+      }
+
+      var charset = this.compileCharset(cff.charset, cff.charStrings.count, cff.strings, cff.isCIDFont);
+      topDictTracker.setEntryLocation('charset', [output.length], output);
+      output.add(charset);
+      var charStrings = this.compileCharStrings(cff.charStrings);
+      topDictTracker.setEntryLocation('CharStrings', [output.length], output);
+      output.add(charStrings);
+
+      if (cff.isCIDFont) {
+        topDictTracker.setEntryLocation('FDSelect', [output.length], output);
+        var fdSelect = this.compileFDSelect(cff.fdSelect);
+        output.add(fdSelect);
+        compiled = this.compileTopDicts(cff.fdArray, output.length, true);
+        topDictTracker.setEntryLocation('FDArray', [output.length], output);
+        output.add(compiled.output);
+        var fontDictTrackers = compiled.trackers;
+        this.compilePrivateDicts(cff.fdArray, fontDictTrackers, output);
+      }
+
+      this.compilePrivateDicts([cff.topDict], [topDictTracker], output);
+      output.add([0]);
+      return output.data;
+    },
+    encodeNumber: function CFFCompiler_encodeNumber(value) {
+      if (parseFloat(value) === parseInt(value, 10) && !isNaN(value)) {
+        return this.encodeInteger(value);
+      }
+
+      return this.encodeFloat(value);
+    },
+    encodeFloat: function CFFCompiler_encodeFloat(num) {
+      var value = num.toString();
+      var m = /\.(\d*?)(?:9{5,20}|0{5,20})\d{0,2}(?:e(.+)|$)/.exec(value);
+
+      if (m) {
+        var epsilon = parseFloat('1e' + ((m[2] ? +m[2] : 0) + m[1].length));
+        value = (Math.round(num * epsilon) / epsilon).toString();
+      }
+
+      var nibbles = '';
+      var i, ii;
+
+      for (i = 0, ii = value.length; i < ii; ++i) {
+        var a = value[i];
+
+        if (a === 'e') {
+          nibbles += value[++i] === '-' ? 'c' : 'b';
+        } else if (a === '.') {
+          nibbles += 'a';
+        } else if (a === '-') {
+          nibbles += 'e';
+        } else {
+          nibbles += a;
+        }
+      }
+
+      nibbles += nibbles.length & 1 ? 'f' : 'ff';
+      var out = [30];
+
+      for (i = 0, ii = nibbles.length; i < ii; i += 2) {
+        out.push(parseInt(nibbles.substring(i, i + 2), 16));
+      }
+
+      return out;
+    },
+    encodeInteger: function CFFCompiler_encodeInteger(value) {
+      var code;
+
+      if (value >= -107 && value <= 107) {
+        code = [value + 139];
+      } else if (value >= 108 && value <= 1131) {
+        value = value - 108;
+        code = [(value >> 8) + 247, value & 0xFF];
+      } else if (value >= -1131 && value <= -108) {
+        value = -value - 108;
+        code = [(value >> 8) + 251, value & 0xFF];
+      } else if (value >= -32768 && value <= 32767) {
+        code = [0x1c, value >> 8 & 0xFF, value & 0xFF];
+      } else {
+        code = [0x1d, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF];
+      }
+
+      return code;
+    },
+    compileHeader: function CFFCompiler_compileHeader(header) {
+      return [header.major, header.minor, header.hdrSize, header.offSize];
+    },
+    compileNameIndex: function CFFCompiler_compileNameIndex(names) {
+      var nameIndex = new CFFIndex();
+
+      for (var i = 0, ii = names.length; i < ii; ++i) {
+        var name = names[i];
+        var length = Math.min(name.length, 127);
+        var sanitizedName = new Array(length);
+
+        for (var j = 0; j < length; j++) {
+          var _char = name[j];
+
+          if (_char < '!' || _char > '~' || _char === '[' || _char === ']' || _char === '(' || _char === ')' || _char === '{' || _char === '}' || _char === '<' || _char === '>' || _char === '/' || _char === '%') {
+            _char = '_';
+          }
+
+          sanitizedName[j] = _char;
+        }
+
+        sanitizedName = sanitizedName.join('');
+
+        if (sanitizedName === '') {
+          sanitizedName = 'Bad_Font_Name';
+        }
+
+        nameIndex.add((0, _util.stringToBytes)(sanitizedName));
+      }
+
+      return this.compileIndex(nameIndex);
+    },
+    compileTopDicts: function CFFCompiler_compileTopDicts(dicts, length, removeCidKeys) {
+      var fontDictTrackers = [];
+      var fdArrayIndex = new CFFIndex();
+
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+
+        if (removeCidKeys) {
+          fontDict.removeByName('CIDFontVersion');
+          fontDict.removeByName('CIDFontRevision');
+          fontDict.removeByName('CIDFontType');
+          fontDict.removeByName('CIDCount');
+          fontDict.removeByName('UIDBase');
+        }
+
+        var fontDictTracker = new CFFOffsetTracker();
+        var fontDictData = this.compileDict(fontDict, fontDictTracker);
+        fontDictTrackers.push(fontDictTracker);
+        fdArrayIndex.add(fontDictData);
+        fontDictTracker.offset(length);
+      }
+
+      fdArrayIndex = this.compileIndex(fdArrayIndex, fontDictTrackers);
+      return {
+        trackers: fontDictTrackers,
+        output: fdArrayIndex
+      };
+    },
+    compilePrivateDicts: function CFFCompiler_compilePrivateDicts(dicts, trackers, output) {
+      for (var i = 0, ii = dicts.length; i < ii; ++i) {
+        var fontDict = dicts[i];
+        var privateDict = fontDict.privateDict;
+
+        if (!privateDict || !fontDict.hasName('Private')) {
+          throw new _util.FormatError('There must be a private dictionary.');
+        }
+
+        var privateDictTracker = new CFFOffsetTracker();
+        var privateDictData = this.compileDict(privateDict, privateDictTracker);
+        var outputLength = output.length;
+        privateDictTracker.offset(outputLength);
+
+        if (!privateDictData.length) {
+          outputLength = 0;
+        }
+
+        trackers[i].setEntryLocation('Private', [privateDictData.length, outputLength], output);
+        output.add(privateDictData);
+
+        if (privateDict.subrsIndex && privateDict.hasName('Subrs')) {
+          var subrs = this.compileIndex(privateDict.subrsIndex);
+          privateDictTracker.setEntryLocation('Subrs', [privateDictData.length], output);
+          output.add(subrs);
+        }
+      }
+    },
+    compileDict: function CFFCompiler_compileDict(dict, offsetTracker) {
+      var out = [];
+      var order = dict.order;
+
+      for (var i = 0; i < order.length; ++i) {
+        var key = order[i];
+
+        if (!(key in dict.values)) {
+          continue;
+        }
+
+        var values = dict.values[key];
+        var types = dict.types[key];
+
+        if (!Array.isArray(types)) {
+          types = [types];
+        }
+
+        if (!Array.isArray(values)) {
+          values = [values];
+        }
+
+        if (values.length === 0) {
+          continue;
+        }
+
+        for (var j = 0, jj = types.length; j < jj; ++j) {
+          var type = types[j];
+          var value = values[j];
+
+          switch (type) {
+            case 'num':
+            case 'sid':
+              out = out.concat(this.encodeNumber(value));
+              break;
+
+            case 'offset':
+              var name = dict.keyToNameMap[key];
+
+              if (!offsetTracker.isTracking(name)) {
+                offsetTracker.track(name, out.length);
+              }
+
+              out = out.concat([0x1d, 0, 0, 0, 0]);
+              break;
+
+            case 'array':
+            case 'delta':
+              out = out.concat(this.encodeNumber(value));
+
+              for (var k = 1, kk = values.length; k < kk; ++k) {
+                out = out.concat(this.encodeNumber(values[k]));
+              }
+
+              break;
+
+            default:
+              throw new _util.FormatError("Unknown data type of ".concat(type));
+          }
+        }
+
+        out = out.concat(dict.opcodes[key]);
+      }
+
+      return out;
+    },
+    compileStringIndex: function CFFCompiler_compileStringIndex(strings) {
+      var stringIndex = new CFFIndex();
+
+      for (var i = 0, ii = strings.length; i < ii; ++i) {
+        stringIndex.add((0, _util.stringToBytes)(strings[i]));
+      }
+
+      return this.compileIndex(stringIndex);
+    },
+    compileGlobalSubrIndex: function CFFCompiler_compileGlobalSubrIndex() {
+      var globalSubrIndex = this.cff.globalSubrIndex;
+      this.out.writeByteArray(this.compileIndex(globalSubrIndex));
+    },
+    compileCharStrings: function CFFCompiler_compileCharStrings(charStrings) {
+      var charStringsIndex = new CFFIndex();
+
+      for (var i = 0; i < charStrings.count; i++) {
+        var glyph = charStrings.get(i);
+
+        if (glyph.length === 0) {
+          charStringsIndex.add(new Uint8Array([0x8B, 0x0E]));
+          continue;
+        }
+
+        charStringsIndex.add(glyph);
+      }
+
+      return this.compileIndex(charStringsIndex);
+    },
+    compileCharset: function CFFCompiler_compileCharset(charset, numGlyphs, strings, isCIDFont) {
+      var out;
+      var numGlyphsLessNotDef = numGlyphs - 1;
+
+      if (isCIDFont) {
+        out = new Uint8Array([2, 0, 0, numGlyphsLessNotDef >> 8 & 0xFF, numGlyphsLessNotDef & 0xFF]);
+      } else {
+        var length = 1 + numGlyphsLessNotDef * 2;
+        out = new Uint8Array(length);
+        out[0] = 0;
+        var charsetIndex = 0;
+        var numCharsets = charset.charset.length;
+        var warned = false;
+
+        for (var i = 1; i < out.length; i += 2) {
+          var sid = 0;
+
+          if (charsetIndex < numCharsets) {
+            var name = charset.charset[charsetIndex++];
+            sid = strings.getSID(name);
+
+            if (sid === -1) {
+              sid = 0;
+
+              if (!warned) {
+                warned = true;
+                (0, _util.warn)("Couldn't find ".concat(name, " in CFF strings"));
+              }
+            }
+          }
+
+          out[i] = sid >> 8 & 0xFF;
+          out[i + 1] = sid & 0xFF;
+        }
+      }
+
+      return this.compileTypedArray(out);
+    },
+    compileEncoding: function CFFCompiler_compileEncoding(encoding) {
+      return this.compileTypedArray(encoding.raw);
+    },
+    compileFDSelect: function CFFCompiler_compileFDSelect(fdSelect) {
+      var format = fdSelect.format;
+      var out, i;
+
+      switch (format) {
+        case 0:
+          out = new Uint8Array(1 + fdSelect.fdSelect.length);
+          out[0] = format;
+
+          for (i = 0; i < fdSelect.fdSelect.length; i++) {
+            out[i + 1] = fdSelect.fdSelect[i];
+          }
+
+          break;
+
+        case 3:
+          var start = 0;
+          var lastFD = fdSelect.fdSelect[0];
+          var ranges = [format, 0, 0, start >> 8 & 0xFF, start & 0xFF, lastFD];
+
+          for (i = 1; i < fdSelect.fdSelect.length; i++) {
+            var currentFD = fdSelect.fdSelect[i];
+
+            if (currentFD !== lastFD) {
+              ranges.push(i >> 8 & 0xFF, i & 0xFF, currentFD);
+              lastFD = currentFD;
+            }
+          }
+
+          var numRanges = (ranges.length - 3) / 3;
+          ranges[1] = numRanges >> 8 & 0xFF;
+          ranges[2] = numRanges & 0xFF;
+          ranges.push(i >> 8 & 0xFF, i & 0xFF);
+          out = new Uint8Array(ranges);
+          break;
+      }
+
+      return this.compileTypedArray(out);
+    },
+    compileTypedArray: function CFFCompiler_compileTypedArray(data) {
+      var out = [];
+
+      for (var i = 0, ii = data.length; i < ii; ++i) {
+        out[i] = data[i];
+      }
+
+      return out;
+    },
+    compileIndex: function CFFCompiler_compileIndex(index, trackers) {
+      trackers = trackers || [];
+      var objects = index.objects;
+      var count = objects.length;
+
+      if (count === 0) {
+        return [0, 0, 0];
+      }
+
+      var data = [count >> 8 & 0xFF, count & 0xff];
+      var lastOffset = 1,
+          i;
+
+      for (i = 0; i < count; ++i) {
+        lastOffset += objects[i].length;
+      }
+
+      var offsetSize;
+
+      if (lastOffset < 0x100) {
+        offsetSize = 1;
+      } else if (lastOffset < 0x10000) {
+        offsetSize = 2;
+      } else if (lastOffset < 0x1000000) {
+        offsetSize = 3;
+      } else {
+        offsetSize = 4;
+      }
+
+      data.push(offsetSize);
+      var relativeOffset = 1;
+
+      for (i = 0; i < count + 1; i++) {
+        if (offsetSize === 1) {
+          data.push(relativeOffset & 0xFF);
+        } else if (offsetSize === 2) {
+          data.push(relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
+        } else if (offsetSize === 3) {
+          data.push(relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
+        } else {
+          data.push(relativeOffset >>> 24 & 0xFF, relativeOffset >> 16 & 0xFF, relativeOffset >> 8 & 0xFF, relativeOffset & 0xFF);
+        }
+
+        if (objects[i]) {
+          relativeOffset += objects[i].length;
+        }
+      }
+
+      for (i = 0; i < count; i++) {
+        if (trackers[i]) {
+          trackers[i].offset(data.length);
+        }
+
+        for (var j = 0, jj = objects[i].length; j < jj; j++) {
+          data.push(objects[i][j]);
+        }
+      }
+
+      return data;
+    }
+  };
+  return CFFCompiler;
+}();
+
+exports.CFFCompiler = CFFCompiler;
+
+/***/ }),
+/* 176 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.ExpertSubsetCharset = exports.ExpertCharset = exports.ISOAdobeCharset = void 0;
+var ISOAdobeCharset = ['.notdef', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'endash', 'dagger', 'daggerdbl', 'periodcentered', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', 'questiondown', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron', 'emdash', 'AE', 'ordfeminine', 'Lslash', 'Oslash', 'OE', 'ordmasculine', 'ae', 'dotlessi', 'lslash', 'oslash', 'oe', 'germandbls', 'onesuperior', 'logicalnot', 'mu', 'trademark', 'Eth', 'onehalf', 'plusminus', 'Thorn', 'onequarter', 'divide', 'brokenbar', 'degree', 'thorn', 'threequarters', 'twosuperior', 'registered', 'minus', 'eth', 'multiply', 'threesuperior', 'copyright', 'Aacute', 'Acircumflex', 'Adieresis', 'Agrave', 'Aring', 'Atilde', 'Ccedilla', 'Eacute', 'Ecircumflex', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Ntilde', 'Oacute', 'Ocircumflex', 'Odieresis', 'Ograve', 'Otilde', 'Scaron', 'Uacute', 'Ucircumflex', 'Udieresis', 'Ugrave', 'Yacute', 'Ydieresis', 'Zcaron', 'aacute', 'acircumflex', 'adieresis', 'agrave', 'aring', 'atilde', 'ccedilla', 'eacute', 'ecircumflex', 'edieresis', 'egrave', 'iacute', 'icircumflex', 'idieresis', 'igrave', 'ntilde', 'oacute', 'ocircumflex', 'odieresis', 'ograve', 'otilde', 'scaron', 'uacute', 'ucircumflex', 'udieresis', 'ugrave', 'yacute', 'ydieresis', 'zcaron'];
+exports.ISOAdobeCharset = ISOAdobeCharset;
+var ExpertCharset = ['.notdef', 'space', 'exclamsmall', 'Hungarumlautsmall', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', 'Dotaccentsmall', 'Macronsmall', 'figuredash', 'hypheninferior', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', 'onequarter', 'onehalf', 'threequarters', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
+exports.ExpertCharset = ExpertCharset;
+var ExpertSubsetCharset = ['.notdef', 'space', 'dollaroldstyle', 'dollarsuperior', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', 'isuperior', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', 'rsuperior', 'ssuperior', 'tsuperior', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', 'parenrightinferior', 'hyphensuperior', 'colonmonetary', 'onefitted', 'rupiah', 'centoldstyle', 'figuredash', 'hypheninferior', 'onequarter', 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior'];
+exports.ExpertSubsetCharset = ExpertSubsetCharset;
+
+/***/ }),
+/* 177 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getEncoding = getEncoding;
+exports.ExpertEncoding = exports.ZapfDingbatsEncoding = exports.SymbolSetEncoding = exports.MacRomanEncoding = exports.StandardEncoding = exports.WinAnsiEncoding = void 0;
+var ExpertEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', '', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', 'commasuperior', 'threequartersemdash', 'periodsuperior', 'questionsmall', '', 'asuperior', 'bsuperior', 'centsuperior', 'dsuperior', 'esuperior', '', '', '', 'isuperior', '', '', 'lsuperior', 'msuperior', 'nsuperior', 'osuperior', '', '', 'rsuperior', 'ssuperior', 'tsuperior', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hyphensuperior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdownsmall', 'centoldstyle', 'Lslashsmall', '', '', 'Scaronsmall', 'Zcaronsmall', 'Dieresissmall', 'Brevesmall', 'Caronsmall', '', 'Dotaccentsmall', '', '', 'Macronsmall', '', '', 'figuredash', 'hypheninferior', '', '', 'Ogoneksmall', 'Ringsmall', 'Cedillasmall', '', '', '', 'onequarter', 'onehalf', 'threequarters', 'questiondownsmall', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', '', 'zerosuperior', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'eightsuperior', 'ninesuperior', 'zeroinferior', 'oneinferior', 'twoinferior', 'threeinferior', 'fourinferior', 'fiveinferior', 'sixinferior', 'seveninferior', 'eightinferior', 'nineinferior', 'centinferior', 'dollarinferior', 'periodinferior', 'commainferior', 'Agravesmall', 'Aacutesmall', 'Acircumflexsmall', 'Atildesmall', 'Adieresissmall', 'Aringsmall', 'AEsmall', 'Ccedillasmall', 'Egravesmall', 'Eacutesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Igravesmall', 'Iacutesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ethsmall', 'Ntildesmall', 'Ogravesmall', 'Oacutesmall', 'Ocircumflexsmall', 'Otildesmall', 'Odieresissmall', 'OEsmall', 'Oslashsmall', 'Ugravesmall', 'Uacutesmall', 'Ucircumflexsmall', 'Udieresissmall', 'Yacutesmall', 'Thornsmall', 'Ydieresissmall'];
+exports.ExpertEncoding = ExpertEncoding;
+var MacExpertEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclamsmall', 'Hungarumlautsmall', 'centoldstyle', 'dollaroldstyle', 'dollarsuperior', 'ampersandsmall', 'Acutesmall', 'parenleftsuperior', 'parenrightsuperior', 'twodotenleader', 'onedotenleader', 'comma', 'hyphen', 'period', 'fraction', 'zerooldstyle', 'oneoldstyle', 'twooldstyle', 'threeoldstyle', 'fouroldstyle', 'fiveoldstyle', 'sixoldstyle', 'sevenoldstyle', 'eightoldstyle', 'nineoldstyle', 'colon', 'semicolon', '', 'threequartersemdash', '', 'questionsmall', '', '', '', '', 'Ethsmall', '', '', 'onequarter', 'onehalf', 'threequarters', 'oneeighth', 'threeeighths', 'fiveeighths', 'seveneighths', 'onethird', 'twothirds', '', '', '', '', '', '', 'ff', 'fi', 'fl', 'ffi', 'ffl', 'parenleftinferior', '', 'parenrightinferior', 'Circumflexsmall', 'hypheninferior', 'Gravesmall', 'Asmall', 'Bsmall', 'Csmall', 'Dsmall', 'Esmall', 'Fsmall', 'Gsmall', 'Hsmall', 'Ismall', 'Jsmall', 'Ksmall', 'Lsmall', 'Msmall', 'Nsmall', 'Osmall', 'Psmall', 'Qsmall', 'Rsmall', 'Ssmall', 'Tsmall', 'Usmall', 'Vsmall', 'Wsmall', 'Xsmall', 'Ysmall', 'Zsmall', 'colonmonetary', 'onefitted', 'rupiah', 'Tildesmall', '', '', 'asuperior', 'centsuperior', '', '', '', '', 'Aacutesmall', 'Agravesmall', 'Acircumflexsmall', 'Adieresissmall', 'Atildesmall', 'Aringsmall', 'Ccedillasmall', 'Eacutesmall', 'Egravesmall', 'Ecircumflexsmall', 'Edieresissmall', 'Iacutesmall', 'Igravesmall', 'Icircumflexsmall', 'Idieresissmall', 'Ntildesmall', 'Oacutesmall', 'Ogravesmall', 'Ocircumflexsmall', 'Odieresissmall', 'Otildesmall', 'Uacutesmall', 'Ugravesmall', 'Ucircumflexsmall', 'Udieresissmall', '', 'eightsuperior', 'fourinferior', 'threeinferior', 'sixinferior', 'eightinferior', 'seveninferior', 'Scaronsmall', '', 'centinferior', 'twoinferior', '', 'Dieresissmall', '', 'Caronsmall', 'osuperior', 'fiveinferior', '', 'commainferior', 'periodinferior', 'Yacutesmall', '', 'dollarinferior', '', '', 'Thornsmall', '', 'nineinferior', 'zeroinferior', 'Zcaronsmall', 'AEsmall', 'Oslashsmall', 'questiondownsmall', 'oneinferior', 'Lslashsmall', '', '', '', '', '', '', 'Cedillasmall', '', '', '', '', '', 'OEsmall', 'figuredash', 'hyphensuperior', '', '', '', '', 'exclamdownsmall', '', 'Ydieresissmall', '', 'onesuperior', 'twosuperior', 'threesuperior', 'foursuperior', 'fivesuperior', 'sixsuperior', 'sevensuperior', 'ninesuperior', 'zerosuperior', '', 'esuperior', 'rsuperior', 'tsuperior', '', '', 'isuperior', 'ssuperior', 'dsuperior', '', '', '', '', '', 'lsuperior', 'Ogoneksmall', 'Brevesmall', 'Macronsmall', 'bsuperior', 'nsuperior', 'msuperior', 'commasuperior', 'periodsuperior', 'Dotaccentsmall', 'Ringsmall', '', '', '', ''];
+var MacRomanEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', 'Adieresis', 'Aring', 'Ccedilla', 'Eacute', 'Ntilde', 'Odieresis', 'Udieresis', 'aacute', 'agrave', 'acircumflex', 'adieresis', 'atilde', 'aring', 'ccedilla', 'eacute', 'egrave', 'ecircumflex', 'edieresis', 'iacute', 'igrave', 'icircumflex', 'idieresis', 'ntilde', 'oacute', 'ograve', 'ocircumflex', 'odieresis', 'otilde', 'uacute', 'ugrave', 'ucircumflex', 'udieresis', 'dagger', 'degree', 'cent', 'sterling', 'section', 'bullet', 'paragraph', 'germandbls', 'registered', 'copyright', 'trademark', 'acute', 'dieresis', 'notequal', 'AE', 'Oslash', 'infinity', 'plusminus', 'lessequal', 'greaterequal', 'yen', 'mu', 'partialdiff', 'summation', 'product', 'pi', 'integral', 'ordfeminine', 'ordmasculine', 'Omega', 'ae', 'oslash', 'questiondown', 'exclamdown', 'logicalnot', 'radical', 'florin', 'approxequal', 'Delta', 'guillemotleft', 'guillemotright', 'ellipsis', 'space', 'Agrave', 'Atilde', 'Otilde', 'OE', 'oe', 'endash', 'emdash', 'quotedblleft', 'quotedblright', 'quoteleft', 'quoteright', 'divide', 'lozenge', 'ydieresis', 'Ydieresis', 'fraction', 'currency', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', 'daggerdbl', 'periodcentered', 'quotesinglbase', 'quotedblbase', 'perthousand', 'Acircumflex', 'Ecircumflex', 'Aacute', 'Edieresis', 'Egrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Igrave', 'Oacute', 'Ocircumflex', 'apple', 'Ograve', 'Uacute', 'Ucircumflex', 'Ugrave', 'dotlessi', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'ring', 'cedilla', 'hungarumlaut', 'ogonek', 'caron'];
+exports.MacRomanEncoding = MacRomanEncoding;
+var StandardEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quoteright', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'quoteleft', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'exclamdown', 'cent', 'sterling', 'fraction', 'yen', 'florin', 'section', 'currency', 'quotesingle', 'quotedblleft', 'guillemotleft', 'guilsinglleft', 'guilsinglright', 'fi', 'fl', '', 'endash', 'dagger', 'daggerdbl', 'periodcentered', '', 'paragraph', 'bullet', 'quotesinglbase', 'quotedblbase', 'quotedblright', 'guillemotright', 'ellipsis', 'perthousand', '', 'questiondown', '', 'grave', 'acute', 'circumflex', 'tilde', 'macron', 'breve', 'dotaccent', 'dieresis', '', 'ring', 'cedilla', '', 'hungarumlaut', 'ogonek', 'caron', 'emdash', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'AE', '', 'ordfeminine', '', '', '', '', 'Lslash', 'Oslash', 'OE', 'ordmasculine', '', '', '', '', '', 'ae', '', '', '', 'dotlessi', '', '', 'lslash', 'oslash', 'oe', 'germandbls', '', '', '', ''];
+exports.StandardEncoding = StandardEncoding;
+var WinAnsiEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'quotedbl', 'numbersign', 'dollar', 'percent', 'ampersand', 'quotesingle', 'parenleft', 'parenright', 'asterisk', 'plus', 'comma', 'hyphen', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'at', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'bracketleft', 'backslash', 'bracketright', 'asciicircum', 'underscore', 'grave', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', 'braceleft', 'bar', 'braceright', 'asciitilde', 'bullet', 'Euro', 'bullet', 'quotesinglbase', 'florin', 'quotedblbase', 'ellipsis', 'dagger', 'daggerdbl', 'circumflex', 'perthousand', 'Scaron', 'guilsinglleft', 'OE', 'bullet', 'Zcaron', 'bullet', 'bullet', 'quoteleft', 'quoteright', 'quotedblleft', 'quotedblright', 'bullet', 'endash', 'emdash', 'tilde', 'trademark', 'scaron', 'guilsinglright', 'oe', 'bullet', 'zcaron', 'Ydieresis', 'space', 'exclamdown', 'cent', 'sterling', 'currency', 'yen', 'brokenbar', 'section', 'dieresis', 'copyright', 'ordfeminine', 'guillemotleft', 'logicalnot', 'hyphen', 'registered', 'macron', 'degree', 'plusminus', 'twosuperior', 'threesuperior', 'acute', 'mu', 'paragraph', 'periodcentered', 'cedilla', 'onesuperior', 'ordmasculine', 'guillemotright', 'onequarter', 'onehalf', 'threequarters', 'questiondown', 'Agrave', 'Aacute', 'Acircumflex', 'Atilde', 'Adieresis', 'Aring', 'AE', 'Ccedilla', 'Egrave', 'Eacute', 'Ecircumflex', 'Edieresis', 'Igrave', 'Iacute', 'Icircumflex', 'Idieresis', 'Eth', 'Ntilde', 'Ograve', 'Oacute', 'Ocircumflex', 'Otilde', 'Odieresis', 'multiply', 'Oslash', 'Ugrave', 'Uacute', 'Ucircumflex', 'Udieresis', 'Yacute', 'Thorn', 'germandbls', 'agrave', 'aacute', 'acircumflex', 'atilde', 'adieresis', 'aring', 'ae', 'ccedilla', 'egrave', 'eacute', 'ecircumflex', 'edieresis', 'igrave', 'iacute', 'icircumflex', 'idieresis', 'eth', 'ntilde', 'ograve', 'oacute', 'ocircumflex', 'otilde', 'odieresis', 'divide', 'oslash', 'ugrave', 'uacute', 'ucircumflex', 'udieresis', 'yacute', 'thorn', 'ydieresis'];
+exports.WinAnsiEncoding = WinAnsiEncoding;
+var SymbolSetEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'exclam', 'universal', 'numbersign', 'existential', 'percent', 'ampersand', 'suchthat', 'parenleft', 'parenright', 'asteriskmath', 'plus', 'comma', 'minus', 'period', 'slash', 'zero', 'one', 'two', 'three', 'four', 'five', 'six', 'seven', 'eight', 'nine', 'colon', 'semicolon', 'less', 'equal', 'greater', 'question', 'congruent', 'Alpha', 'Beta', 'Chi', 'Delta', 'Epsilon', 'Phi', 'Gamma', 'Eta', 'Iota', 'theta1', 'Kappa', 'Lambda', 'Mu', 'Nu', 'Omicron', 'Pi', 'Theta', 'Rho', 'Sigma', 'Tau', 'Upsilon', 'sigma1', 'Omega', 'Xi', 'Psi', 'Zeta', 'bracketleft', 'therefore', 'bracketright', 'perpendicular', 'underscore', 'radicalex', 'alpha', 'beta', 'chi', 'delta', 'epsilon', 'phi', 'gamma', 'eta', 'iota', 'phi1', 'kappa', 'lambda', 'mu', 'nu', 'omicron', 'pi', 'theta', 'rho', 'sigma', 'tau', 'upsilon', 'omega1', 'omega', 'xi', 'psi', 'zeta', 'braceleft', 'bar', 'braceright', 'similar', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'Euro', 'Upsilon1', 'minute', 'lessequal', 'fraction', 'infinity', 'florin', 'club', 'diamond', 'heart', 'spade', 'arrowboth', 'arrowleft', 'arrowup', 'arrowright', 'arrowdown', 'degree', 'plusminus', 'second', 'greaterequal', 'multiply', 'proportional', 'partialdiff', 'bullet', 'divide', 'notequal', 'equivalence', 'approxequal', 'ellipsis', 'arrowvertex', 'arrowhorizex', 'carriagereturn', 'aleph', 'Ifraktur', 'Rfraktur', 'weierstrass', 'circlemultiply', 'circleplus', 'emptyset', 'intersection', 'union', 'propersuperset', 'reflexsuperset', 'notsubset', 'propersubset', 'reflexsubset', 'element', 'notelement', 'angle', 'gradient', 'registerserif', 'copyrightserif', 'trademarkserif', 'product', 'radical', 'dotmath', 'logicalnot', 'logicaland', 'logicalor', 'arrowdblboth', 'arrowdblleft', 'arrowdblup', 'arrowdblright', 'arrowdbldown', 'lozenge', 'angleleft', 'registersans', 'copyrightsans', 'trademarksans', 'summation', 'parenlefttp', 'parenleftex', 'parenleftbt', 'bracketlefttp', 'bracketleftex', 'bracketleftbt', 'bracelefttp', 'braceleftmid', 'braceleftbt', 'braceex', '', 'angleright', 'integral', 'integraltp', 'integralex', 'integralbt', 'parenrighttp', 'parenrightex', 'parenrightbt', 'bracketrighttp', 'bracketrightex', 'bracketrightbt', 'bracerighttp', 'bracerightmid', 'bracerightbt', ''];
+exports.SymbolSetEncoding = SymbolSetEncoding;
+var ZapfDingbatsEncoding = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'space', 'a1', 'a2', 'a202', 'a3', 'a4', 'a5', 'a119', 'a118', 'a117', 'a11', 'a12', 'a13', 'a14', 'a15', 'a16', 'a105', 'a17', 'a18', 'a19', 'a20', 'a21', 'a22', 'a23', 'a24', 'a25', 'a26', 'a27', 'a28', 'a6', 'a7', 'a8', 'a9', 'a10', 'a29', 'a30', 'a31', 'a32', 'a33', 'a34', 'a35', 'a36', 'a37', 'a38', 'a39', 'a40', 'a41', 'a42', 'a43', 'a44', 'a45', 'a46', 'a47', 'a48', 'a49', 'a50', 'a51', 'a52', 'a53', 'a54', 'a55', 'a56', 'a57', 'a58', 'a59', 'a60', 'a61', 'a62', 'a63', 'a64', 'a65', 'a66', 'a67', 'a68', 'a69', 'a70', 'a71', 'a72', 'a73', 'a74', 'a203', 'a75', 'a204', 'a76', 'a77', 'a78', 'a79', 'a81', 'a82', 'a83', 'a84', 'a97', 'a98', 'a99', 'a100', '', 'a89', 'a90', 'a93', 'a94', 'a91', 'a92', 'a205', 'a85', 'a206', 'a86', 'a87', 'a88', 'a95', 'a96', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', 'a101', 'a102', 'a103', 'a104', 'a106', 'a107', 'a108', 'a112', 'a111', 'a110', 'a109', 'a120', 'a121', 'a122', 'a123', 'a124', 'a125', 'a126', 'a127', 'a128', 'a129', 'a130', 'a131', 'a132', 'a133', 'a134', 'a135', 'a136', 'a137', 'a138', 'a139', 'a140', 'a141', 'a142', 'a143', 'a144', 'a145', 'a146', 'a147', 'a148', 'a149', 'a150', 'a151', 'a152', 'a153', 'a154', 'a155', 'a156', 'a157', 'a158', 'a159', 'a160', 'a161', 'a163', 'a164', 'a196', 'a165', 'a192', 'a166', 'a167', 'a168', 'a169', 'a170', 'a171', 'a172', 'a173', 'a162', 'a174', 'a175', 'a176', 'a177', 'a178', 'a179', 'a193', 'a180', 'a199', 'a181', 'a200', 'a182', '', 'a201', 'a183', 'a184', 'a197', 'a185', 'a194', 'a198', 'a186', 'a195', 'a187', 'a188', 'a189', 'a190', 'a191', ''];
+exports.ZapfDingbatsEncoding = ZapfDingbatsEncoding;
+
+function getEncoding(encodingName) {
+  switch (encodingName) {
+    case 'WinAnsiEncoding':
+      return WinAnsiEncoding;
+
+    case 'StandardEncoding':
+      return StandardEncoding;
+
+    case 'MacRomanEncoding':
+      return MacRomanEncoding;
+
+    case 'SymbolSetEncoding':
+      return SymbolSetEncoding;
+
+    case 'ZapfDingbatsEncoding':
+      return ZapfDingbatsEncoding;
+
+    case 'ExpertEncoding':
+      return ExpertEncoding;
+
+    case 'MacExpertEncoding':
+      return MacExpertEncoding;
+
+    default:
+      return null;
+  }
+}
+
+/***/ }),
+/* 178 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+var getLookupTableFactory = __w_pdfjs_require__(154).getLookupTableFactory;
+var getGlyphsUnicode = getLookupTableFactory(function (t) {
+ t['A'] = 0x0041;
+ t['AE'] = 0x00C6;
+ t['AEacute'] = 0x01FC;
+ t['AEmacron'] = 0x01E2;
+ t['AEsmall'] = 0xF7E6;
+ t['Aacute'] = 0x00C1;
+ t['Aacutesmall'] = 0xF7E1;
+ t['Abreve'] = 0x0102;
+ t['Abreveacute'] = 0x1EAE;
+ t['Abrevecyrillic'] = 0x04D0;
+ t['Abrevedotbelow'] = 0x1EB6;
+ t['Abrevegrave'] = 0x1EB0;
+ t['Abrevehookabove'] = 0x1EB2;
+ t['Abrevetilde'] = 0x1EB4;
+ t['Acaron'] = 0x01CD;
+ t['Acircle'] = 0x24B6;
+ t['Acircumflex'] = 0x00C2;
+ t['Acircumflexacute'] = 0x1EA4;
+ t['Acircumflexdotbelow'] = 0x1EAC;
+ t['Acircumflexgrave'] = 0x1EA6;
+ t['Acircumflexhookabove'] = 0x1EA8;
+ t['Acircumflexsmall'] = 0xF7E2;
+ t['Acircumflextilde'] = 0x1EAA;
+ t['Acute'] = 0xF6C9;
+ t['Acutesmall'] = 0xF7B4;
+ t['Acyrillic'] = 0x0410;
+ t['Adblgrave'] = 0x0200;
+ t['Adieresis'] = 0x00C4;
+ t['Adieresiscyrillic'] = 0x04D2;
+ t['Adieresismacron'] = 0x01DE;
+ t['Adieresissmall'] = 0xF7E4;
+ t['Adotbelow'] = 0x1EA0;
+ t['Adotmacron'] = 0x01E0;
+ t['Agrave'] = 0x00C0;
+ t['Agravesmall'] = 0xF7E0;
+ t['Ahookabove'] = 0x1EA2;
+ t['Aiecyrillic'] = 0x04D4;
+ t['Ainvertedbreve'] = 0x0202;
+ t['Alpha'] = 0x0391;
+ t['Alphatonos'] = 0x0386;
+ t['Amacron'] = 0x0100;
+ t['Amonospace'] = 0xFF21;
+ t['Aogonek'] = 0x0104;
+ t['Aring'] = 0x00C5;
+ t['Aringacute'] = 0x01FA;
+ t['Aringbelow'] = 0x1E00;
+ t['Aringsmall'] = 0xF7E5;
+ t['Asmall'] = 0xF761;
+ t['Atilde'] = 0x00C3;
+ t['Atildesmall'] = 0xF7E3;
+ t['Aybarmenian'] = 0x0531;
+ t['B'] = 0x0042;
+ t['Bcircle'] = 0x24B7;
+ t['Bdotaccent'] = 0x1E02;
+ t['Bdotbelow'] = 0x1E04;
+ t['Becyrillic'] = 0x0411;
+ t['Benarmenian'] = 0x0532;
+ t['Beta'] = 0x0392;
+ t['Bhook'] = 0x0181;
+ t['Blinebelow'] = 0x1E06;
+ t['Bmonospace'] = 0xFF22;
+ t['Brevesmall'] = 0xF6F4;
+ t['Bsmall'] = 0xF762;
+ t['Btopbar'] = 0x0182;
+ t['C'] = 0x0043;
+ t['Caarmenian'] = 0x053E;
+ t['Cacute'] = 0x0106;
+ t['Caron'] = 0xF6CA;
+ t['Caronsmall'] = 0xF6F5;
+ t['Ccaron'] = 0x010C;
+ t['Ccedilla'] = 0x00C7;
+ t['Ccedillaacute'] = 0x1E08;
+ t['Ccedillasmall'] = 0xF7E7;
+ t['Ccircle'] = 0x24B8;
+ t['Ccircumflex'] = 0x0108;
+ t['Cdot'] = 0x010A;
+ t['Cdotaccent'] = 0x010A;
+ t['Cedillasmall'] = 0xF7B8;
+ t['Chaarmenian'] = 0x0549;
+ t['Cheabkhasiancyrillic'] = 0x04BC;
+ t['Checyrillic'] = 0x0427;
+ t['Chedescenderabkhasiancyrillic'] = 0x04BE;
+ t['Chedescendercyrillic'] = 0x04B6;
+ t['Chedieresiscyrillic'] = 0x04F4;
+ t['Cheharmenian'] = 0x0543;
+ t['Chekhakassiancyrillic'] = 0x04CB;
+ t['Cheverticalstrokecyrillic'] = 0x04B8;
+ t['Chi'] = 0x03A7;
+ t['Chook'] = 0x0187;
+ t['Circumflexsmall'] = 0xF6F6;
+ t['Cmonospace'] = 0xFF23;
+ t['Coarmenian'] = 0x0551;
+ t['Csmall'] = 0xF763;
+ t['D'] = 0x0044;
+ t['DZ'] = 0x01F1;
+ t['DZcaron'] = 0x01C4;
+ t['Daarmenian'] = 0x0534;
+ t['Dafrican'] = 0x0189;
+ t['Dcaron'] = 0x010E;
+ t['Dcedilla'] = 0x1E10;
+ t['Dcircle'] = 0x24B9;
+ t['Dcircumflexbelow'] = 0x1E12;
+ t['Dcroat'] = 0x0110;
+ t['Ddotaccent'] = 0x1E0A;
+ t['Ddotbelow'] = 0x1E0C;
+ t['Decyrillic'] = 0x0414;
+ t['Deicoptic'] = 0x03EE;
+ t['Delta'] = 0x2206;
+ t['Deltagreek'] = 0x0394;
+ t['Dhook'] = 0x018A;
+ t['Dieresis'] = 0xF6CB;
+ t['DieresisAcute'] = 0xF6CC;
+ t['DieresisGrave'] = 0xF6CD;
+ t['Dieresissmall'] = 0xF7A8;
+ t['Digammagreek'] = 0x03DC;
+ t['Djecyrillic'] = 0x0402;
+ t['Dlinebelow'] = 0x1E0E;
+ t['Dmonospace'] = 0xFF24;
+ t['Dotaccentsmall'] = 0xF6F7;
+ t['Dslash'] = 0x0110;
+ t['Dsmall'] = 0xF764;
+ t['Dtopbar'] = 0x018B;
+ t['Dz'] = 0x01F2;
+ t['Dzcaron'] = 0x01C5;
+ t['Dzeabkhasiancyrillic'] = 0x04E0;
+ t['Dzecyrillic'] = 0x0405;
+ t['Dzhecyrillic'] = 0x040F;
+ t['E'] = 0x0045;
+ t['Eacute'] = 0x00C9;
+ t['Eacutesmall'] = 0xF7E9;
+ t['Ebreve'] = 0x0114;
+ t['Ecaron'] = 0x011A;
+ t['Ecedillabreve'] = 0x1E1C;
+ t['Echarmenian'] = 0x0535;
+ t['Ecircle'] = 0x24BA;
+ t['Ecircumflex'] = 0x00CA;
+ t['Ecircumflexacute'] = 0x1EBE;
+ t['Ecircumflexbelow'] = 0x1E18;
+ t['Ecircumflexdotbelow'] = 0x1EC6;
+ t['Ecircumflexgrave'] = 0x1EC0;
+ t['Ecircumflexhookabove'] = 0x1EC2;
+ t['Ecircumflexsmall'] = 0xF7EA;
+ t['Ecircumflextilde'] = 0x1EC4;
+ t['Ecyrillic'] = 0x0404;
+ t['Edblgrave'] = 0x0204;
+ t['Edieresis'] = 0x00CB;
+ t['Edieresissmall'] = 0xF7EB;
+ t['Edot'] = 0x0116;
+ t['Edotaccent'] = 0x0116;
+ t['Edotbelow'] = 0x1EB8;
+ t['Efcyrillic'] = 0x0424;
+ t['Egrave'] = 0x00C8;
+ t['Egravesmall'] = 0xF7E8;
+ t['Eharmenian'] = 0x0537;
+ t['Ehookabove'] = 0x1EBA;
+ t['Eightroman'] = 0x2167;
+ t['Einvertedbreve'] = 0x0206;
+ t['Eiotifiedcyrillic'] = 0x0464;
+ t['Elcyrillic'] = 0x041B;
+ t['Elevenroman'] = 0x216A;
+ t['Emacron'] = 0x0112;
+ t['Emacronacute'] = 0x1E16;
+ t['Emacrongrave'] = 0x1E14;
+ t['Emcyrillic'] = 0x041C;
+ t['Emonospace'] = 0xFF25;
+ t['Encyrillic'] = 0x041D;
+ t['Endescendercyrillic'] = 0x04A2;
+ t['Eng'] = 0x014A;
+ t['Enghecyrillic'] = 0x04A4;
+ t['Enhookcyrillic'] = 0x04C7;
+ t['Eogonek'] = 0x0118;
+ t['Eopen'] = 0x0190;
+ t['Epsilon'] = 0x0395;
+ t['Epsilontonos'] = 0x0388;
+ t['Ercyrillic'] = 0x0420;
+ t['Ereversed'] = 0x018E;
+ t['Ereversedcyrillic'] = 0x042D;
+ t['Escyrillic'] = 0x0421;
+ t['Esdescendercyrillic'] = 0x04AA;
+ t['Esh'] = 0x01A9;
+ t['Esmall'] = 0xF765;
+ t['Eta'] = 0x0397;
+ t['Etarmenian'] = 0x0538;
+ t['Etatonos'] = 0x0389;
+ t['Eth'] = 0x00D0;
+ t['Ethsmall'] = 0xF7F0;
+ t['Etilde'] = 0x1EBC;
+ t['Etildebelow'] = 0x1E1A;
+ t['Euro'] = 0x20AC;
+ t['Ezh'] = 0x01B7;
+ t['Ezhcaron'] = 0x01EE;
+ t['Ezhreversed'] = 0x01B8;
+ t['F'] = 0x0046;
+ t['Fcircle'] = 0x24BB;
+ t['Fdotaccent'] = 0x1E1E;
+ t['Feharmenian'] = 0x0556;
+ t['Feicoptic'] = 0x03E4;
+ t['Fhook'] = 0x0191;
+ t['Fitacyrillic'] = 0x0472;
+ t['Fiveroman'] = 0x2164;
+ t['Fmonospace'] = 0xFF26;
+ t['Fourroman'] = 0x2163;
+ t['Fsmall'] = 0xF766;
+ t['G'] = 0x0047;
+ t['GBsquare'] = 0x3387;
+ t['Gacute'] = 0x01F4;
+ t['Gamma'] = 0x0393;
+ t['Gammaafrican'] = 0x0194;
+ t['Gangiacoptic'] = 0x03EA;
+ t['Gbreve'] = 0x011E;
+ t['Gcaron'] = 0x01E6;
+ t['Gcedilla'] = 0x0122;
+ t['Gcircle'] = 0x24BC;
+ t['Gcircumflex'] = 0x011C;
+ t['Gcommaaccent'] = 0x0122;
+ t['Gdot'] = 0x0120;
+ t['Gdotaccent'] = 0x0120;
+ t['Gecyrillic'] = 0x0413;
+ t['Ghadarmenian'] = 0x0542;
+ t['Ghemiddlehookcyrillic'] = 0x0494;
+ t['Ghestrokecyrillic'] = 0x0492;
+ t['Gheupturncyrillic'] = 0x0490;
+ t['Ghook'] = 0x0193;
+ t['Gimarmenian'] = 0x0533;
+ t['Gjecyrillic'] = 0x0403;
+ t['Gmacron'] = 0x1E20;
+ t['Gmonospace'] = 0xFF27;
+ t['Grave'] = 0xF6CE;
+ t['Gravesmall'] = 0xF760;
+ t['Gsmall'] = 0xF767;
+ t['Gsmallhook'] = 0x029B;
+ t['Gstroke'] = 0x01E4;
+ t['H'] = 0x0048;
+ t['H18533'] = 0x25CF;
+ t['H18543'] = 0x25AA;
+ t['H18551'] = 0x25AB;
+ t['H22073'] = 0x25A1;
+ t['HPsquare'] = 0x33CB;
+ t['Haabkhasiancyrillic'] = 0x04A8;
+ t['Hadescendercyrillic'] = 0x04B2;
+ t['Hardsigncyrillic'] = 0x042A;
+ t['Hbar'] = 0x0126;
+ t['Hbrevebelow'] = 0x1E2A;
+ t['Hcedilla'] = 0x1E28;
+ t['Hcircle'] = 0x24BD;
+ t['Hcircumflex'] = 0x0124;
+ t['Hdieresis'] = 0x1E26;
+ t['Hdotaccent'] = 0x1E22;
+ t['Hdotbelow'] = 0x1E24;
+ t['Hmonospace'] = 0xFF28;
+ t['Hoarmenian'] = 0x0540;
+ t['Horicoptic'] = 0x03E8;
+ t['Hsmall'] = 0xF768;
+ t['Hungarumlaut'] = 0xF6CF;
+ t['Hungarumlautsmall'] = 0xF6F8;
+ t['Hzsquare'] = 0x3390;
+ t['I'] = 0x0049;
+ t['IAcyrillic'] = 0x042F;
+ t['IJ'] = 0x0132;
+ t['IUcyrillic'] = 0x042E;
+ t['Iacute'] = 0x00CD;
+ t['Iacutesmall'] = 0xF7ED;
+ t['Ibreve'] = 0x012C;
+ t['Icaron'] = 0x01CF;
+ t['Icircle'] = 0x24BE;
+ t['Icircumflex'] = 0x00CE;
+ t['Icircumflexsmall'] = 0xF7EE;
+ t['Icyrillic'] = 0x0406;
+ t['Idblgrave'] = 0x0208;
+ t['Idieresis'] = 0x00CF;
+ t['Idieresisacute'] = 0x1E2E;
+ t['Idieresiscyrillic'] = 0x04E4;
+ t['Idieresissmall'] = 0xF7EF;
+ t['Idot'] = 0x0130;
+ t['Idotaccent'] = 0x0130;
+ t['Idotbelow'] = 0x1ECA;
+ t['Iebrevecyrillic'] = 0x04D6;
+ t['Iecyrillic'] = 0x0415;
+ t['Ifraktur'] = 0x2111;
+ t['Igrave'] = 0x00CC;
+ t['Igravesmall'] = 0xF7EC;
+ t['Ihookabove'] = 0x1EC8;
+ t['Iicyrillic'] = 0x0418;
+ t['Iinvertedbreve'] = 0x020A;
+ t['Iishortcyrillic'] = 0x0419;
+ t['Imacron'] = 0x012A;
+ t['Imacroncyrillic'] = 0x04E2;
+ t['Imonospace'] = 0xFF29;
+ t['Iniarmenian'] = 0x053B;
+ t['Iocyrillic'] = 0x0401;
+ t['Iogonek'] = 0x012E;
+ t['Iota'] = 0x0399;
+ t['Iotaafrican'] = 0x0196;
+ t['Iotadieresis'] = 0x03AA;
+ t['Iotatonos'] = 0x038A;
+ t['Ismall'] = 0xF769;
+ t['Istroke'] = 0x0197;
+ t['Itilde'] = 0x0128;
+ t['Itildebelow'] = 0x1E2C;
+ t['Izhitsacyrillic'] = 0x0474;
+ t['Izhitsadblgravecyrillic'] = 0x0476;
+ t['J'] = 0x004A;
+ t['Jaarmenian'] = 0x0541;
+ t['Jcircle'] = 0x24BF;
+ t['Jcircumflex'] = 0x0134;
+ t['Jecyrillic'] = 0x0408;
+ t['Jheharmenian'] = 0x054B;
+ t['Jmonospace'] = 0xFF2A;
+ t['Jsmall'] = 0xF76A;
+ t['K'] = 0x004B;
+ t['KBsquare'] = 0x3385;
+ t['KKsquare'] = 0x33CD;
+ t['Kabashkircyrillic'] = 0x04A0;
+ t['Kacute'] = 0x1E30;
+ t['Kacyrillic'] = 0x041A;
+ t['Kadescendercyrillic'] = 0x049A;
+ t['Kahookcyrillic'] = 0x04C3;
+ t['Kappa'] = 0x039A;
+ t['Kastrokecyrillic'] = 0x049E;
+ t['Kaverticalstrokecyrillic'] = 0x049C;
+ t['Kcaron'] = 0x01E8;
+ t['Kcedilla'] = 0x0136;
+ t['Kcircle'] = 0x24C0;
+ t['Kcommaaccent'] = 0x0136;
+ t['Kdotbelow'] = 0x1E32;
+ t['Keharmenian'] = 0x0554;
+ t['Kenarmenian'] = 0x053F;
+ t['Khacyrillic'] = 0x0425;
+ t['Kheicoptic'] = 0x03E6;
+ t['Khook'] = 0x0198;
+ t['Kjecyrillic'] = 0x040C;
+ t['Klinebelow'] = 0x1E34;
+ t['Kmonospace'] = 0xFF2B;
+ t['Koppacyrillic'] = 0x0480;
+ t['Koppagreek'] = 0x03DE;
+ t['Ksicyrillic'] = 0x046E;
+ t['Ksmall'] = 0xF76B;
+ t['L'] = 0x004C;
+ t['LJ'] = 0x01C7;
+ t['LL'] = 0xF6BF;
+ t['Lacute'] = 0x0139;
+ t['Lambda'] = 0x039B;
+ t['Lcaron'] = 0x013D;
+ t['Lcedilla'] = 0x013B;
+ t['Lcircle'] = 0x24C1;
+ t['Lcircumflexbelow'] = 0x1E3C;
+ t['Lcommaaccent'] = 0x013B;
+ t['Ldot'] = 0x013F;
+ t['Ldotaccent'] = 0x013F;
+ t['Ldotbelow'] = 0x1E36;
+ t['Ldotbelowmacron'] = 0x1E38;
+ t['Liwnarmenian'] = 0x053C;
+ t['Lj'] = 0x01C8;
+ t['Ljecyrillic'] = 0x0409;
+ t['Llinebelow'] = 0x1E3A;
+ t['Lmonospace'] = 0xFF2C;
+ t['Lslash'] = 0x0141;
+ t['Lslashsmall'] = 0xF6F9;
+ t['Lsmall'] = 0xF76C;
+ t['M'] = 0x004D;
+ t['MBsquare'] = 0x3386;
+ t['Macron'] = 0xF6D0;
+ t['Macronsmall'] = 0xF7AF;
+ t['Macute'] = 0x1E3E;
+ t['Mcircle'] = 0x24C2;
+ t['Mdotaccent'] = 0x1E40;
+ t['Mdotbelow'] = 0x1E42;
+ t['Menarmenian'] = 0x0544;
+ t['Mmonospace'] = 0xFF2D;
+ t['Msmall'] = 0xF76D;
+ t['Mturned'] = 0x019C;
+ t['Mu'] = 0x039C;
+ t['N'] = 0x004E;
+ t['NJ'] = 0x01CA;
+ t['Nacute'] = 0x0143;
+ t['Ncaron'] = 0x0147;
+ t['Ncedilla'] = 0x0145;
+ t['Ncircle'] = 0x24C3;
+ t['Ncircumflexbelow'] = 0x1E4A;
+ t['Ncommaaccent'] = 0x0145;
+ t['Ndotaccent'] = 0x1E44;
+ t['Ndotbelow'] = 0x1E46;
+ t['Nhookleft'] = 0x019D;
+ t['Nineroman'] = 0x2168;
+ t['Nj'] = 0x01CB;
+ t['Njecyrillic'] = 0x040A;
+ t['Nlinebelow'] = 0x1E48;
+ t['Nmonospace'] = 0xFF2E;
+ t['Nowarmenian'] = 0x0546;
+ t['Nsmall'] = 0xF76E;
+ t['Ntilde'] = 0x00D1;
+ t['Ntildesmall'] = 0xF7F1;
+ t['Nu'] = 0x039D;
+ t['O'] = 0x004F;
+ t['OE'] = 0x0152;
+ t['OEsmall'] = 0xF6FA;
+ t['Oacute'] = 0x00D3;
+ t['Oacutesmall'] = 0xF7F3;
+ t['Obarredcyrillic'] = 0x04E8;
+ t['Obarreddieresiscyrillic'] = 0x04EA;
+ t['Obreve'] = 0x014E;
+ t['Ocaron'] = 0x01D1;
+ t['Ocenteredtilde'] = 0x019F;
+ t['Ocircle'] = 0x24C4;
+ t['Ocircumflex'] = 0x00D4;
+ t['Ocircumflexacute'] = 0x1ED0;
+ t['Ocircumflexdotbelow'] = 0x1ED8;
+ t['Ocircumflexgrave'] = 0x1ED2;
+ t['Ocircumflexhookabove'] = 0x1ED4;
+ t['Ocircumflexsmall'] = 0xF7F4;
+ t['Ocircumflextilde'] = 0x1ED6;
+ t['Ocyrillic'] = 0x041E;
+ t['Odblacute'] = 0x0150;
+ t['Odblgrave'] = 0x020C;
+ t['Odieresis'] = 0x00D6;
+ t['Odieresiscyrillic'] = 0x04E6;
+ t['Odieresissmall'] = 0xF7F6;
+ t['Odotbelow'] = 0x1ECC;
+ t['Ogoneksmall'] = 0xF6FB;
+ t['Ograve'] = 0x00D2;
+ t['Ogravesmall'] = 0xF7F2;
+ t['Oharmenian'] = 0x0555;
+ t['Ohm'] = 0x2126;
+ t['Ohookabove'] = 0x1ECE;
+ t['Ohorn'] = 0x01A0;
+ t['Ohornacute'] = 0x1EDA;
+ t['Ohorndotbelow'] = 0x1EE2;
+ t['Ohorngrave'] = 0x1EDC;
+ t['Ohornhookabove'] = 0x1EDE;
+ t['Ohorntilde'] = 0x1EE0;
+ t['Ohungarumlaut'] = 0x0150;
+ t['Oi'] = 0x01A2;
+ t['Oinvertedbreve'] = 0x020E;
+ t['Omacron'] = 0x014C;
+ t['Omacronacute'] = 0x1E52;
+ t['Omacrongrave'] = 0x1E50;
+ t['Omega'] = 0x2126;
+ t['Omegacyrillic'] = 0x0460;
+ t['Omegagreek'] = 0x03A9;
+ t['Omegaroundcyrillic'] = 0x047A;
+ t['Omegatitlocyrillic'] = 0x047C;
+ t['Omegatonos'] = 0x038F;
+ t['Omicron'] = 0x039F;
+ t['Omicrontonos'] = 0x038C;
+ t['Omonospace'] = 0xFF2F;
+ t['Oneroman'] = 0x2160;
+ t['Oogonek'] = 0x01EA;
+ t['Oogonekmacron'] = 0x01EC;
+ t['Oopen'] = 0x0186;
+ t['Oslash'] = 0x00D8;
+ t['Oslashacute'] = 0x01FE;
+ t['Oslashsmall'] = 0xF7F8;
+ t['Osmall'] = 0xF76F;
+ t['Ostrokeacute'] = 0x01FE;
+ t['Otcyrillic'] = 0x047E;
+ t['Otilde'] = 0x00D5;
+ t['Otildeacute'] = 0x1E4C;
+ t['Otildedieresis'] = 0x1E4E;
+ t['Otildesmall'] = 0xF7F5;
+ t['P'] = 0x0050;
+ t['Pacute'] = 0x1E54;
+ t['Pcircle'] = 0x24C5;
+ t['Pdotaccent'] = 0x1E56;
+ t['Pecyrillic'] = 0x041F;
+ t['Peharmenian'] = 0x054A;
+ t['Pemiddlehookcyrillic'] = 0x04A6;
+ t['Phi'] = 0x03A6;
+ t['Phook'] = 0x01A4;
+ t['Pi'] = 0x03A0;
+ t['Piwrarmenian'] = 0x0553;
+ t['Pmonospace'] = 0xFF30;
+ t['Psi'] = 0x03A8;
+ t['Psicyrillic'] = 0x0470;
+ t['Psmall'] = 0xF770;
+ t['Q'] = 0x0051;
+ t['Qcircle'] = 0x24C6;
+ t['Qmonospace'] = 0xFF31;
+ t['Qsmall'] = 0xF771;
+ t['R'] = 0x0052;
+ t['Raarmenian'] = 0x054C;
+ t['Racute'] = 0x0154;
+ t['Rcaron'] = 0x0158;
+ t['Rcedilla'] = 0x0156;
+ t['Rcircle'] = 0x24C7;
+ t['Rcommaaccent'] = 0x0156;
+ t['Rdblgrave'] = 0x0210;
+ t['Rdotaccent'] = 0x1E58;
+ t['Rdotbelow'] = 0x1E5A;
+ t['Rdotbelowmacron'] = 0x1E5C;
+ t['Reharmenian'] = 0x0550;
+ t['Rfraktur'] = 0x211C;
+ t['Rho'] = 0x03A1;
+ t['Ringsmall'] = 0xF6FC;
+ t['Rinvertedbreve'] = 0x0212;
+ t['Rlinebelow'] = 0x1E5E;
+ t['Rmonospace'] = 0xFF32;
+ t['Rsmall'] = 0xF772;
+ t['Rsmallinverted'] = 0x0281;
+ t['Rsmallinvertedsuperior'] = 0x02B6;
+ t['S'] = 0x0053;
+ t['SF010000'] = 0x250C;
+ t['SF020000'] = 0x2514;
+ t['SF030000'] = 0x2510;
+ t['SF040000'] = 0x2518;
+ t['SF050000'] = 0x253C;
+ t['SF060000'] = 0x252C;
+ t['SF070000'] = 0x2534;
+ t['SF080000'] = 0x251C;
+ t['SF090000'] = 0x2524;
+ t['SF100000'] = 0x2500;
+ t['SF110000'] = 0x2502;
+ t['SF190000'] = 0x2561;
+ t['SF200000'] = 0x2562;
+ t['SF210000'] = 0x2556;
+ t['SF220000'] = 0x2555;
+ t['SF230000'] = 0x2563;
+ t['SF240000'] = 0x2551;
+ t['SF250000'] = 0x2557;
+ t['SF260000'] = 0x255D;
+ t['SF270000'] = 0x255C;
+ t['SF280000'] = 0x255B;
+ t['SF360000'] = 0x255E;
+ t['SF370000'] = 0x255F;
+ t['SF380000'] = 0x255A;
+ t['SF390000'] = 0x2554;
+ t['SF400000'] = 0x2569;
+ t['SF410000'] = 0x2566;
+ t['SF420000'] = 0x2560;
+ t['SF430000'] = 0x2550;
+ t['SF440000'] = 0x256C;
+ t['SF450000'] = 0x2567;
+ t['SF460000'] = 0x2568;
+ t['SF470000'] = 0x2564;
+ t['SF480000'] = 0x2565;
+ t['SF490000'] = 0x2559;
+ t['SF500000'] = 0x2558;
+ t['SF510000'] = 0x2552;
+ t['SF520000'] = 0x2553;
+ t['SF530000'] = 0x256B;
+ t['SF540000'] = 0x256A;
+ t['Sacute'] = 0x015A;
+ t['Sacutedotaccent'] = 0x1E64;
+ t['Sampigreek'] = 0x03E0;
+ t['Scaron'] = 0x0160;
+ t['Scarondotaccent'] = 0x1E66;
+ t['Scaronsmall'] = 0xF6FD;
+ t['Scedilla'] = 0x015E;
+ t['Schwa'] = 0x018F;
+ t['Schwacyrillic'] = 0x04D8;
+ t['Schwadieresiscyrillic'] = 0x04DA;
+ t['Scircle'] = 0x24C8;
+ t['Scircumflex'] = 0x015C;
+ t['Scommaaccent'] = 0x0218;
+ t['Sdotaccent'] = 0x1E60;
+ t['Sdotbelow'] = 0x1E62;
+ t['Sdotbelowdotaccent'] = 0x1E68;
+ t['Seharmenian'] = 0x054D;
+ t['Sevenroman'] = 0x2166;
+ t['Shaarmenian'] = 0x0547;
+ t['Shacyrillic'] = 0x0428;
+ t['Shchacyrillic'] = 0x0429;
+ t['Sheicoptic'] = 0x03E2;
+ t['Shhacyrillic'] = 0x04BA;
+ t['Shimacoptic'] = 0x03EC;
+ t['Sigma'] = 0x03A3;
+ t['Sixroman'] = 0x2165;
+ t['Smonospace'] = 0xFF33;
+ t['Softsigncyrillic'] = 0x042C;
+ t['Ssmall'] = 0xF773;
+ t['Stigmagreek'] = 0x03DA;
+ t['T'] = 0x0054;
+ t['Tau'] = 0x03A4;
+ t['Tbar'] = 0x0166;
+ t['Tcaron'] = 0x0164;
+ t['Tcedilla'] = 0x0162;
+ t['Tcircle'] = 0x24C9;
+ t['Tcircumflexbelow'] = 0x1E70;
+ t['Tcommaaccent'] = 0x0162;
+ t['Tdotaccent'] = 0x1E6A;
+ t['Tdotbelow'] = 0x1E6C;
+ t['Tecyrillic'] = 0x0422;
+ t['Tedescendercyrillic'] = 0x04AC;
+ t['Tenroman'] = 0x2169;
+ t['Tetsecyrillic'] = 0x04B4;
+ t['Theta'] = 0x0398;
+ t['Thook'] = 0x01AC;
+ t['Thorn'] = 0x00DE;
+ t['Thornsmall'] = 0xF7FE;
+ t['Threeroman'] = 0x2162;
+ t['Tildesmall'] = 0xF6FE;
+ t['Tiwnarmenian'] = 0x054F;
+ t['Tlinebelow'] = 0x1E6E;
+ t['Tmonospace'] = 0xFF34;
+ t['Toarmenian'] = 0x0539;
+ t['Tonefive'] = 0x01BC;
+ t['Tonesix'] = 0x0184;
+ t['Tonetwo'] = 0x01A7;
+ t['Tretroflexhook'] = 0x01AE;
+ t['Tsecyrillic'] = 0x0426;
+ t['Tshecyrillic'] = 0x040B;
+ t['Tsmall'] = 0xF774;
+ t['Twelveroman'] = 0x216B;
+ t['Tworoman'] = 0x2161;
+ t['U'] = 0x0055;
+ t['Uacute'] = 0x00DA;
+ t['Uacutesmall'] = 0xF7FA;
+ t['Ubreve'] = 0x016C;
+ t['Ucaron'] = 0x01D3;
+ t['Ucircle'] = 0x24CA;
+ t['Ucircumflex'] = 0x00DB;
+ t['Ucircumflexbelow'] = 0x1E76;
+ t['Ucircumflexsmall'] = 0xF7FB;
+ t['Ucyrillic'] = 0x0423;
+ t['Udblacute'] = 0x0170;
+ t['Udblgrave'] = 0x0214;
+ t['Udieresis'] = 0x00DC;
+ t['Udieresisacute'] = 0x01D7;
+ t['Udieresisbelow'] = 0x1E72;
+ t['Udieresiscaron'] = 0x01D9;
+ t['Udieresiscyrillic'] = 0x04F0;
+ t['Udieresisgrave'] = 0x01DB;
+ t['Udieresismacron'] = 0x01D5;
+ t['Udieresissmall'] = 0xF7FC;
+ t['Udotbelow'] = 0x1EE4;
+ t['Ugrave'] = 0x00D9;
+ t['Ugravesmall'] = 0xF7F9;
+ t['Uhookabove'] = 0x1EE6;
+ t['Uhorn'] = 0x01AF;
+ t['Uhornacute'] = 0x1EE8;
+ t['Uhorndotbelow'] = 0x1EF0;
+ t['Uhorngrave'] = 0x1EEA;
+ t['Uhornhookabove'] = 0x1EEC;
+ t['Uhorntilde'] = 0x1EEE;
+ t['Uhungarumlaut'] = 0x0170;
+ t['Uhungarumlautcyrillic'] = 0x04F2;
+ t['Uinvertedbreve'] = 0x0216;
+ t['Ukcyrillic'] = 0x0478;
+ t['Umacron'] = 0x016A;
+ t['Umacroncyrillic'] = 0x04EE;
+ t['Umacrondieresis'] = 0x1E7A;
+ t['Umonospace'] = 0xFF35;
+ t['Uogonek'] = 0x0172;
+ t['Upsilon'] = 0x03A5;
+ t['Upsilon1'] = 0x03D2;
+ t['Upsilonacutehooksymbolgreek'] = 0x03D3;
+ t['Upsilonafrican'] = 0x01B1;
+ t['Upsilondieresis'] = 0x03AB;
+ t['Upsilondieresishooksymbolgreek'] = 0x03D4;
+ t['Upsilonhooksymbol'] = 0x03D2;
+ t['Upsilontonos'] = 0x038E;
+ t['Uring'] = 0x016E;
+ t['Ushortcyrillic'] = 0x040E;
+ t['Usmall'] = 0xF775;
+ t['Ustraightcyrillic'] = 0x04AE;
+ t['Ustraightstrokecyrillic'] = 0x04B0;
+ t['Utilde'] = 0x0168;
+ t['Utildeacute'] = 0x1E78;
+ t['Utildebelow'] = 0x1E74;
+ t['V'] = 0x0056;
+ t['Vcircle'] = 0x24CB;
+ t['Vdotbelow'] = 0x1E7E;
+ t['Vecyrillic'] = 0x0412;
+ t['Vewarmenian'] = 0x054E;
+ t['Vhook'] = 0x01B2;
+ t['Vmonospace'] = 0xFF36;
+ t['Voarmenian'] = 0x0548;
+ t['Vsmall'] = 0xF776;
+ t['Vtilde'] = 0x1E7C;
+ t['W'] = 0x0057;
+ t['Wacute'] = 0x1E82;
+ t['Wcircle'] = 0x24CC;
+ t['Wcircumflex'] = 0x0174;
+ t['Wdieresis'] = 0x1E84;
+ t['Wdotaccent'] = 0x1E86;
+ t['Wdotbelow'] = 0x1E88;
+ t['Wgrave'] = 0x1E80;
+ t['Wmonospace'] = 0xFF37;
+ t['Wsmall'] = 0xF777;
+ t['X'] = 0x0058;
+ t['Xcircle'] = 0x24CD;
+ t['Xdieresis'] = 0x1E8C;
+ t['Xdotaccent'] = 0x1E8A;
+ t['Xeharmenian'] = 0x053D;
+ t['Xi'] = 0x039E;
+ t['Xmonospace'] = 0xFF38;
+ t['Xsmall'] = 0xF778;
+ t['Y'] = 0x0059;
+ t['Yacute'] = 0x00DD;
+ t['Yacutesmall'] = 0xF7FD;
+ t['Yatcyrillic'] = 0x0462;
+ t['Ycircle'] = 0x24CE;
+ t['Ycircumflex'] = 0x0176;
+ t['Ydieresis'] = 0x0178;
+ t['Ydieresissmall'] = 0xF7FF;
+ t['Ydotaccent'] = 0x1E8E;
+ t['Ydotbelow'] = 0x1EF4;
+ t['Yericyrillic'] = 0x042B;
+ t['Yerudieresiscyrillic'] = 0x04F8;
+ t['Ygrave'] = 0x1EF2;
+ t['Yhook'] = 0x01B3;
+ t['Yhookabove'] = 0x1EF6;
+ t['Yiarmenian'] = 0x0545;
+ t['Yicyrillic'] = 0x0407;
+ t['Yiwnarmenian'] = 0x0552;
+ t['Ymonospace'] = 0xFF39;
+ t['Ysmall'] = 0xF779;
+ t['Ytilde'] = 0x1EF8;
+ t['Yusbigcyrillic'] = 0x046A;
+ t['Yusbigiotifiedcyrillic'] = 0x046C;
+ t['Yuslittlecyrillic'] = 0x0466;
+ t['Yuslittleiotifiedcyrillic'] = 0x0468;
+ t['Z'] = 0x005A;
+ t['Zaarmenian'] = 0x0536;
+ t['Zacute'] = 0x0179;
+ t['Zcaron'] = 0x017D;
+ t['Zcaronsmall'] = 0xF6FF;
+ t['Zcircle'] = 0x24CF;
+ t['Zcircumflex'] = 0x1E90;
+ t['Zdot'] = 0x017B;
+ t['Zdotaccent'] = 0x017B;
+ t['Zdotbelow'] = 0x1E92;
+ t['Zecyrillic'] = 0x0417;
+ t['Zedescendercyrillic'] = 0x0498;
+ t['Zedieresiscyrillic'] = 0x04DE;
+ t['Zeta'] = 0x0396;
+ t['Zhearmenian'] = 0x053A;
+ t['Zhebrevecyrillic'] = 0x04C1;
+ t['Zhecyrillic'] = 0x0416;
+ t['Zhedescendercyrillic'] = 0x0496;
+ t['Zhedieresiscyrillic'] = 0x04DC;
+ t['Zlinebelow'] = 0x1E94;
+ t['Zmonospace'] = 0xFF3A;
+ t['Zsmall'] = 0xF77A;
+ t['Zstroke'] = 0x01B5;
+ t['a'] = 0x0061;
+ t['aabengali'] = 0x0986;
+ t['aacute'] = 0x00E1;
+ t['aadeva'] = 0x0906;
+ t['aagujarati'] = 0x0A86;
+ t['aagurmukhi'] = 0x0A06;
+ t['aamatragurmukhi'] = 0x0A3E;
+ t['aarusquare'] = 0x3303;
+ t['aavowelsignbengali'] = 0x09BE;
+ t['aavowelsigndeva'] = 0x093E;
+ t['aavowelsigngujarati'] = 0x0ABE;
+ t['abbreviationmarkarmenian'] = 0x055F;
+ t['abbreviationsigndeva'] = 0x0970;
+ t['abengali'] = 0x0985;
+ t['abopomofo'] = 0x311A;
+ t['abreve'] = 0x0103;
+ t['abreveacute'] = 0x1EAF;
+ t['abrevecyrillic'] = 0x04D1;
+ t['abrevedotbelow'] = 0x1EB7;
+ t['abrevegrave'] = 0x1EB1;
+ t['abrevehookabove'] = 0x1EB3;
+ t['abrevetilde'] = 0x1EB5;
+ t['acaron'] = 0x01CE;
+ t['acircle'] = 0x24D0;
+ t['acircumflex'] = 0x00E2;
+ t['acircumflexacute'] = 0x1EA5;
+ t['acircumflexdotbelow'] = 0x1EAD;
+ t['acircumflexgrave'] = 0x1EA7;
+ t['acircumflexhookabove'] = 0x1EA9;
+ t['acircumflextilde'] = 0x1EAB;
+ t['acute'] = 0x00B4;
+ t['acutebelowcmb'] = 0x0317;
+ t['acutecmb'] = 0x0301;
+ t['acutecomb'] = 0x0301;
+ t['acutedeva'] = 0x0954;
+ t['acutelowmod'] = 0x02CF;
+ t['acutetonecmb'] = 0x0341;
+ t['acyrillic'] = 0x0430;
+ t['adblgrave'] = 0x0201;
+ t['addakgurmukhi'] = 0x0A71;
+ t['adeva'] = 0x0905;
+ t['adieresis'] = 0x00E4;
+ t['adieresiscyrillic'] = 0x04D3;
+ t['adieresismacron'] = 0x01DF;
+ t['adotbelow'] = 0x1EA1;
+ t['adotmacron'] = 0x01E1;
+ t['ae'] = 0x00E6;
+ t['aeacute'] = 0x01FD;
+ t['aekorean'] = 0x3150;
+ t['aemacron'] = 0x01E3;
+ t['afii00208'] = 0x2015;
+ t['afii08941'] = 0x20A4;
+ t['afii10017'] = 0x0410;
+ t['afii10018'] = 0x0411;
+ t['afii10019'] = 0x0412;
+ t['afii10020'] = 0x0413;
+ t['afii10021'] = 0x0414;
+ t['afii10022'] = 0x0415;
+ t['afii10023'] = 0x0401;
+ t['afii10024'] = 0x0416;
+ t['afii10025'] = 0x0417;
+ t['afii10026'] = 0x0418;
+ t['afii10027'] = 0x0419;
+ t['afii10028'] = 0x041A;
+ t['afii10029'] = 0x041B;
+ t['afii10030'] = 0x041C;
+ t['afii10031'] = 0x041D;
+ t['afii10032'] = 0x041E;
+ t['afii10033'] = 0x041F;
+ t['afii10034'] = 0x0420;
+ t['afii10035'] = 0x0421;
+ t['afii10036'] = 0x0422;
+ t['afii10037'] = 0x0423;
+ t['afii10038'] = 0x0424;
+ t['afii10039'] = 0x0425;
+ t['afii10040'] = 0x0426;
+ t['afii10041'] = 0x0427;
+ t['afii10042'] = 0x0428;
+ t['afii10043'] = 0x0429;
+ t['afii10044'] = 0x042A;
+ t['afii10045'] = 0x042B;
+ t['afii10046'] = 0x042C;
+ t['afii10047'] = 0x042D;
+ t['afii10048'] = 0x042E;
+ t['afii10049'] = 0x042F;
+ t['afii10050'] = 0x0490;
+ t['afii10051'] = 0x0402;
+ t['afii10052'] = 0x0403;
+ t['afii10053'] = 0x0404;
+ t['afii10054'] = 0x0405;
+ t['afii10055'] = 0x0406;
+ t['afii10056'] = 0x0407;
+ t['afii10057'] = 0x0408;
+ t['afii10058'] = 0x0409;
+ t['afii10059'] = 0x040A;
+ t['afii10060'] = 0x040B;
+ t['afii10061'] = 0x040C;
+ t['afii10062'] = 0x040E;
+ t['afii10063'] = 0xF6C4;
+ t['afii10064'] = 0xF6C5;
+ t['afii10065'] = 0x0430;
+ t['afii10066'] = 0x0431;
+ t['afii10067'] = 0x0432;
+ t['afii10068'] = 0x0433;
+ t['afii10069'] = 0x0434;
+ t['afii10070'] = 0x0435;
+ t['afii10071'] = 0x0451;
+ t['afii10072'] = 0x0436;
+ t['afii10073'] = 0x0437;
+ t['afii10074'] = 0x0438;
+ t['afii10075'] = 0x0439;
+ t['afii10076'] = 0x043A;
+ t['afii10077'] = 0x043B;
+ t['afii10078'] = 0x043C;
+ t['afii10079'] = 0x043D;
+ t['afii10080'] = 0x043E;
+ t['afii10081'] = 0x043F;
+ t['afii10082'] = 0x0440;
+ t['afii10083'] = 0x0441;
+ t['afii10084'] = 0x0442;
+ t['afii10085'] = 0x0443;
+ t['afii10086'] = 0x0444;
+ t['afii10087'] = 0x0445;
+ t['afii10088'] = 0x0446;
+ t['afii10089'] = 0x0447;
+ t['afii10090'] = 0x0448;
+ t['afii10091'] = 0x0449;
+ t['afii10092'] = 0x044A;
+ t['afii10093'] = 0x044B;
+ t['afii10094'] = 0x044C;
+ t['afii10095'] = 0x044D;
+ t['afii10096'] = 0x044E;
+ t['afii10097'] = 0x044F;
+ t['afii10098'] = 0x0491;
+ t['afii10099'] = 0x0452;
+ t['afii10100'] = 0x0453;
+ t['afii10101'] = 0x0454;
+ t['afii10102'] = 0x0455;
+ t['afii10103'] = 0x0456;
+ t['afii10104'] = 0x0457;
+ t['afii10105'] = 0x0458;
+ t['afii10106'] = 0x0459;
+ t['afii10107'] = 0x045A;
+ t['afii10108'] = 0x045B;
+ t['afii10109'] = 0x045C;
+ t['afii10110'] = 0x045E;
+ t['afii10145'] = 0x040F;
+ t['afii10146'] = 0x0462;
+ t['afii10147'] = 0x0472;
+ t['afii10148'] = 0x0474;
+ t['afii10192'] = 0xF6C6;
+ t['afii10193'] = 0x045F;
+ t['afii10194'] = 0x0463;
+ t['afii10195'] = 0x0473;
+ t['afii10196'] = 0x0475;
+ t['afii10831'] = 0xF6C7;
+ t['afii10832'] = 0xF6C8;
+ t['afii10846'] = 0x04D9;
+ t['afii299'] = 0x200E;
+ t['afii300'] = 0x200F;
+ t['afii301'] = 0x200D;
+ t['afii57381'] = 0x066A;
+ t['afii57388'] = 0x060C;
+ t['afii57392'] = 0x0660;
+ t['afii57393'] = 0x0661;
+ t['afii57394'] = 0x0662;
+ t['afii57395'] = 0x0663;
+ t['afii57396'] = 0x0664;
+ t['afii57397'] = 0x0665;
+ t['afii57398'] = 0x0666;
+ t['afii57399'] = 0x0667;
+ t['afii57400'] = 0x0668;
+ t['afii57401'] = 0x0669;
+ t['afii57403'] = 0x061B;
+ t['afii57407'] = 0x061F;
+ t['afii57409'] = 0x0621;
+ t['afii57410'] = 0x0622;
+ t['afii57411'] = 0x0623;
+ t['afii57412'] = 0x0624;
+ t['afii57413'] = 0x0625;
+ t['afii57414'] = 0x0626;
+ t['afii57415'] = 0x0627;
+ t['afii57416'] = 0x0628;
+ t['afii57417'] = 0x0629;
+ t['afii57418'] = 0x062A;
+ t['afii57419'] = 0x062B;
+ t['afii57420'] = 0x062C;
+ t['afii57421'] = 0x062D;
+ t['afii57422'] = 0x062E;
+ t['afii57423'] = 0x062F;
+ t['afii57424'] = 0x0630;
+ t['afii57425'] = 0x0631;
+ t['afii57426'] = 0x0632;
+ t['afii57427'] = 0x0633;
+ t['afii57428'] = 0x0634;
+ t['afii57429'] = 0x0635;
+ t['afii57430'] = 0x0636;
+ t['afii57431'] = 0x0637;
+ t['afii57432'] = 0x0638;
+ t['afii57433'] = 0x0639;
+ t['afii57434'] = 0x063A;
+ t['afii57440'] = 0x0640;
+ t['afii57441'] = 0x0641;
+ t['afii57442'] = 0x0642;
+ t['afii57443'] = 0x0643;
+ t['afii57444'] = 0x0644;
+ t['afii57445'] = 0x0645;
+ t['afii57446'] = 0x0646;
+ t['afii57448'] = 0x0648;
+ t['afii57449'] = 0x0649;
+ t['afii57450'] = 0x064A;
+ t['afii57451'] = 0x064B;
+ t['afii57452'] = 0x064C;
+ t['afii57453'] = 0x064D;
+ t['afii57454'] = 0x064E;
+ t['afii57455'] = 0x064F;
+ t['afii57456'] = 0x0650;
+ t['afii57457'] = 0x0651;
+ t['afii57458'] = 0x0652;
+ t['afii57470'] = 0x0647;
+ t['afii57505'] = 0x06A4;
+ t['afii57506'] = 0x067E;
+ t['afii57507'] = 0x0686;
+ t['afii57508'] = 0x0698;
+ t['afii57509'] = 0x06AF;
+ t['afii57511'] = 0x0679;
+ t['afii57512'] = 0x0688;
+ t['afii57513'] = 0x0691;
+ t['afii57514'] = 0x06BA;
+ t['afii57519'] = 0x06D2;
+ t['afii57534'] = 0x06D5;
+ t['afii57636'] = 0x20AA;
+ t['afii57645'] = 0x05BE;
+ t['afii57658'] = 0x05C3;
+ t['afii57664'] = 0x05D0;
+ t['afii57665'] = 0x05D1;
+ t['afii57666'] = 0x05D2;
+ t['afii57667'] = 0x05D3;
+ t['afii57668'] = 0x05D4;
+ t['afii57669'] = 0x05D5;
+ t['afii57670'] = 0x05D6;
+ t['afii57671'] = 0x05D7;
+ t['afii57672'] = 0x05D8;
+ t['afii57673'] = 0x05D9;
+ t['afii57674'] = 0x05DA;
+ t['afii57675'] = 0x05DB;
+ t['afii57676'] = 0x05DC;
+ t['afii57677'] = 0x05DD;
+ t['afii57678'] = 0x05DE;
+ t['afii57679'] = 0x05DF;
+ t['afii57680'] = 0x05E0;
+ t['afii57681'] = 0x05E1;
+ t['afii57682'] = 0x05E2;
+ t['afii57683'] = 0x05E3;
+ t['afii57684'] = 0x05E4;
+ t['afii57685'] = 0x05E5;
+ t['afii57686'] = 0x05E6;
+ t['afii57687'] = 0x05E7;
+ t['afii57688'] = 0x05E8;
+ t['afii57689'] = 0x05E9;
+ t['afii57690'] = 0x05EA;
+ t['afii57694'] = 0xFB2A;
+ t['afii57695'] = 0xFB2B;
+ t['afii57700'] = 0xFB4B;
+ t['afii57705'] = 0xFB1F;
+ t['afii57716'] = 0x05F0;
+ t['afii57717'] = 0x05F1;
+ t['afii57718'] = 0x05F2;
+ t['afii57723'] = 0xFB35;
+ t['afii57793'] = 0x05B4;
+ t['afii57794'] = 0x05B5;
+ t['afii57795'] = 0x05B6;
+ t['afii57796'] = 0x05BB;
+ t['afii57797'] = 0x05B8;
+ t['afii57798'] = 0x05B7;
+ t['afii57799'] = 0x05B0;
+ t['afii57800'] = 0x05B2;
+ t['afii57801'] = 0x05B1;
+ t['afii57802'] = 0x05B3;
+ t['afii57803'] = 0x05C2;
+ t['afii57804'] = 0x05C1;
+ t['afii57806'] = 0x05B9;
+ t['afii57807'] = 0x05BC;
+ t['afii57839'] = 0x05BD;
+ t['afii57841'] = 0x05BF;
+ t['afii57842'] = 0x05C0;
+ t['afii57929'] = 0x02BC;
+ t['afii61248'] = 0x2105;
+ t['afii61289'] = 0x2113;
+ t['afii61352'] = 0x2116;
+ t['afii61573'] = 0x202C;
+ t['afii61574'] = 0x202D;
+ t['afii61575'] = 0x202E;
+ t['afii61664'] = 0x200C;
+ t['afii63167'] = 0x066D;
+ t['afii64937'] = 0x02BD;
+ t['agrave'] = 0x00E0;
+ t['agujarati'] = 0x0A85;
+ t['agurmukhi'] = 0x0A05;
+ t['ahiragana'] = 0x3042;
+ t['ahookabove'] = 0x1EA3;
+ t['aibengali'] = 0x0990;
+ t['aibopomofo'] = 0x311E;
+ t['aideva'] = 0x0910;
+ t['aiecyrillic'] = 0x04D5;
+ t['aigujarati'] = 0x0A90;
+ t['aigurmukhi'] = 0x0A10;
+ t['aimatragurmukhi'] = 0x0A48;
+ t['ainarabic'] = 0x0639;
+ t['ainfinalarabic'] = 0xFECA;
+ t['aininitialarabic'] = 0xFECB;
+ t['ainmedialarabic'] = 0xFECC;
+ t['ainvertedbreve'] = 0x0203;
+ t['aivowelsignbengali'] = 0x09C8;
+ t['aivowelsigndeva'] = 0x0948;
+ t['aivowelsigngujarati'] = 0x0AC8;
+ t['akatakana'] = 0x30A2;
+ t['akatakanahalfwidth'] = 0xFF71;
+ t['akorean'] = 0x314F;
+ t['alef'] = 0x05D0;
+ t['alefarabic'] = 0x0627;
+ t['alefdageshhebrew'] = 0xFB30;
+ t['aleffinalarabic'] = 0xFE8E;
+ t['alefhamzaabovearabic'] = 0x0623;
+ t['alefhamzaabovefinalarabic'] = 0xFE84;
+ t['alefhamzabelowarabic'] = 0x0625;
+ t['alefhamzabelowfinalarabic'] = 0xFE88;
+ t['alefhebrew'] = 0x05D0;
+ t['aleflamedhebrew'] = 0xFB4F;
+ t['alefmaddaabovearabic'] = 0x0622;
+ t['alefmaddaabovefinalarabic'] = 0xFE82;
+ t['alefmaksuraarabic'] = 0x0649;
+ t['alefmaksurafinalarabic'] = 0xFEF0;
+ t['alefmaksurainitialarabic'] = 0xFEF3;
+ t['alefmaksuramedialarabic'] = 0xFEF4;
+ t['alefpatahhebrew'] = 0xFB2E;
+ t['alefqamatshebrew'] = 0xFB2F;
+ t['aleph'] = 0x2135;
+ t['allequal'] = 0x224C;
+ t['alpha'] = 0x03B1;
+ t['alphatonos'] = 0x03AC;
+ t['amacron'] = 0x0101;
+ t['amonospace'] = 0xFF41;
+ t['ampersand'] = 0x0026;
+ t['ampersandmonospace'] = 0xFF06;
+ t['ampersandsmall'] = 0xF726;
+ t['amsquare'] = 0x33C2;
+ t['anbopomofo'] = 0x3122;
+ t['angbopomofo'] = 0x3124;
+ t['angbracketleft'] = 0x3008;
+ t['angbracketright'] = 0x3009;
+ t['angkhankhuthai'] = 0x0E5A;
+ t['angle'] = 0x2220;
+ t['anglebracketleft'] = 0x3008;
+ t['anglebracketleftvertical'] = 0xFE3F;
+ t['anglebracketright'] = 0x3009;
+ t['anglebracketrightvertical'] = 0xFE40;
+ t['angleleft'] = 0x2329;
+ t['angleright'] = 0x232A;
+ t['angstrom'] = 0x212B;
+ t['anoteleia'] = 0x0387;
+ t['anudattadeva'] = 0x0952;
+ t['anusvarabengali'] = 0x0982;
+ t['anusvaradeva'] = 0x0902;
+ t['anusvaragujarati'] = 0x0A82;
+ t['aogonek'] = 0x0105;
+ t['apaatosquare'] = 0x3300;
+ t['aparen'] = 0x249C;
+ t['apostrophearmenian'] = 0x055A;
+ t['apostrophemod'] = 0x02BC;
+ t['apple'] = 0xF8FF;
+ t['approaches'] = 0x2250;
+ t['approxequal'] = 0x2248;
+ t['approxequalorimage'] = 0x2252;
+ t['approximatelyequal'] = 0x2245;
+ t['araeaekorean'] = 0x318E;
+ t['araeakorean'] = 0x318D;
+ t['arc'] = 0x2312;
+ t['arighthalfring'] = 0x1E9A;
+ t['aring'] = 0x00E5;
+ t['aringacute'] = 0x01FB;
+ t['aringbelow'] = 0x1E01;
+ t['arrowboth'] = 0x2194;
+ t['arrowdashdown'] = 0x21E3;
+ t['arrowdashleft'] = 0x21E0;
+ t['arrowdashright'] = 0x21E2;
+ t['arrowdashup'] = 0x21E1;
+ t['arrowdblboth'] = 0x21D4;
+ t['arrowdbldown'] = 0x21D3;
+ t['arrowdblleft'] = 0x21D0;
+ t['arrowdblright'] = 0x21D2;
+ t['arrowdblup'] = 0x21D1;
+ t['arrowdown'] = 0x2193;
+ t['arrowdownleft'] = 0x2199;
+ t['arrowdownright'] = 0x2198;
+ t['arrowdownwhite'] = 0x21E9;
+ t['arrowheaddownmod'] = 0x02C5;
+ t['arrowheadleftmod'] = 0x02C2;
+ t['arrowheadrightmod'] = 0x02C3;
+ t['arrowheadupmod'] = 0x02C4;
+ t['arrowhorizex'] = 0xF8E7;
+ t['arrowleft'] = 0x2190;
+ t['arrowleftdbl'] = 0x21D0;
+ t['arrowleftdblstroke'] = 0x21CD;
+ t['arrowleftoverright'] = 0x21C6;
+ t['arrowleftwhite'] = 0x21E6;
+ t['arrowright'] = 0x2192;
+ t['arrowrightdblstroke'] = 0x21CF;
+ t['arrowrightheavy'] = 0x279E;
+ t['arrowrightoverleft'] = 0x21C4;
+ t['arrowrightwhite'] = 0x21E8;
+ t['arrowtableft'] = 0x21E4;
+ t['arrowtabright'] = 0x21E5;
+ t['arrowup'] = 0x2191;
+ t['arrowupdn'] = 0x2195;
+ t['arrowupdnbse'] = 0x21A8;
+ t['arrowupdownbase'] = 0x21A8;
+ t['arrowupleft'] = 0x2196;
+ t['arrowupleftofdown'] = 0x21C5;
+ t['arrowupright'] = 0x2197;
+ t['arrowupwhite'] = 0x21E7;
+ t['arrowvertex'] = 0xF8E6;
+ t['asciicircum'] = 0x005E;
+ t['asciicircummonospace'] = 0xFF3E;
+ t['asciitilde'] = 0x007E;
+ t['asciitildemonospace'] = 0xFF5E;
+ t['ascript'] = 0x0251;
+ t['ascriptturned'] = 0x0252;
+ t['asmallhiragana'] = 0x3041;
+ t['asmallkatakana'] = 0x30A1;
+ t['asmallkatakanahalfwidth'] = 0xFF67;
+ t['asterisk'] = 0x002A;
+ t['asteriskaltonearabic'] = 0x066D;
+ t['asteriskarabic'] = 0x066D;
+ t['asteriskmath'] = 0x2217;
+ t['asteriskmonospace'] = 0xFF0A;
+ t['asterisksmall'] = 0xFE61;
+ t['asterism'] = 0x2042;
+ t['asuperior'] = 0xF6E9;
+ t['asymptoticallyequal'] = 0x2243;
+ t['at'] = 0x0040;
+ t['atilde'] = 0x00E3;
+ t['atmonospace'] = 0xFF20;
+ t['atsmall'] = 0xFE6B;
+ t['aturned'] = 0x0250;
+ t['aubengali'] = 0x0994;
+ t['aubopomofo'] = 0x3120;
+ t['audeva'] = 0x0914;
+ t['augujarati'] = 0x0A94;
+ t['augurmukhi'] = 0x0A14;
+ t['aulengthmarkbengali'] = 0x09D7;
+ t['aumatragurmukhi'] = 0x0A4C;
+ t['auvowelsignbengali'] = 0x09CC;
+ t['auvowelsigndeva'] = 0x094C;
+ t['auvowelsigngujarati'] = 0x0ACC;
+ t['avagrahadeva'] = 0x093D;
+ t['aybarmenian'] = 0x0561;
+ t['ayin'] = 0x05E2;
+ t['ayinaltonehebrew'] = 0xFB20;
+ t['ayinhebrew'] = 0x05E2;
+ t['b'] = 0x0062;
+ t['babengali'] = 0x09AC;
+ t['backslash'] = 0x005C;
+ t['backslashmonospace'] = 0xFF3C;
+ t['badeva'] = 0x092C;
+ t['bagujarati'] = 0x0AAC;
+ t['bagurmukhi'] = 0x0A2C;
+ t['bahiragana'] = 0x3070;
+ t['bahtthai'] = 0x0E3F;
+ t['bakatakana'] = 0x30D0;
+ t['bar'] = 0x007C;
+ t['barmonospace'] = 0xFF5C;
+ t['bbopomofo'] = 0x3105;
+ t['bcircle'] = 0x24D1;
+ t['bdotaccent'] = 0x1E03;
+ t['bdotbelow'] = 0x1E05;
+ t['beamedsixteenthnotes'] = 0x266C;
+ t['because'] = 0x2235;
+ t['becyrillic'] = 0x0431;
+ t['beharabic'] = 0x0628;
+ t['behfinalarabic'] = 0xFE90;
+ t['behinitialarabic'] = 0xFE91;
+ t['behiragana'] = 0x3079;
+ t['behmedialarabic'] = 0xFE92;
+ t['behmeeminitialarabic'] = 0xFC9F;
+ t['behmeemisolatedarabic'] = 0xFC08;
+ t['behnoonfinalarabic'] = 0xFC6D;
+ t['bekatakana'] = 0x30D9;
+ t['benarmenian'] = 0x0562;
+ t['bet'] = 0x05D1;
+ t['beta'] = 0x03B2;
+ t['betasymbolgreek'] = 0x03D0;
+ t['betdagesh'] = 0xFB31;
+ t['betdageshhebrew'] = 0xFB31;
+ t['bethebrew'] = 0x05D1;
+ t['betrafehebrew'] = 0xFB4C;
+ t['bhabengali'] = 0x09AD;
+ t['bhadeva'] = 0x092D;
+ t['bhagujarati'] = 0x0AAD;
+ t['bhagurmukhi'] = 0x0A2D;
+ t['bhook'] = 0x0253;
+ t['bihiragana'] = 0x3073;
+ t['bikatakana'] = 0x30D3;
+ t['bilabialclick'] = 0x0298;
+ t['bindigurmukhi'] = 0x0A02;
+ t['birusquare'] = 0x3331;
+ t['blackcircle'] = 0x25CF;
+ t['blackdiamond'] = 0x25C6;
+ t['blackdownpointingtriangle'] = 0x25BC;
+ t['blackleftpointingpointer'] = 0x25C4;
+ t['blackleftpointingtriangle'] = 0x25C0;
+ t['blacklenticularbracketleft'] = 0x3010;
+ t['blacklenticularbracketleftvertical'] = 0xFE3B;
+ t['blacklenticularbracketright'] = 0x3011;
+ t['blacklenticularbracketrightvertical'] = 0xFE3C;
+ t['blacklowerlefttriangle'] = 0x25E3;
+ t['blacklowerrighttriangle'] = 0x25E2;
+ t['blackrectangle'] = 0x25AC;
+ t['blackrightpointingpointer'] = 0x25BA;
+ t['blackrightpointingtriangle'] = 0x25B6;
+ t['blacksmallsquare'] = 0x25AA;
+ t['blacksmilingface'] = 0x263B;
+ t['blacksquare'] = 0x25A0;
+ t['blackstar'] = 0x2605;
+ t['blackupperlefttriangle'] = 0x25E4;
+ t['blackupperrighttriangle'] = 0x25E5;
+ t['blackuppointingsmalltriangle'] = 0x25B4;
+ t['blackuppointingtriangle'] = 0x25B2;
+ t['blank'] = 0x2423;
+ t['blinebelow'] = 0x1E07;
+ t['block'] = 0x2588;
+ t['bmonospace'] = 0xFF42;
+ t['bobaimaithai'] = 0x0E1A;
+ t['bohiragana'] = 0x307C;
+ t['bokatakana'] = 0x30DC;
+ t['bparen'] = 0x249D;
+ t['bqsquare'] = 0x33C3;
+ t['braceex'] = 0xF8F4;
+ t['braceleft'] = 0x007B;
+ t['braceleftbt'] = 0xF8F3;
+ t['braceleftmid'] = 0xF8F2;
+ t['braceleftmonospace'] = 0xFF5B;
+ t['braceleftsmall'] = 0xFE5B;
+ t['bracelefttp'] = 0xF8F1;
+ t['braceleftvertical'] = 0xFE37;
+ t['braceright'] = 0x007D;
+ t['bracerightbt'] = 0xF8FE;
+ t['bracerightmid'] = 0xF8FD;
+ t['bracerightmonospace'] = 0xFF5D;
+ t['bracerightsmall'] = 0xFE5C;
+ t['bracerighttp'] = 0xF8FC;
+ t['bracerightvertical'] = 0xFE38;
+ t['bracketleft'] = 0x005B;
+ t['bracketleftbt'] = 0xF8F0;
+ t['bracketleftex'] = 0xF8EF;
+ t['bracketleftmonospace'] = 0xFF3B;
+ t['bracketlefttp'] = 0xF8EE;
+ t['bracketright'] = 0x005D;
+ t['bracketrightbt'] = 0xF8FB;
+ t['bracketrightex'] = 0xF8FA;
+ t['bracketrightmonospace'] = 0xFF3D;
+ t['bracketrighttp'] = 0xF8F9;
+ t['breve'] = 0x02D8;
+ t['brevebelowcmb'] = 0x032E;
+ t['brevecmb'] = 0x0306;
+ t['breveinvertedbelowcmb'] = 0x032F;
+ t['breveinvertedcmb'] = 0x0311;
+ t['breveinverteddoublecmb'] = 0x0361;
+ t['bridgebelowcmb'] = 0x032A;
+ t['bridgeinvertedbelowcmb'] = 0x033A;
+ t['brokenbar'] = 0x00A6;
+ t['bstroke'] = 0x0180;
+ t['bsuperior'] = 0xF6EA;
+ t['btopbar'] = 0x0183;
+ t['buhiragana'] = 0x3076;
+ t['bukatakana'] = 0x30D6;
+ t['bullet'] = 0x2022;
+ t['bulletinverse'] = 0x25D8;
+ t['bulletoperator'] = 0x2219;
+ t['bullseye'] = 0x25CE;
+ t['c'] = 0x0063;
+ t['caarmenian'] = 0x056E;
+ t['cabengali'] = 0x099A;
+ t['cacute'] = 0x0107;
+ t['cadeva'] = 0x091A;
+ t['cagujarati'] = 0x0A9A;
+ t['cagurmukhi'] = 0x0A1A;
+ t['calsquare'] = 0x3388;
+ t['candrabindubengali'] = 0x0981;
+ t['candrabinducmb'] = 0x0310;
+ t['candrabindudeva'] = 0x0901;
+ t['candrabindugujarati'] = 0x0A81;
+ t['capslock'] = 0x21EA;
+ t['careof'] = 0x2105;
+ t['caron'] = 0x02C7;
+ t['caronbelowcmb'] = 0x032C;
+ t['caroncmb'] = 0x030C;
+ t['carriagereturn'] = 0x21B5;
+ t['cbopomofo'] = 0x3118;
+ t['ccaron'] = 0x010D;
+ t['ccedilla'] = 0x00E7;
+ t['ccedillaacute'] = 0x1E09;
+ t['ccircle'] = 0x24D2;
+ t['ccircumflex'] = 0x0109;
+ t['ccurl'] = 0x0255;
+ t['cdot'] = 0x010B;
+ t['cdotaccent'] = 0x010B;
+ t['cdsquare'] = 0x33C5;
+ t['cedilla'] = 0x00B8;
+ t['cedillacmb'] = 0x0327;
+ t['cent'] = 0x00A2;
+ t['centigrade'] = 0x2103;
+ t['centinferior'] = 0xF6DF;
+ t['centmonospace'] = 0xFFE0;
+ t['centoldstyle'] = 0xF7A2;
+ t['centsuperior'] = 0xF6E0;
+ t['chaarmenian'] = 0x0579;
+ t['chabengali'] = 0x099B;
+ t['chadeva'] = 0x091B;
+ t['chagujarati'] = 0x0A9B;
+ t['chagurmukhi'] = 0x0A1B;
+ t['chbopomofo'] = 0x3114;
+ t['cheabkhasiancyrillic'] = 0x04BD;
+ t['checkmark'] = 0x2713;
+ t['checyrillic'] = 0x0447;
+ t['chedescenderabkhasiancyrillic'] = 0x04BF;
+ t['chedescendercyrillic'] = 0x04B7;
+ t['chedieresiscyrillic'] = 0x04F5;
+ t['cheharmenian'] = 0x0573;
+ t['chekhakassiancyrillic'] = 0x04CC;
+ t['cheverticalstrokecyrillic'] = 0x04B9;
+ t['chi'] = 0x03C7;
+ t['chieuchacirclekorean'] = 0x3277;
+ t['chieuchaparenkorean'] = 0x3217;
+ t['chieuchcirclekorean'] = 0x3269;
+ t['chieuchkorean'] = 0x314A;
+ t['chieuchparenkorean'] = 0x3209;
+ t['chochangthai'] = 0x0E0A;
+ t['chochanthai'] = 0x0E08;
+ t['chochingthai'] = 0x0E09;
+ t['chochoethai'] = 0x0E0C;
+ t['chook'] = 0x0188;
+ t['cieucacirclekorean'] = 0x3276;
+ t['cieucaparenkorean'] = 0x3216;
+ t['cieuccirclekorean'] = 0x3268;
+ t['cieuckorean'] = 0x3148;
+ t['cieucparenkorean'] = 0x3208;
+ t['cieucuparenkorean'] = 0x321C;
+ t['circle'] = 0x25CB;
+ t['circlecopyrt'] = 0x00A9;
+ t['circlemultiply'] = 0x2297;
+ t['circleot'] = 0x2299;
+ t['circleplus'] = 0x2295;
+ t['circlepostalmark'] = 0x3036;
+ t['circlewithlefthalfblack'] = 0x25D0;
+ t['circlewithrighthalfblack'] = 0x25D1;
+ t['circumflex'] = 0x02C6;
+ t['circumflexbelowcmb'] = 0x032D;
+ t['circumflexcmb'] = 0x0302;
+ t['clear'] = 0x2327;
+ t['clickalveolar'] = 0x01C2;
+ t['clickdental'] = 0x01C0;
+ t['clicklateral'] = 0x01C1;
+ t['clickretroflex'] = 0x01C3;
+ t['club'] = 0x2663;
+ t['clubsuitblack'] = 0x2663;
+ t['clubsuitwhite'] = 0x2667;
+ t['cmcubedsquare'] = 0x33A4;
+ t['cmonospace'] = 0xFF43;
+ t['cmsquaredsquare'] = 0x33A0;
+ t['coarmenian'] = 0x0581;
+ t['colon'] = 0x003A;
+ t['colonmonetary'] = 0x20A1;
+ t['colonmonospace'] = 0xFF1A;
+ t['colonsign'] = 0x20A1;
+ t['colonsmall'] = 0xFE55;
+ t['colontriangularhalfmod'] = 0x02D1;
+ t['colontriangularmod'] = 0x02D0;
+ t['comma'] = 0x002C;
+ t['commaabovecmb'] = 0x0313;
+ t['commaaboverightcmb'] = 0x0315;
+ t['commaaccent'] = 0xF6C3;
+ t['commaarabic'] = 0x060C;
+ t['commaarmenian'] = 0x055D;
+ t['commainferior'] = 0xF6E1;
+ t['commamonospace'] = 0xFF0C;
+ t['commareversedabovecmb'] = 0x0314;
+ t['commareversedmod'] = 0x02BD;
+ t['commasmall'] = 0xFE50;
+ t['commasuperior'] = 0xF6E2;
+ t['commaturnedabovecmb'] = 0x0312;
+ t['commaturnedmod'] = 0x02BB;
+ t['compass'] = 0x263C;
+ t['congruent'] = 0x2245;
+ t['contourintegral'] = 0x222E;
+ t['control'] = 0x2303;
+ t['controlACK'] = 0x0006;
+ t['controlBEL'] = 0x0007;
+ t['controlBS'] = 0x0008;
+ t['controlCAN'] = 0x0018;
+ t['controlCR'] = 0x000D;
+ t['controlDC1'] = 0x0011;
+ t['controlDC2'] = 0x0012;
+ t['controlDC3'] = 0x0013;
+ t['controlDC4'] = 0x0014;
+ t['controlDEL'] = 0x007F;
+ t['controlDLE'] = 0x0010;
+ t['controlEM'] = 0x0019;
+ t['controlENQ'] = 0x0005;
+ t['controlEOT'] = 0x0004;
+ t['controlESC'] = 0x001B;
+ t['controlETB'] = 0x0017;
+ t['controlETX'] = 0x0003;
+ t['controlFF'] = 0x000C;
+ t['controlFS'] = 0x001C;
+ t['controlGS'] = 0x001D;
+ t['controlHT'] = 0x0009;
+ t['controlLF'] = 0x000A;
+ t['controlNAK'] = 0x0015;
+ t['controlNULL'] = 0x0000;
+ t['controlRS'] = 0x001E;
+ t['controlSI'] = 0x000F;
+ t['controlSO'] = 0x000E;
+ t['controlSOT'] = 0x0002;
+ t['controlSTX'] = 0x0001;
+ t['controlSUB'] = 0x001A;
+ t['controlSYN'] = 0x0016;
+ t['controlUS'] = 0x001F;
+ t['controlVT'] = 0x000B;
+ t['copyright'] = 0x00A9;
+ t['copyrightsans'] = 0xF8E9;
+ t['copyrightserif'] = 0xF6D9;
+ t['cornerbracketleft'] = 0x300C;
+ t['cornerbracketlefthalfwidth'] = 0xFF62;
+ t['cornerbracketleftvertical'] = 0xFE41;
+ t['cornerbracketright'] = 0x300D;
+ t['cornerbracketrighthalfwidth'] = 0xFF63;
+ t['cornerbracketrightvertical'] = 0xFE42;
+ t['corporationsquare'] = 0x337F;
+ t['cosquare'] = 0x33C7;
+ t['coverkgsquare'] = 0x33C6;
+ t['cparen'] = 0x249E;
+ t['cruzeiro'] = 0x20A2;
+ t['cstretched'] = 0x0297;
+ t['curlyand'] = 0x22CF;
+ t['curlyor'] = 0x22CE;
+ t['currency'] = 0x00A4;
+ t['cyrBreve'] = 0xF6D1;
+ t['cyrFlex'] = 0xF6D2;
+ t['cyrbreve'] = 0xF6D4;
+ t['cyrflex'] = 0xF6D5;
+ t['d'] = 0x0064;
+ t['daarmenian'] = 0x0564;
+ t['dabengali'] = 0x09A6;
+ t['dadarabic'] = 0x0636;
+ t['dadeva'] = 0x0926;
+ t['dadfinalarabic'] = 0xFEBE;
+ t['dadinitialarabic'] = 0xFEBF;
+ t['dadmedialarabic'] = 0xFEC0;
+ t['dagesh'] = 0x05BC;
+ t['dageshhebrew'] = 0x05BC;
+ t['dagger'] = 0x2020;
+ t['daggerdbl'] = 0x2021;
+ t['dagujarati'] = 0x0AA6;
+ t['dagurmukhi'] = 0x0A26;
+ t['dahiragana'] = 0x3060;
+ t['dakatakana'] = 0x30C0;
+ t['dalarabic'] = 0x062F;
+ t['dalet'] = 0x05D3;
+ t['daletdagesh'] = 0xFB33;
+ t['daletdageshhebrew'] = 0xFB33;
+ t['dalethebrew'] = 0x05D3;
+ t['dalfinalarabic'] = 0xFEAA;
+ t['dammaarabic'] = 0x064F;
+ t['dammalowarabic'] = 0x064F;
+ t['dammatanaltonearabic'] = 0x064C;
+ t['dammatanarabic'] = 0x064C;
+ t['danda'] = 0x0964;
+ t['dargahebrew'] = 0x05A7;
+ t['dargalefthebrew'] = 0x05A7;
+ t['dasiapneumatacyrilliccmb'] = 0x0485;
+ t['dblGrave'] = 0xF6D3;
+ t['dblanglebracketleft'] = 0x300A;
+ t['dblanglebracketleftvertical'] = 0xFE3D;
+ t['dblanglebracketright'] = 0x300B;
+ t['dblanglebracketrightvertical'] = 0xFE3E;
+ t['dblarchinvertedbelowcmb'] = 0x032B;
+ t['dblarrowleft'] = 0x21D4;
+ t['dblarrowright'] = 0x21D2;
+ t['dbldanda'] = 0x0965;
+ t['dblgrave'] = 0xF6D6;
+ t['dblgravecmb'] = 0x030F;
+ t['dblintegral'] = 0x222C;
+ t['dbllowline'] = 0x2017;
+ t['dbllowlinecmb'] = 0x0333;
+ t['dbloverlinecmb'] = 0x033F;
+ t['dblprimemod'] = 0x02BA;
+ t['dblverticalbar'] = 0x2016;
+ t['dblverticallineabovecmb'] = 0x030E;
+ t['dbopomofo'] = 0x3109;
+ t['dbsquare'] = 0x33C8;
+ t['dcaron'] = 0x010F;
+ t['dcedilla'] = 0x1E11;
+ t['dcircle'] = 0x24D3;
+ t['dcircumflexbelow'] = 0x1E13;
+ t['dcroat'] = 0x0111;
+ t['ddabengali'] = 0x09A1;
+ t['ddadeva'] = 0x0921;
+ t['ddagujarati'] = 0x0AA1;
+ t['ddagurmukhi'] = 0x0A21;
+ t['ddalarabic'] = 0x0688;
+ t['ddalfinalarabic'] = 0xFB89;
+ t['dddhadeva'] = 0x095C;
+ t['ddhabengali'] = 0x09A2;
+ t['ddhadeva'] = 0x0922;
+ t['ddhagujarati'] = 0x0AA2;
+ t['ddhagurmukhi'] = 0x0A22;
+ t['ddotaccent'] = 0x1E0B;
+ t['ddotbelow'] = 0x1E0D;
+ t['decimalseparatorarabic'] = 0x066B;
+ t['decimalseparatorpersian'] = 0x066B;
+ t['decyrillic'] = 0x0434;
+ t['degree'] = 0x00B0;
+ t['dehihebrew'] = 0x05AD;
+ t['dehiragana'] = 0x3067;
+ t['deicoptic'] = 0x03EF;
+ t['dekatakana'] = 0x30C7;
+ t['deleteleft'] = 0x232B;
+ t['deleteright'] = 0x2326;
+ t['delta'] = 0x03B4;
+ t['deltaturned'] = 0x018D;
+ t['denominatorminusonenumeratorbengali'] = 0x09F8;
+ t['dezh'] = 0x02A4;
+ t['dhabengali'] = 0x09A7;
+ t['dhadeva'] = 0x0927;
+ t['dhagujarati'] = 0x0AA7;
+ t['dhagurmukhi'] = 0x0A27;
+ t['dhook'] = 0x0257;
+ t['dialytikatonos'] = 0x0385;
+ t['dialytikatonoscmb'] = 0x0344;
+ t['diamond'] = 0x2666;
+ t['diamondsuitwhite'] = 0x2662;
+ t['dieresis'] = 0x00A8;
+ t['dieresisacute'] = 0xF6D7;
+ t['dieresisbelowcmb'] = 0x0324;
+ t['dieresiscmb'] = 0x0308;
+ t['dieresisgrave'] = 0xF6D8;
+ t['dieresistonos'] = 0x0385;
+ t['dihiragana'] = 0x3062;
+ t['dikatakana'] = 0x30C2;
+ t['dittomark'] = 0x3003;
+ t['divide'] = 0x00F7;
+ t['divides'] = 0x2223;
+ t['divisionslash'] = 0x2215;
+ t['djecyrillic'] = 0x0452;
+ t['dkshade'] = 0x2593;
+ t['dlinebelow'] = 0x1E0F;
+ t['dlsquare'] = 0x3397;
+ t['dmacron'] = 0x0111;
+ t['dmonospace'] = 0xFF44;
+ t['dnblock'] = 0x2584;
+ t['dochadathai'] = 0x0E0E;
+ t['dodekthai'] = 0x0E14;
+ t['dohiragana'] = 0x3069;
+ t['dokatakana'] = 0x30C9;
+ t['dollar'] = 0x0024;
+ t['dollarinferior'] = 0xF6E3;
+ t['dollarmonospace'] = 0xFF04;
+ t['dollaroldstyle'] = 0xF724;
+ t['dollarsmall'] = 0xFE69;
+ t['dollarsuperior'] = 0xF6E4;
+ t['dong'] = 0x20AB;
+ t['dorusquare'] = 0x3326;
+ t['dotaccent'] = 0x02D9;
+ t['dotaccentcmb'] = 0x0307;
+ t['dotbelowcmb'] = 0x0323;
+ t['dotbelowcomb'] = 0x0323;
+ t['dotkatakana'] = 0x30FB;
+ t['dotlessi'] = 0x0131;
+ t['dotlessj'] = 0xF6BE;
+ t['dotlessjstrokehook'] = 0x0284;
+ t['dotmath'] = 0x22C5;
+ t['dottedcircle'] = 0x25CC;
+ t['doubleyodpatah'] = 0xFB1F;
+ t['doubleyodpatahhebrew'] = 0xFB1F;
+ t['downtackbelowcmb'] = 0x031E;
+ t['downtackmod'] = 0x02D5;
+ t['dparen'] = 0x249F;
+ t['dsuperior'] = 0xF6EB;
+ t['dtail'] = 0x0256;
+ t['dtopbar'] = 0x018C;
+ t['duhiragana'] = 0x3065;
+ t['dukatakana'] = 0x30C5;
+ t['dz'] = 0x01F3;
+ t['dzaltone'] = 0x02A3;
+ t['dzcaron'] = 0x01C6;
+ t['dzcurl'] = 0x02A5;
+ t['dzeabkhasiancyrillic'] = 0x04E1;
+ t['dzecyrillic'] = 0x0455;
+ t['dzhecyrillic'] = 0x045F;
+ t['e'] = 0x0065;
+ t['eacute'] = 0x00E9;
+ t['earth'] = 0x2641;
+ t['ebengali'] = 0x098F;
+ t['ebopomofo'] = 0x311C;
+ t['ebreve'] = 0x0115;
+ t['ecandradeva'] = 0x090D;
+ t['ecandragujarati'] = 0x0A8D;
+ t['ecandravowelsigndeva'] = 0x0945;
+ t['ecandravowelsigngujarati'] = 0x0AC5;
+ t['ecaron'] = 0x011B;
+ t['ecedillabreve'] = 0x1E1D;
+ t['echarmenian'] = 0x0565;
+ t['echyiwnarmenian'] = 0x0587;
+ t['ecircle'] = 0x24D4;
+ t['ecircumflex'] = 0x00EA;
+ t['ecircumflexacute'] = 0x1EBF;
+ t['ecircumflexbelow'] = 0x1E19;
+ t['ecircumflexdotbelow'] = 0x1EC7;
+ t['ecircumflexgrave'] = 0x1EC1;
+ t['ecircumflexhookabove'] = 0x1EC3;
+ t['ecircumflextilde'] = 0x1EC5;
+ t['ecyrillic'] = 0x0454;
+ t['edblgrave'] = 0x0205;
+ t['edeva'] = 0x090F;
+ t['edieresis'] = 0x00EB;
+ t['edot'] = 0x0117;
+ t['edotaccent'] = 0x0117;
+ t['edotbelow'] = 0x1EB9;
+ t['eegurmukhi'] = 0x0A0F;
+ t['eematragurmukhi'] = 0x0A47;
+ t['efcyrillic'] = 0x0444;
+ t['egrave'] = 0x00E8;
+ t['egujarati'] = 0x0A8F;
+ t['eharmenian'] = 0x0567;
+ t['ehbopomofo'] = 0x311D;
+ t['ehiragana'] = 0x3048;
+ t['ehookabove'] = 0x1EBB;
+ t['eibopomofo'] = 0x311F;
+ t['eight'] = 0x0038;
+ t['eightarabic'] = 0x0668;
+ t['eightbengali'] = 0x09EE;
+ t['eightcircle'] = 0x2467;
+ t['eightcircleinversesansserif'] = 0x2791;
+ t['eightdeva'] = 0x096E;
+ t['eighteencircle'] = 0x2471;
+ t['eighteenparen'] = 0x2485;
+ t['eighteenperiod'] = 0x2499;
+ t['eightgujarati'] = 0x0AEE;
+ t['eightgurmukhi'] = 0x0A6E;
+ t['eighthackarabic'] = 0x0668;
+ t['eighthangzhou'] = 0x3028;
+ t['eighthnotebeamed'] = 0x266B;
+ t['eightideographicparen'] = 0x3227;
+ t['eightinferior'] = 0x2088;
+ t['eightmonospace'] = 0xFF18;
+ t['eightoldstyle'] = 0xF738;
+ t['eightparen'] = 0x247B;
+ t['eightperiod'] = 0x248F;
+ t['eightpersian'] = 0x06F8;
+ t['eightroman'] = 0x2177;
+ t['eightsuperior'] = 0x2078;
+ t['eightthai'] = 0x0E58;
+ t['einvertedbreve'] = 0x0207;
+ t['eiotifiedcyrillic'] = 0x0465;
+ t['ekatakana'] = 0x30A8;
+ t['ekatakanahalfwidth'] = 0xFF74;
+ t['ekonkargurmukhi'] = 0x0A74;
+ t['ekorean'] = 0x3154;
+ t['elcyrillic'] = 0x043B;
+ t['element'] = 0x2208;
+ t['elevencircle'] = 0x246A;
+ t['elevenparen'] = 0x247E;
+ t['elevenperiod'] = 0x2492;
+ t['elevenroman'] = 0x217A;
+ t['ellipsis'] = 0x2026;
+ t['ellipsisvertical'] = 0x22EE;
+ t['emacron'] = 0x0113;
+ t['emacronacute'] = 0x1E17;
+ t['emacrongrave'] = 0x1E15;
+ t['emcyrillic'] = 0x043C;
+ t['emdash'] = 0x2014;
+ t['emdashvertical'] = 0xFE31;
+ t['emonospace'] = 0xFF45;
+ t['emphasismarkarmenian'] = 0x055B;
+ t['emptyset'] = 0x2205;
+ t['enbopomofo'] = 0x3123;
+ t['encyrillic'] = 0x043D;
+ t['endash'] = 0x2013;
+ t['endashvertical'] = 0xFE32;
+ t['endescendercyrillic'] = 0x04A3;
+ t['eng'] = 0x014B;
+ t['engbopomofo'] = 0x3125;
+ t['enghecyrillic'] = 0x04A5;
+ t['enhookcyrillic'] = 0x04C8;
+ t['enspace'] = 0x2002;
+ t['eogonek'] = 0x0119;
+ t['eokorean'] = 0x3153;
+ t['eopen'] = 0x025B;
+ t['eopenclosed'] = 0x029A;
+ t['eopenreversed'] = 0x025C;
+ t['eopenreversedclosed'] = 0x025E;
+ t['eopenreversedhook'] = 0x025D;
+ t['eparen'] = 0x24A0;
+ t['epsilon'] = 0x03B5;
+ t['epsilontonos'] = 0x03AD;
+ t['equal'] = 0x003D;
+ t['equalmonospace'] = 0xFF1D;
+ t['equalsmall'] = 0xFE66;
+ t['equalsuperior'] = 0x207C;
+ t['equivalence'] = 0x2261;
+ t['erbopomofo'] = 0x3126;
+ t['ercyrillic'] = 0x0440;
+ t['ereversed'] = 0x0258;
+ t['ereversedcyrillic'] = 0x044D;
+ t['escyrillic'] = 0x0441;
+ t['esdescendercyrillic'] = 0x04AB;
+ t['esh'] = 0x0283;
+ t['eshcurl'] = 0x0286;
+ t['eshortdeva'] = 0x090E;
+ t['eshortvowelsigndeva'] = 0x0946;
+ t['eshreversedloop'] = 0x01AA;
+ t['eshsquatreversed'] = 0x0285;
+ t['esmallhiragana'] = 0x3047;
+ t['esmallkatakana'] = 0x30A7;
+ t['esmallkatakanahalfwidth'] = 0xFF6A;
+ t['estimated'] = 0x212E;
+ t['esuperior'] = 0xF6EC;
+ t['eta'] = 0x03B7;
+ t['etarmenian'] = 0x0568;
+ t['etatonos'] = 0x03AE;
+ t['eth'] = 0x00F0;
+ t['etilde'] = 0x1EBD;
+ t['etildebelow'] = 0x1E1B;
+ t['etnahtafoukhhebrew'] = 0x0591;
+ t['etnahtafoukhlefthebrew'] = 0x0591;
+ t['etnahtahebrew'] = 0x0591;
+ t['etnahtalefthebrew'] = 0x0591;
+ t['eturned'] = 0x01DD;
+ t['eukorean'] = 0x3161;
+ t['euro'] = 0x20AC;
+ t['evowelsignbengali'] = 0x09C7;
+ t['evowelsigndeva'] = 0x0947;
+ t['evowelsigngujarati'] = 0x0AC7;
+ t['exclam'] = 0x0021;
+ t['exclamarmenian'] = 0x055C;
+ t['exclamdbl'] = 0x203C;
+ t['exclamdown'] = 0x00A1;
+ t['exclamdownsmall'] = 0xF7A1;
+ t['exclammonospace'] = 0xFF01;
+ t['exclamsmall'] = 0xF721;
+ t['existential'] = 0x2203;
+ t['ezh'] = 0x0292;
+ t['ezhcaron'] = 0x01EF;
+ t['ezhcurl'] = 0x0293;
+ t['ezhreversed'] = 0x01B9;
+ t['ezhtail'] = 0x01BA;
+ t['f'] = 0x0066;
+ t['fadeva'] = 0x095E;
+ t['fagurmukhi'] = 0x0A5E;
+ t['fahrenheit'] = 0x2109;
+ t['fathaarabic'] = 0x064E;
+ t['fathalowarabic'] = 0x064E;
+ t['fathatanarabic'] = 0x064B;
+ t['fbopomofo'] = 0x3108;
+ t['fcircle'] = 0x24D5;
+ t['fdotaccent'] = 0x1E1F;
+ t['feharabic'] = 0x0641;
+ t['feharmenian'] = 0x0586;
+ t['fehfinalarabic'] = 0xFED2;
+ t['fehinitialarabic'] = 0xFED3;
+ t['fehmedialarabic'] = 0xFED4;
+ t['feicoptic'] = 0x03E5;
+ t['female'] = 0x2640;
+ t['ff'] = 0xFB00;
+ t['ffi'] = 0xFB03;
+ t['ffl'] = 0xFB04;
+ t['fi'] = 0xFB01;
+ t['fifteencircle'] = 0x246E;
+ t['fifteenparen'] = 0x2482;
+ t['fifteenperiod'] = 0x2496;
+ t['figuredash'] = 0x2012;
+ t['filledbox'] = 0x25A0;
+ t['filledrect'] = 0x25AC;
+ t['finalkaf'] = 0x05DA;
+ t['finalkafdagesh'] = 0xFB3A;
+ t['finalkafdageshhebrew'] = 0xFB3A;
+ t['finalkafhebrew'] = 0x05DA;
+ t['finalmem'] = 0x05DD;
+ t['finalmemhebrew'] = 0x05DD;
+ t['finalnun'] = 0x05DF;
+ t['finalnunhebrew'] = 0x05DF;
+ t['finalpe'] = 0x05E3;
+ t['finalpehebrew'] = 0x05E3;
+ t['finaltsadi'] = 0x05E5;
+ t['finaltsadihebrew'] = 0x05E5;
+ t['firsttonechinese'] = 0x02C9;
+ t['fisheye'] = 0x25C9;
+ t['fitacyrillic'] = 0x0473;
+ t['five'] = 0x0035;
+ t['fivearabic'] = 0x0665;
+ t['fivebengali'] = 0x09EB;
+ t['fivecircle'] = 0x2464;
+ t['fivecircleinversesansserif'] = 0x278E;
+ t['fivedeva'] = 0x096B;
+ t['fiveeighths'] = 0x215D;
+ t['fivegujarati'] = 0x0AEB;
+ t['fivegurmukhi'] = 0x0A6B;
+ t['fivehackarabic'] = 0x0665;
+ t['fivehangzhou'] = 0x3025;
+ t['fiveideographicparen'] = 0x3224;
+ t['fiveinferior'] = 0x2085;
+ t['fivemonospace'] = 0xFF15;
+ t['fiveoldstyle'] = 0xF735;
+ t['fiveparen'] = 0x2478;
+ t['fiveperiod'] = 0x248C;
+ t['fivepersian'] = 0x06F5;
+ t['fiveroman'] = 0x2174;
+ t['fivesuperior'] = 0x2075;
+ t['fivethai'] = 0x0E55;
+ t['fl'] = 0xFB02;
+ t['florin'] = 0x0192;
+ t['fmonospace'] = 0xFF46;
+ t['fmsquare'] = 0x3399;
+ t['fofanthai'] = 0x0E1F;
+ t['fofathai'] = 0x0E1D;
+ t['fongmanthai'] = 0x0E4F;
+ t['forall'] = 0x2200;
+ t['four'] = 0x0034;
+ t['fourarabic'] = 0x0664;
+ t['fourbengali'] = 0x09EA;
+ t['fourcircle'] = 0x2463;
+ t['fourcircleinversesansserif'] = 0x278D;
+ t['fourdeva'] = 0x096A;
+ t['fourgujarati'] = 0x0AEA;
+ t['fourgurmukhi'] = 0x0A6A;
+ t['fourhackarabic'] = 0x0664;
+ t['fourhangzhou'] = 0x3024;
+ t['fourideographicparen'] = 0x3223;
+ t['fourinferior'] = 0x2084;
+ t['fourmonospace'] = 0xFF14;
+ t['fournumeratorbengali'] = 0x09F7;
+ t['fouroldstyle'] = 0xF734;
+ t['fourparen'] = 0x2477;
+ t['fourperiod'] = 0x248B;
+ t['fourpersian'] = 0x06F4;
+ t['fourroman'] = 0x2173;
+ t['foursuperior'] = 0x2074;
+ t['fourteencircle'] = 0x246D;
+ t['fourteenparen'] = 0x2481;
+ t['fourteenperiod'] = 0x2495;
+ t['fourthai'] = 0x0E54;
+ t['fourthtonechinese'] = 0x02CB;
+ t['fparen'] = 0x24A1;
+ t['fraction'] = 0x2044;
+ t['franc'] = 0x20A3;
+ t['g'] = 0x0067;
+ t['gabengali'] = 0x0997;
+ t['gacute'] = 0x01F5;
+ t['gadeva'] = 0x0917;
+ t['gafarabic'] = 0x06AF;
+ t['gaffinalarabic'] = 0xFB93;
+ t['gafinitialarabic'] = 0xFB94;
+ t['gafmedialarabic'] = 0xFB95;
+ t['gagujarati'] = 0x0A97;
+ t['gagurmukhi'] = 0x0A17;
+ t['gahiragana'] = 0x304C;
+ t['gakatakana'] = 0x30AC;
+ t['gamma'] = 0x03B3;
+ t['gammalatinsmall'] = 0x0263;
+ t['gammasuperior'] = 0x02E0;
+ t['gangiacoptic'] = 0x03EB;
+ t['gbopomofo'] = 0x310D;
+ t['gbreve'] = 0x011F;
+ t['gcaron'] = 0x01E7;
+ t['gcedilla'] = 0x0123;
+ t['gcircle'] = 0x24D6;
+ t['gcircumflex'] = 0x011D;
+ t['gcommaaccent'] = 0x0123;
+ t['gdot'] = 0x0121;
+ t['gdotaccent'] = 0x0121;
+ t['gecyrillic'] = 0x0433;
+ t['gehiragana'] = 0x3052;
+ t['gekatakana'] = 0x30B2;
+ t['geometricallyequal'] = 0x2251;
+ t['gereshaccenthebrew'] = 0x059C;
+ t['gereshhebrew'] = 0x05F3;
+ t['gereshmuqdamhebrew'] = 0x059D;
+ t['germandbls'] = 0x00DF;
+ t['gershayimaccenthebrew'] = 0x059E;
+ t['gershayimhebrew'] = 0x05F4;
+ t['getamark'] = 0x3013;
+ t['ghabengali'] = 0x0998;
+ t['ghadarmenian'] = 0x0572;
+ t['ghadeva'] = 0x0918;
+ t['ghagujarati'] = 0x0A98;
+ t['ghagurmukhi'] = 0x0A18;
+ t['ghainarabic'] = 0x063A;
+ t['ghainfinalarabic'] = 0xFECE;
+ t['ghaininitialarabic'] = 0xFECF;
+ t['ghainmedialarabic'] = 0xFED0;
+ t['ghemiddlehookcyrillic'] = 0x0495;
+ t['ghestrokecyrillic'] = 0x0493;
+ t['gheupturncyrillic'] = 0x0491;
+ t['ghhadeva'] = 0x095A;
+ t['ghhagurmukhi'] = 0x0A5A;
+ t['ghook'] = 0x0260;
+ t['ghzsquare'] = 0x3393;
+ t['gihiragana'] = 0x304E;
+ t['gikatakana'] = 0x30AE;
+ t['gimarmenian'] = 0x0563;
+ t['gimel'] = 0x05D2;
+ t['gimeldagesh'] = 0xFB32;
+ t['gimeldageshhebrew'] = 0xFB32;
+ t['gimelhebrew'] = 0x05D2;
+ t['gjecyrillic'] = 0x0453;
+ t['glottalinvertedstroke'] = 0x01BE;
+ t['glottalstop'] = 0x0294;
+ t['glottalstopinverted'] = 0x0296;
+ t['glottalstopmod'] = 0x02C0;
+ t['glottalstopreversed'] = 0x0295;
+ t['glottalstopreversedmod'] = 0x02C1;
+ t['glottalstopreversedsuperior'] = 0x02E4;
+ t['glottalstopstroke'] = 0x02A1;
+ t['glottalstopstrokereversed'] = 0x02A2;
+ t['gmacron'] = 0x1E21;
+ t['gmonospace'] = 0xFF47;
+ t['gohiragana'] = 0x3054;
+ t['gokatakana'] = 0x30B4;
+ t['gparen'] = 0x24A2;
+ t['gpasquare'] = 0x33AC;
+ t['gradient'] = 0x2207;
+ t['grave'] = 0x0060;
+ t['gravebelowcmb'] = 0x0316;
+ t['gravecmb'] = 0x0300;
+ t['gravecomb'] = 0x0300;
+ t['gravedeva'] = 0x0953;
+ t['gravelowmod'] = 0x02CE;
+ t['gravemonospace'] = 0xFF40;
+ t['gravetonecmb'] = 0x0340;
+ t['greater'] = 0x003E;
+ t['greaterequal'] = 0x2265;
+ t['greaterequalorless'] = 0x22DB;
+ t['greatermonospace'] = 0xFF1E;
+ t['greaterorequivalent'] = 0x2273;
+ t['greaterorless'] = 0x2277;
+ t['greateroverequal'] = 0x2267;
+ t['greatersmall'] = 0xFE65;
+ t['gscript'] = 0x0261;
+ t['gstroke'] = 0x01E5;
+ t['guhiragana'] = 0x3050;
+ t['guillemotleft'] = 0x00AB;
+ t['guillemotright'] = 0x00BB;
+ t['guilsinglleft'] = 0x2039;
+ t['guilsinglright'] = 0x203A;
+ t['gukatakana'] = 0x30B0;
+ t['guramusquare'] = 0x3318;
+ t['gysquare'] = 0x33C9;
+ t['h'] = 0x0068;
+ t['haabkhasiancyrillic'] = 0x04A9;
+ t['haaltonearabic'] = 0x06C1;
+ t['habengali'] = 0x09B9;
+ t['hadescendercyrillic'] = 0x04B3;
+ t['hadeva'] = 0x0939;
+ t['hagujarati'] = 0x0AB9;
+ t['hagurmukhi'] = 0x0A39;
+ t['haharabic'] = 0x062D;
+ t['hahfinalarabic'] = 0xFEA2;
+ t['hahinitialarabic'] = 0xFEA3;
+ t['hahiragana'] = 0x306F;
+ t['hahmedialarabic'] = 0xFEA4;
+ t['haitusquare'] = 0x332A;
+ t['hakatakana'] = 0x30CF;
+ t['hakatakanahalfwidth'] = 0xFF8A;
+ t['halantgurmukhi'] = 0x0A4D;
+ t['hamzaarabic'] = 0x0621;
+ t['hamzalowarabic'] = 0x0621;
+ t['hangulfiller'] = 0x3164;
+ t['hardsigncyrillic'] = 0x044A;
+ t['harpoonleftbarbup'] = 0x21BC;
+ t['harpoonrightbarbup'] = 0x21C0;
+ t['hasquare'] = 0x33CA;
+ t['hatafpatah'] = 0x05B2;
+ t['hatafpatah16'] = 0x05B2;
+ t['hatafpatah23'] = 0x05B2;
+ t['hatafpatah2f'] = 0x05B2;
+ t['hatafpatahhebrew'] = 0x05B2;
+ t['hatafpatahnarrowhebrew'] = 0x05B2;
+ t['hatafpatahquarterhebrew'] = 0x05B2;
+ t['hatafpatahwidehebrew'] = 0x05B2;
+ t['hatafqamats'] = 0x05B3;
+ t['hatafqamats1b'] = 0x05B3;
+ t['hatafqamats28'] = 0x05B3;
+ t['hatafqamats34'] = 0x05B3;
+ t['hatafqamatshebrew'] = 0x05B3;
+ t['hatafqamatsnarrowhebrew'] = 0x05B3;
+ t['hatafqamatsquarterhebrew'] = 0x05B3;
+ t['hatafqamatswidehebrew'] = 0x05B3;
+ t['hatafsegol'] = 0x05B1;
+ t['hatafsegol17'] = 0x05B1;
+ t['hatafsegol24'] = 0x05B1;
+ t['hatafsegol30'] = 0x05B1;
+ t['hatafsegolhebrew'] = 0x05B1;
+ t['hatafsegolnarrowhebrew'] = 0x05B1;
+ t['hatafsegolquarterhebrew'] = 0x05B1;
+ t['hatafsegolwidehebrew'] = 0x05B1;
+ t['hbar'] = 0x0127;
+ t['hbopomofo'] = 0x310F;
+ t['hbrevebelow'] = 0x1E2B;
+ t['hcedilla'] = 0x1E29;
+ t['hcircle'] = 0x24D7;
+ t['hcircumflex'] = 0x0125;
+ t['hdieresis'] = 0x1E27;
+ t['hdotaccent'] = 0x1E23;
+ t['hdotbelow'] = 0x1E25;
+ t['he'] = 0x05D4;
+ t['heart'] = 0x2665;
+ t['heartsuitblack'] = 0x2665;
+ t['heartsuitwhite'] = 0x2661;
+ t['hedagesh'] = 0xFB34;
+ t['hedageshhebrew'] = 0xFB34;
+ t['hehaltonearabic'] = 0x06C1;
+ t['heharabic'] = 0x0647;
+ t['hehebrew'] = 0x05D4;
+ t['hehfinalaltonearabic'] = 0xFBA7;
+ t['hehfinalalttwoarabic'] = 0xFEEA;
+ t['hehfinalarabic'] = 0xFEEA;
+ t['hehhamzaabovefinalarabic'] = 0xFBA5;
+ t['hehhamzaaboveisolatedarabic'] = 0xFBA4;
+ t['hehinitialaltonearabic'] = 0xFBA8;
+ t['hehinitialarabic'] = 0xFEEB;
+ t['hehiragana'] = 0x3078;
+ t['hehmedialaltonearabic'] = 0xFBA9;
+ t['hehmedialarabic'] = 0xFEEC;
+ t['heiseierasquare'] = 0x337B;
+ t['hekatakana'] = 0x30D8;
+ t['hekatakanahalfwidth'] = 0xFF8D;
+ t['hekutaarusquare'] = 0x3336;
+ t['henghook'] = 0x0267;
+ t['herutusquare'] = 0x3339;
+ t['het'] = 0x05D7;
+ t['hethebrew'] = 0x05D7;
+ t['hhook'] = 0x0266;
+ t['hhooksuperior'] = 0x02B1;
+ t['hieuhacirclekorean'] = 0x327B;
+ t['hieuhaparenkorean'] = 0x321B;
+ t['hieuhcirclekorean'] = 0x326D;
+ t['hieuhkorean'] = 0x314E;
+ t['hieuhparenkorean'] = 0x320D;
+ t['hihiragana'] = 0x3072;
+ t['hikatakana'] = 0x30D2;
+ t['hikatakanahalfwidth'] = 0xFF8B;
+ t['hiriq'] = 0x05B4;
+ t['hiriq14'] = 0x05B4;
+ t['hiriq21'] = 0x05B4;
+ t['hiriq2d'] = 0x05B4;
+ t['hiriqhebrew'] = 0x05B4;
+ t['hiriqnarrowhebrew'] = 0x05B4;
+ t['hiriqquarterhebrew'] = 0x05B4;
+ t['hiriqwidehebrew'] = 0x05B4;
+ t['hlinebelow'] = 0x1E96;
+ t['hmonospace'] = 0xFF48;
+ t['hoarmenian'] = 0x0570;
+ t['hohipthai'] = 0x0E2B;
+ t['hohiragana'] = 0x307B;
+ t['hokatakana'] = 0x30DB;
+ t['hokatakanahalfwidth'] = 0xFF8E;
+ t['holam'] = 0x05B9;
+ t['holam19'] = 0x05B9;
+ t['holam26'] = 0x05B9;
+ t['holam32'] = 0x05B9;
+ t['holamhebrew'] = 0x05B9;
+ t['holamnarrowhebrew'] = 0x05B9;
+ t['holamquarterhebrew'] = 0x05B9;
+ t['holamwidehebrew'] = 0x05B9;
+ t['honokhukthai'] = 0x0E2E;
+ t['hookabovecomb'] = 0x0309;
+ t['hookcmb'] = 0x0309;
+ t['hookpalatalizedbelowcmb'] = 0x0321;
+ t['hookretroflexbelowcmb'] = 0x0322;
+ t['hoonsquare'] = 0x3342;
+ t['horicoptic'] = 0x03E9;
+ t['horizontalbar'] = 0x2015;
+ t['horncmb'] = 0x031B;
+ t['hotsprings'] = 0x2668;
+ t['house'] = 0x2302;
+ t['hparen'] = 0x24A3;
+ t['hsuperior'] = 0x02B0;
+ t['hturned'] = 0x0265;
+ t['huhiragana'] = 0x3075;
+ t['huiitosquare'] = 0x3333;
+ t['hukatakana'] = 0x30D5;
+ t['hukatakanahalfwidth'] = 0xFF8C;
+ t['hungarumlaut'] = 0x02DD;
+ t['hungarumlautcmb'] = 0x030B;
+ t['hv'] = 0x0195;
+ t['hyphen'] = 0x002D;
+ t['hypheninferior'] = 0xF6E5;
+ t['hyphenmonospace'] = 0xFF0D;
+ t['hyphensmall'] = 0xFE63;
+ t['hyphensuperior'] = 0xF6E6;
+ t['hyphentwo'] = 0x2010;
+ t['i'] = 0x0069;
+ t['iacute'] = 0x00ED;
+ t['iacyrillic'] = 0x044F;
+ t['ibengali'] = 0x0987;
+ t['ibopomofo'] = 0x3127;
+ t['ibreve'] = 0x012D;
+ t['icaron'] = 0x01D0;
+ t['icircle'] = 0x24D8;
+ t['icircumflex'] = 0x00EE;
+ t['icyrillic'] = 0x0456;
+ t['idblgrave'] = 0x0209;
+ t['ideographearthcircle'] = 0x328F;
+ t['ideographfirecircle'] = 0x328B;
+ t['ideographicallianceparen'] = 0x323F;
+ t['ideographiccallparen'] = 0x323A;
+ t['ideographiccentrecircle'] = 0x32A5;
+ t['ideographicclose'] = 0x3006;
+ t['ideographiccomma'] = 0x3001;
+ t['ideographiccommaleft'] = 0xFF64;
+ t['ideographiccongratulationparen'] = 0x3237;
+ t['ideographiccorrectcircle'] = 0x32A3;
+ t['ideographicearthparen'] = 0x322F;
+ t['ideographicenterpriseparen'] = 0x323D;
+ t['ideographicexcellentcircle'] = 0x329D;
+ t['ideographicfestivalparen'] = 0x3240;
+ t['ideographicfinancialcircle'] = 0x3296;
+ t['ideographicfinancialparen'] = 0x3236;
+ t['ideographicfireparen'] = 0x322B;
+ t['ideographichaveparen'] = 0x3232;
+ t['ideographichighcircle'] = 0x32A4;
+ t['ideographiciterationmark'] = 0x3005;
+ t['ideographiclaborcircle'] = 0x3298;
+ t['ideographiclaborparen'] = 0x3238;
+ t['ideographicleftcircle'] = 0x32A7;
+ t['ideographiclowcircle'] = 0x32A6;
+ t['ideographicmedicinecircle'] = 0x32A9;
+ t['ideographicmetalparen'] = 0x322E;
+ t['ideographicmoonparen'] = 0x322A;
+ t['ideographicnameparen'] = 0x3234;
+ t['ideographicperiod'] = 0x3002;
+ t['ideographicprintcircle'] = 0x329E;
+ t['ideographicreachparen'] = 0x3243;
+ t['ideographicrepresentparen'] = 0x3239;
+ t['ideographicresourceparen'] = 0x323E;
+ t['ideographicrightcircle'] = 0x32A8;
+ t['ideographicsecretcircle'] = 0x3299;
+ t['ideographicselfparen'] = 0x3242;
+ t['ideographicsocietyparen'] = 0x3233;
+ t['ideographicspace'] = 0x3000;
+ t['ideographicspecialparen'] = 0x3235;
+ t['ideographicstockparen'] = 0x3231;
+ t['ideographicstudyparen'] = 0x323B;
+ t['ideographicsunparen'] = 0x3230;
+ t['ideographicsuperviseparen'] = 0x323C;
+ t['ideographicwaterparen'] = 0x322C;
+ t['ideographicwoodparen'] = 0x322D;
+ t['ideographiczero'] = 0x3007;
+ t['ideographmetalcircle'] = 0x328E;
+ t['ideographmooncircle'] = 0x328A;
+ t['ideographnamecircle'] = 0x3294;
+ t['ideographsuncircle'] = 0x3290;
+ t['ideographwatercircle'] = 0x328C;
+ t['ideographwoodcircle'] = 0x328D;
+ t['ideva'] = 0x0907;
+ t['idieresis'] = 0x00EF;
+ t['idieresisacute'] = 0x1E2F;
+ t['idieresiscyrillic'] = 0x04E5;
+ t['idotbelow'] = 0x1ECB;
+ t['iebrevecyrillic'] = 0x04D7;
+ t['iecyrillic'] = 0x0435;
+ t['ieungacirclekorean'] = 0x3275;
+ t['ieungaparenkorean'] = 0x3215;
+ t['ieungcirclekorean'] = 0x3267;
+ t['ieungkorean'] = 0x3147;
+ t['ieungparenkorean'] = 0x3207;
+ t['igrave'] = 0x00EC;
+ t['igujarati'] = 0x0A87;
+ t['igurmukhi'] = 0x0A07;
+ t['ihiragana'] = 0x3044;
+ t['ihookabove'] = 0x1EC9;
+ t['iibengali'] = 0x0988;
+ t['iicyrillic'] = 0x0438;
+ t['iideva'] = 0x0908;
+ t['iigujarati'] = 0x0A88;
+ t['iigurmukhi'] = 0x0A08;
+ t['iimatragurmukhi'] = 0x0A40;
+ t['iinvertedbreve'] = 0x020B;
+ t['iishortcyrillic'] = 0x0439;
+ t['iivowelsignbengali'] = 0x09C0;
+ t['iivowelsigndeva'] = 0x0940;
+ t['iivowelsigngujarati'] = 0x0AC0;
+ t['ij'] = 0x0133;
+ t['ikatakana'] = 0x30A4;
+ t['ikatakanahalfwidth'] = 0xFF72;
+ t['ikorean'] = 0x3163;
+ t['ilde'] = 0x02DC;
+ t['iluyhebrew'] = 0x05AC;
+ t['imacron'] = 0x012B;
+ t['imacroncyrillic'] = 0x04E3;
+ t['imageorapproximatelyequal'] = 0x2253;
+ t['imatragurmukhi'] = 0x0A3F;
+ t['imonospace'] = 0xFF49;
+ t['increment'] = 0x2206;
+ t['infinity'] = 0x221E;
+ t['iniarmenian'] = 0x056B;
+ t['integral'] = 0x222B;
+ t['integralbottom'] = 0x2321;
+ t['integralbt'] = 0x2321;
+ t['integralex'] = 0xF8F5;
+ t['integraltop'] = 0x2320;
+ t['integraltp'] = 0x2320;
+ t['intersection'] = 0x2229;
+ t['intisquare'] = 0x3305;
+ t['invbullet'] = 0x25D8;
+ t['invcircle'] = 0x25D9;
+ t['invsmileface'] = 0x263B;
+ t['iocyrillic'] = 0x0451;
+ t['iogonek'] = 0x012F;
+ t['iota'] = 0x03B9;
+ t['iotadieresis'] = 0x03CA;
+ t['iotadieresistonos'] = 0x0390;
+ t['iotalatin'] = 0x0269;
+ t['iotatonos'] = 0x03AF;
+ t['iparen'] = 0x24A4;
+ t['irigurmukhi'] = 0x0A72;
+ t['ismallhiragana'] = 0x3043;
+ t['ismallkatakana'] = 0x30A3;
+ t['ismallkatakanahalfwidth'] = 0xFF68;
+ t['issharbengali'] = 0x09FA;
+ t['istroke'] = 0x0268;
+ t['isuperior'] = 0xF6ED;
+ t['iterationhiragana'] = 0x309D;
+ t['iterationkatakana'] = 0x30FD;
+ t['itilde'] = 0x0129;
+ t['itildebelow'] = 0x1E2D;
+ t['iubopomofo'] = 0x3129;
+ t['iucyrillic'] = 0x044E;
+ t['ivowelsignbengali'] = 0x09BF;
+ t['ivowelsigndeva'] = 0x093F;
+ t['ivowelsigngujarati'] = 0x0ABF;
+ t['izhitsacyrillic'] = 0x0475;
+ t['izhitsadblgravecyrillic'] = 0x0477;
+ t['j'] = 0x006A;
+ t['jaarmenian'] = 0x0571;
+ t['jabengali'] = 0x099C;
+ t['jadeva'] = 0x091C;
+ t['jagujarati'] = 0x0A9C;
+ t['jagurmukhi'] = 0x0A1C;
+ t['jbopomofo'] = 0x3110;
+ t['jcaron'] = 0x01F0;
+ t['jcircle'] = 0x24D9;
+ t['jcircumflex'] = 0x0135;
+ t['jcrossedtail'] = 0x029D;
+ t['jdotlessstroke'] = 0x025F;
+ t['jecyrillic'] = 0x0458;
+ t['jeemarabic'] = 0x062C;
+ t['jeemfinalarabic'] = 0xFE9E;
+ t['jeeminitialarabic'] = 0xFE9F;
+ t['jeemmedialarabic'] = 0xFEA0;
+ t['jeharabic'] = 0x0698;
+ t['jehfinalarabic'] = 0xFB8B;
+ t['jhabengali'] = 0x099D;
+ t['jhadeva'] = 0x091D;
+ t['jhagujarati'] = 0x0A9D;
+ t['jhagurmukhi'] = 0x0A1D;
+ t['jheharmenian'] = 0x057B;
+ t['jis'] = 0x3004;
+ t['jmonospace'] = 0xFF4A;
+ t['jparen'] = 0x24A5;
+ t['jsuperior'] = 0x02B2;
+ t['k'] = 0x006B;
+ t['kabashkircyrillic'] = 0x04A1;
+ t['kabengali'] = 0x0995;
+ t['kacute'] = 0x1E31;
+ t['kacyrillic'] = 0x043A;
+ t['kadescendercyrillic'] = 0x049B;
+ t['kadeva'] = 0x0915;
+ t['kaf'] = 0x05DB;
+ t['kafarabic'] = 0x0643;
+ t['kafdagesh'] = 0xFB3B;
+ t['kafdageshhebrew'] = 0xFB3B;
+ t['kaffinalarabic'] = 0xFEDA;
+ t['kafhebrew'] = 0x05DB;
+ t['kafinitialarabic'] = 0xFEDB;
+ t['kafmedialarabic'] = 0xFEDC;
+ t['kafrafehebrew'] = 0xFB4D;
+ t['kagujarati'] = 0x0A95;
+ t['kagurmukhi'] = 0x0A15;
+ t['kahiragana'] = 0x304B;
+ t['kahookcyrillic'] = 0x04C4;
+ t['kakatakana'] = 0x30AB;
+ t['kakatakanahalfwidth'] = 0xFF76;
+ t['kappa'] = 0x03BA;
+ t['kappasymbolgreek'] = 0x03F0;
+ t['kapyeounmieumkorean'] = 0x3171;
+ t['kapyeounphieuphkorean'] = 0x3184;
+ t['kapyeounpieupkorean'] = 0x3178;
+ t['kapyeounssangpieupkorean'] = 0x3179;
+ t['karoriisquare'] = 0x330D;
+ t['kashidaautoarabic'] = 0x0640;
+ t['kashidaautonosidebearingarabic'] = 0x0640;
+ t['kasmallkatakana'] = 0x30F5;
+ t['kasquare'] = 0x3384;
+ t['kasraarabic'] = 0x0650;
+ t['kasratanarabic'] = 0x064D;
+ t['kastrokecyrillic'] = 0x049F;
+ t['katahiraprolongmarkhalfwidth'] = 0xFF70;
+ t['kaverticalstrokecyrillic'] = 0x049D;
+ t['kbopomofo'] = 0x310E;
+ t['kcalsquare'] = 0x3389;
+ t['kcaron'] = 0x01E9;
+ t['kcedilla'] = 0x0137;
+ t['kcircle'] = 0x24DA;
+ t['kcommaaccent'] = 0x0137;
+ t['kdotbelow'] = 0x1E33;
+ t['keharmenian'] = 0x0584;
+ t['kehiragana'] = 0x3051;
+ t['kekatakana'] = 0x30B1;
+ t['kekatakanahalfwidth'] = 0xFF79;
+ t['kenarmenian'] = 0x056F;
+ t['kesmallkatakana'] = 0x30F6;
+ t['kgreenlandic'] = 0x0138;
+ t['khabengali'] = 0x0996;
+ t['khacyrillic'] = 0x0445;
+ t['khadeva'] = 0x0916;
+ t['khagujarati'] = 0x0A96;
+ t['khagurmukhi'] = 0x0A16;
+ t['khaharabic'] = 0x062E;
+ t['khahfinalarabic'] = 0xFEA6;
+ t['khahinitialarabic'] = 0xFEA7;
+ t['khahmedialarabic'] = 0xFEA8;
+ t['kheicoptic'] = 0x03E7;
+ t['khhadeva'] = 0x0959;
+ t['khhagurmukhi'] = 0x0A59;
+ t['khieukhacirclekorean'] = 0x3278;
+ t['khieukhaparenkorean'] = 0x3218;
+ t['khieukhcirclekorean'] = 0x326A;
+ t['khieukhkorean'] = 0x314B;
+ t['khieukhparenkorean'] = 0x320A;
+ t['khokhaithai'] = 0x0E02;
+ t['khokhonthai'] = 0x0E05;
+ t['khokhuatthai'] = 0x0E03;
+ t['khokhwaithai'] = 0x0E04;
+ t['khomutthai'] = 0x0E5B;
+ t['khook'] = 0x0199;
+ t['khorakhangthai'] = 0x0E06;
+ t['khzsquare'] = 0x3391;
+ t['kihiragana'] = 0x304D;
+ t['kikatakana'] = 0x30AD;
+ t['kikatakanahalfwidth'] = 0xFF77;
+ t['kiroguramusquare'] = 0x3315;
+ t['kiromeetorusquare'] = 0x3316;
+ t['kirosquare'] = 0x3314;
+ t['kiyeokacirclekorean'] = 0x326E;
+ t['kiyeokaparenkorean'] = 0x320E;
+ t['kiyeokcirclekorean'] = 0x3260;
+ t['kiyeokkorean'] = 0x3131;
+ t['kiyeokparenkorean'] = 0x3200;
+ t['kiyeoksioskorean'] = 0x3133;
+ t['kjecyrillic'] = 0x045C;
+ t['klinebelow'] = 0x1E35;
+ t['klsquare'] = 0x3398;
+ t['kmcubedsquare'] = 0x33A6;
+ t['kmonospace'] = 0xFF4B;
+ t['kmsquaredsquare'] = 0x33A2;
+ t['kohiragana'] = 0x3053;
+ t['kohmsquare'] = 0x33C0;
+ t['kokaithai'] = 0x0E01;
+ t['kokatakana'] = 0x30B3;
+ t['kokatakanahalfwidth'] = 0xFF7A;
+ t['kooposquare'] = 0x331E;
+ t['koppacyrillic'] = 0x0481;
+ t['koreanstandardsymbol'] = 0x327F;
+ t['koroniscmb'] = 0x0343;
+ t['kparen'] = 0x24A6;
+ t['kpasquare'] = 0x33AA;
+ t['ksicyrillic'] = 0x046F;
+ t['ktsquare'] = 0x33CF;
+ t['kturned'] = 0x029E;
+ t['kuhiragana'] = 0x304F;
+ t['kukatakana'] = 0x30AF;
+ t['kukatakanahalfwidth'] = 0xFF78;
+ t['kvsquare'] = 0x33B8;
+ t['kwsquare'] = 0x33BE;
+ t['l'] = 0x006C;
+ t['labengali'] = 0x09B2;
+ t['lacute'] = 0x013A;
+ t['ladeva'] = 0x0932;
+ t['lagujarati'] = 0x0AB2;
+ t['lagurmukhi'] = 0x0A32;
+ t['lakkhangyaothai'] = 0x0E45;
+ t['lamaleffinalarabic'] = 0xFEFC;
+ t['lamalefhamzaabovefinalarabic'] = 0xFEF8;
+ t['lamalefhamzaaboveisolatedarabic'] = 0xFEF7;
+ t['lamalefhamzabelowfinalarabic'] = 0xFEFA;
+ t['lamalefhamzabelowisolatedarabic'] = 0xFEF9;
+ t['lamalefisolatedarabic'] = 0xFEFB;
+ t['lamalefmaddaabovefinalarabic'] = 0xFEF6;
+ t['lamalefmaddaaboveisolatedarabic'] = 0xFEF5;
+ t['lamarabic'] = 0x0644;
+ t['lambda'] = 0x03BB;
+ t['lambdastroke'] = 0x019B;
+ t['lamed'] = 0x05DC;
+ t['lameddagesh'] = 0xFB3C;
+ t['lameddageshhebrew'] = 0xFB3C;
+ t['lamedhebrew'] = 0x05DC;
+ t['lamfinalarabic'] = 0xFEDE;
+ t['lamhahinitialarabic'] = 0xFCCA;
+ t['laminitialarabic'] = 0xFEDF;
+ t['lamjeeminitialarabic'] = 0xFCC9;
+ t['lamkhahinitialarabic'] = 0xFCCB;
+ t['lamlamhehisolatedarabic'] = 0xFDF2;
+ t['lammedialarabic'] = 0xFEE0;
+ t['lammeemhahinitialarabic'] = 0xFD88;
+ t['lammeeminitialarabic'] = 0xFCCC;
+ t['largecircle'] = 0x25EF;
+ t['lbar'] = 0x019A;
+ t['lbelt'] = 0x026C;
+ t['lbopomofo'] = 0x310C;
+ t['lcaron'] = 0x013E;
+ t['lcedilla'] = 0x013C;
+ t['lcircle'] = 0x24DB;
+ t['lcircumflexbelow'] = 0x1E3D;
+ t['lcommaaccent'] = 0x013C;
+ t['ldot'] = 0x0140;
+ t['ldotaccent'] = 0x0140;
+ t['ldotbelow'] = 0x1E37;
+ t['ldotbelowmacron'] = 0x1E39;
+ t['leftangleabovecmb'] = 0x031A;
+ t['lefttackbelowcmb'] = 0x0318;
+ t['less'] = 0x003C;
+ t['lessequal'] = 0x2264;
+ t['lessequalorgreater'] = 0x22DA;
+ t['lessmonospace'] = 0xFF1C;
+ t['lessorequivalent'] = 0x2272;
+ t['lessorgreater'] = 0x2276;
+ t['lessoverequal'] = 0x2266;
+ t['lesssmall'] = 0xFE64;
+ t['lezh'] = 0x026E;
+ t['lfblock'] = 0x258C;
+ t['lhookretroflex'] = 0x026D;
+ t['lira'] = 0x20A4;
+ t['liwnarmenian'] = 0x056C;
+ t['lj'] = 0x01C9;
+ t['ljecyrillic'] = 0x0459;
+ t['ll'] = 0xF6C0;
+ t['lladeva'] = 0x0933;
+ t['llagujarati'] = 0x0AB3;
+ t['llinebelow'] = 0x1E3B;
+ t['llladeva'] = 0x0934;
+ t['llvocalicbengali'] = 0x09E1;
+ t['llvocalicdeva'] = 0x0961;
+ t['llvocalicvowelsignbengali'] = 0x09E3;
+ t['llvocalicvowelsigndeva'] = 0x0963;
+ t['lmiddletilde'] = 0x026B;
+ t['lmonospace'] = 0xFF4C;
+ t['lmsquare'] = 0x33D0;
+ t['lochulathai'] = 0x0E2C;
+ t['logicaland'] = 0x2227;
+ t['logicalnot'] = 0x00AC;
+ t['logicalnotreversed'] = 0x2310;
+ t['logicalor'] = 0x2228;
+ t['lolingthai'] = 0x0E25;
+ t['longs'] = 0x017F;
+ t['lowlinecenterline'] = 0xFE4E;
+ t['lowlinecmb'] = 0x0332;
+ t['lowlinedashed'] = 0xFE4D;
+ t['lozenge'] = 0x25CA;
+ t['lparen'] = 0x24A7;
+ t['lslash'] = 0x0142;
+ t['lsquare'] = 0x2113;
+ t['lsuperior'] = 0xF6EE;
+ t['ltshade'] = 0x2591;
+ t['luthai'] = 0x0E26;
+ t['lvocalicbengali'] = 0x098C;
+ t['lvocalicdeva'] = 0x090C;
+ t['lvocalicvowelsignbengali'] = 0x09E2;
+ t['lvocalicvowelsigndeva'] = 0x0962;
+ t['lxsquare'] = 0x33D3;
+ t['m'] = 0x006D;
+ t['mabengali'] = 0x09AE;
+ t['macron'] = 0x00AF;
+ t['macronbelowcmb'] = 0x0331;
+ t['macroncmb'] = 0x0304;
+ t['macronlowmod'] = 0x02CD;
+ t['macronmonospace'] = 0xFFE3;
+ t['macute'] = 0x1E3F;
+ t['madeva'] = 0x092E;
+ t['magujarati'] = 0x0AAE;
+ t['magurmukhi'] = 0x0A2E;
+ t['mahapakhhebrew'] = 0x05A4;
+ t['mahapakhlefthebrew'] = 0x05A4;
+ t['mahiragana'] = 0x307E;
+ t['maichattawalowleftthai'] = 0xF895;
+ t['maichattawalowrightthai'] = 0xF894;
+ t['maichattawathai'] = 0x0E4B;
+ t['maichattawaupperleftthai'] = 0xF893;
+ t['maieklowleftthai'] = 0xF88C;
+ t['maieklowrightthai'] = 0xF88B;
+ t['maiekthai'] = 0x0E48;
+ t['maiekupperleftthai'] = 0xF88A;
+ t['maihanakatleftthai'] = 0xF884;
+ t['maihanakatthai'] = 0x0E31;
+ t['maitaikhuleftthai'] = 0xF889;
+ t['maitaikhuthai'] = 0x0E47;
+ t['maitholowleftthai'] = 0xF88F;
+ t['maitholowrightthai'] = 0xF88E;
+ t['maithothai'] = 0x0E49;
+ t['maithoupperleftthai'] = 0xF88D;
+ t['maitrilowleftthai'] = 0xF892;
+ t['maitrilowrightthai'] = 0xF891;
+ t['maitrithai'] = 0x0E4A;
+ t['maitriupperleftthai'] = 0xF890;
+ t['maiyamokthai'] = 0x0E46;
+ t['makatakana'] = 0x30DE;
+ t['makatakanahalfwidth'] = 0xFF8F;
+ t['male'] = 0x2642;
+ t['mansyonsquare'] = 0x3347;
+ t['maqafhebrew'] = 0x05BE;
+ t['mars'] = 0x2642;
+ t['masoracirclehebrew'] = 0x05AF;
+ t['masquare'] = 0x3383;
+ t['mbopomofo'] = 0x3107;
+ t['mbsquare'] = 0x33D4;
+ t['mcircle'] = 0x24DC;
+ t['mcubedsquare'] = 0x33A5;
+ t['mdotaccent'] = 0x1E41;
+ t['mdotbelow'] = 0x1E43;
+ t['meemarabic'] = 0x0645;
+ t['meemfinalarabic'] = 0xFEE2;
+ t['meeminitialarabic'] = 0xFEE3;
+ t['meemmedialarabic'] = 0xFEE4;
+ t['meemmeeminitialarabic'] = 0xFCD1;
+ t['meemmeemisolatedarabic'] = 0xFC48;
+ t['meetorusquare'] = 0x334D;
+ t['mehiragana'] = 0x3081;
+ t['meizierasquare'] = 0x337E;
+ t['mekatakana'] = 0x30E1;
+ t['mekatakanahalfwidth'] = 0xFF92;
+ t['mem'] = 0x05DE;
+ t['memdagesh'] = 0xFB3E;
+ t['memdageshhebrew'] = 0xFB3E;
+ t['memhebrew'] = 0x05DE;
+ t['menarmenian'] = 0x0574;
+ t['merkhahebrew'] = 0x05A5;
+ t['merkhakefulahebrew'] = 0x05A6;
+ t['merkhakefulalefthebrew'] = 0x05A6;
+ t['merkhalefthebrew'] = 0x05A5;
+ t['mhook'] = 0x0271;
+ t['mhzsquare'] = 0x3392;
+ t['middledotkatakanahalfwidth'] = 0xFF65;
+ t['middot'] = 0x00B7;
+ t['mieumacirclekorean'] = 0x3272;
+ t['mieumaparenkorean'] = 0x3212;
+ t['mieumcirclekorean'] = 0x3264;
+ t['mieumkorean'] = 0x3141;
+ t['mieumpansioskorean'] = 0x3170;
+ t['mieumparenkorean'] = 0x3204;
+ t['mieumpieupkorean'] = 0x316E;
+ t['mieumsioskorean'] = 0x316F;
+ t['mihiragana'] = 0x307F;
+ t['mikatakana'] = 0x30DF;
+ t['mikatakanahalfwidth'] = 0xFF90;
+ t['minus'] = 0x2212;
+ t['minusbelowcmb'] = 0x0320;
+ t['minuscircle'] = 0x2296;
+ t['minusmod'] = 0x02D7;
+ t['minusplus'] = 0x2213;
+ t['minute'] = 0x2032;
+ t['miribaarusquare'] = 0x334A;
+ t['mirisquare'] = 0x3349;
+ t['mlonglegturned'] = 0x0270;
+ t['mlsquare'] = 0x3396;
+ t['mmcubedsquare'] = 0x33A3;
+ t['mmonospace'] = 0xFF4D;
+ t['mmsquaredsquare'] = 0x339F;
+ t['mohiragana'] = 0x3082;
+ t['mohmsquare'] = 0x33C1;
+ t['mokatakana'] = 0x30E2;
+ t['mokatakanahalfwidth'] = 0xFF93;
+ t['molsquare'] = 0x33D6;
+ t['momathai'] = 0x0E21;
+ t['moverssquare'] = 0x33A7;
+ t['moverssquaredsquare'] = 0x33A8;
+ t['mparen'] = 0x24A8;
+ t['mpasquare'] = 0x33AB;
+ t['mssquare'] = 0x33B3;
+ t['msuperior'] = 0xF6EF;
+ t['mturned'] = 0x026F;
+ t['mu'] = 0x00B5;
+ t['mu1'] = 0x00B5;
+ t['muasquare'] = 0x3382;
+ t['muchgreater'] = 0x226B;
+ t['muchless'] = 0x226A;
+ t['mufsquare'] = 0x338C;
+ t['mugreek'] = 0x03BC;
+ t['mugsquare'] = 0x338D;
+ t['muhiragana'] = 0x3080;
+ t['mukatakana'] = 0x30E0;
+ t['mukatakanahalfwidth'] = 0xFF91;
+ t['mulsquare'] = 0x3395;
+ t['multiply'] = 0x00D7;
+ t['mumsquare'] = 0x339B;
+ t['munahhebrew'] = 0x05A3;
+ t['munahlefthebrew'] = 0x05A3;
+ t['musicalnote'] = 0x266A;
+ t['musicalnotedbl'] = 0x266B;
+ t['musicflatsign'] = 0x266D;
+ t['musicsharpsign'] = 0x266F;
+ t['mussquare'] = 0x33B2;
+ t['muvsquare'] = 0x33B6;
+ t['muwsquare'] = 0x33BC;
+ t['mvmegasquare'] = 0x33B9;
+ t['mvsquare'] = 0x33B7;
+ t['mwmegasquare'] = 0x33BF;
+ t['mwsquare'] = 0x33BD;
+ t['n'] = 0x006E;
+ t['nabengali'] = 0x09A8;
+ t['nabla'] = 0x2207;
+ t['nacute'] = 0x0144;
+ t['nadeva'] = 0x0928;
+ t['nagujarati'] = 0x0AA8;
+ t['nagurmukhi'] = 0x0A28;
+ t['nahiragana'] = 0x306A;
+ t['nakatakana'] = 0x30CA;
+ t['nakatakanahalfwidth'] = 0xFF85;
+ t['napostrophe'] = 0x0149;
+ t['nasquare'] = 0x3381;
+ t['nbopomofo'] = 0x310B;
+ t['nbspace'] = 0x00A0;
+ t['ncaron'] = 0x0148;
+ t['ncedilla'] = 0x0146;
+ t['ncircle'] = 0x24DD;
+ t['ncircumflexbelow'] = 0x1E4B;
+ t['ncommaaccent'] = 0x0146;
+ t['ndotaccent'] = 0x1E45;
+ t['ndotbelow'] = 0x1E47;
+ t['nehiragana'] = 0x306D;
+ t['nekatakana'] = 0x30CD;
+ t['nekatakanahalfwidth'] = 0xFF88;
+ t['newsheqelsign'] = 0x20AA;
+ t['nfsquare'] = 0x338B;
+ t['ngabengali'] = 0x0999;
+ t['ngadeva'] = 0x0919;
+ t['ngagujarati'] = 0x0A99;
+ t['ngagurmukhi'] = 0x0A19;
+ t['ngonguthai'] = 0x0E07;
+ t['nhiragana'] = 0x3093;
+ t['nhookleft'] = 0x0272;
+ t['nhookretroflex'] = 0x0273;
+ t['nieunacirclekorean'] = 0x326F;
+ t['nieunaparenkorean'] = 0x320F;
+ t['nieuncieuckorean'] = 0x3135;
+ t['nieuncirclekorean'] = 0x3261;
+ t['nieunhieuhkorean'] = 0x3136;
+ t['nieunkorean'] = 0x3134;
+ t['nieunpansioskorean'] = 0x3168;
+ t['nieunparenkorean'] = 0x3201;
+ t['nieunsioskorean'] = 0x3167;
+ t['nieuntikeutkorean'] = 0x3166;
+ t['nihiragana'] = 0x306B;
+ t['nikatakana'] = 0x30CB;
+ t['nikatakanahalfwidth'] = 0xFF86;
+ t['nikhahitleftthai'] = 0xF899;
+ t['nikhahitthai'] = 0x0E4D;
+ t['nine'] = 0x0039;
+ t['ninearabic'] = 0x0669;
+ t['ninebengali'] = 0x09EF;
+ t['ninecircle'] = 0x2468;
+ t['ninecircleinversesansserif'] = 0x2792;
+ t['ninedeva'] = 0x096F;
+ t['ninegujarati'] = 0x0AEF;
+ t['ninegurmukhi'] = 0x0A6F;
+ t['ninehackarabic'] = 0x0669;
+ t['ninehangzhou'] = 0x3029;
+ t['nineideographicparen'] = 0x3228;
+ t['nineinferior'] = 0x2089;
+ t['ninemonospace'] = 0xFF19;
+ t['nineoldstyle'] = 0xF739;
+ t['nineparen'] = 0x247C;
+ t['nineperiod'] = 0x2490;
+ t['ninepersian'] = 0x06F9;
+ t['nineroman'] = 0x2178;
+ t['ninesuperior'] = 0x2079;
+ t['nineteencircle'] = 0x2472;
+ t['nineteenparen'] = 0x2486;
+ t['nineteenperiod'] = 0x249A;
+ t['ninethai'] = 0x0E59;
+ t['nj'] = 0x01CC;
+ t['njecyrillic'] = 0x045A;
+ t['nkatakana'] = 0x30F3;
+ t['nkatakanahalfwidth'] = 0xFF9D;
+ t['nlegrightlong'] = 0x019E;
+ t['nlinebelow'] = 0x1E49;
+ t['nmonospace'] = 0xFF4E;
+ t['nmsquare'] = 0x339A;
+ t['nnabengali'] = 0x09A3;
+ t['nnadeva'] = 0x0923;
+ t['nnagujarati'] = 0x0AA3;
+ t['nnagurmukhi'] = 0x0A23;
+ t['nnnadeva'] = 0x0929;
+ t['nohiragana'] = 0x306E;
+ t['nokatakana'] = 0x30CE;
+ t['nokatakanahalfwidth'] = 0xFF89;
+ t['nonbreakingspace'] = 0x00A0;
+ t['nonenthai'] = 0x0E13;
+ t['nonuthai'] = 0x0E19;
+ t['noonarabic'] = 0x0646;
+ t['noonfinalarabic'] = 0xFEE6;
+ t['noonghunnaarabic'] = 0x06BA;
+ t['noonghunnafinalarabic'] = 0xFB9F;
+ t['nooninitialarabic'] = 0xFEE7;
+ t['noonjeeminitialarabic'] = 0xFCD2;
+ t['noonjeemisolatedarabic'] = 0xFC4B;
+ t['noonmedialarabic'] = 0xFEE8;
+ t['noonmeeminitialarabic'] = 0xFCD5;
+ t['noonmeemisolatedarabic'] = 0xFC4E;
+ t['noonnoonfinalarabic'] = 0xFC8D;
+ t['notcontains'] = 0x220C;
+ t['notelement'] = 0x2209;
+ t['notelementof'] = 0x2209;
+ t['notequal'] = 0x2260;
+ t['notgreater'] = 0x226F;
+ t['notgreaternorequal'] = 0x2271;
+ t['notgreaternorless'] = 0x2279;
+ t['notidentical'] = 0x2262;
+ t['notless'] = 0x226E;
+ t['notlessnorequal'] = 0x2270;
+ t['notparallel'] = 0x2226;
+ t['notprecedes'] = 0x2280;
+ t['notsubset'] = 0x2284;
+ t['notsucceeds'] = 0x2281;
+ t['notsuperset'] = 0x2285;
+ t['nowarmenian'] = 0x0576;
+ t['nparen'] = 0x24A9;
+ t['nssquare'] = 0x33B1;
+ t['nsuperior'] = 0x207F;
+ t['ntilde'] = 0x00F1;
+ t['nu'] = 0x03BD;
+ t['nuhiragana'] = 0x306C;
+ t['nukatakana'] = 0x30CC;
+ t['nukatakanahalfwidth'] = 0xFF87;
+ t['nuktabengali'] = 0x09BC;
+ t['nuktadeva'] = 0x093C;
+ t['nuktagujarati'] = 0x0ABC;
+ t['nuktagurmukhi'] = 0x0A3C;
+ t['numbersign'] = 0x0023;
+ t['numbersignmonospace'] = 0xFF03;
+ t['numbersignsmall'] = 0xFE5F;
+ t['numeralsigngreek'] = 0x0374;
+ t['numeralsignlowergreek'] = 0x0375;
+ t['numero'] = 0x2116;
+ t['nun'] = 0x05E0;
+ t['nundagesh'] = 0xFB40;
+ t['nundageshhebrew'] = 0xFB40;
+ t['nunhebrew'] = 0x05E0;
+ t['nvsquare'] = 0x33B5;
+ t['nwsquare'] = 0x33BB;
+ t['nyabengali'] = 0x099E;
+ t['nyadeva'] = 0x091E;
+ t['nyagujarati'] = 0x0A9E;
+ t['nyagurmukhi'] = 0x0A1E;
+ t['o'] = 0x006F;
+ t['oacute'] = 0x00F3;
+ t['oangthai'] = 0x0E2D;
+ t['obarred'] = 0x0275;
+ t['obarredcyrillic'] = 0x04E9;
+ t['obarreddieresiscyrillic'] = 0x04EB;
+ t['obengali'] = 0x0993;
+ t['obopomofo'] = 0x311B;
+ t['obreve'] = 0x014F;
+ t['ocandradeva'] = 0x0911;
+ t['ocandragujarati'] = 0x0A91;
+ t['ocandravowelsigndeva'] = 0x0949;
+ t['ocandravowelsigngujarati'] = 0x0AC9;
+ t['ocaron'] = 0x01D2;
+ t['ocircle'] = 0x24DE;
+ t['ocircumflex'] = 0x00F4;
+ t['ocircumflexacute'] = 0x1ED1;
+ t['ocircumflexdotbelow'] = 0x1ED9;
+ t['ocircumflexgrave'] = 0x1ED3;
+ t['ocircumflexhookabove'] = 0x1ED5;
+ t['ocircumflextilde'] = 0x1ED7;
+ t['ocyrillic'] = 0x043E;
+ t['odblacute'] = 0x0151;
+ t['odblgrave'] = 0x020D;
+ t['odeva'] = 0x0913;
+ t['odieresis'] = 0x00F6;
+ t['odieresiscyrillic'] = 0x04E7;
+ t['odotbelow'] = 0x1ECD;
+ t['oe'] = 0x0153;
+ t['oekorean'] = 0x315A;
+ t['ogonek'] = 0x02DB;
+ t['ogonekcmb'] = 0x0328;
+ t['ograve'] = 0x00F2;
+ t['ogujarati'] = 0x0A93;
+ t['oharmenian'] = 0x0585;
+ t['ohiragana'] = 0x304A;
+ t['ohookabove'] = 0x1ECF;
+ t['ohorn'] = 0x01A1;
+ t['ohornacute'] = 0x1EDB;
+ t['ohorndotbelow'] = 0x1EE3;
+ t['ohorngrave'] = 0x1EDD;
+ t['ohornhookabove'] = 0x1EDF;
+ t['ohorntilde'] = 0x1EE1;
+ t['ohungarumlaut'] = 0x0151;
+ t['oi'] = 0x01A3;
+ t['oinvertedbreve'] = 0x020F;
+ t['okatakana'] = 0x30AA;
+ t['okatakanahalfwidth'] = 0xFF75;
+ t['okorean'] = 0x3157;
+ t['olehebrew'] = 0x05AB;
+ t['omacron'] = 0x014D;
+ t['omacronacute'] = 0x1E53;
+ t['omacrongrave'] = 0x1E51;
+ t['omdeva'] = 0x0950;
+ t['omega'] = 0x03C9;
+ t['omega1'] = 0x03D6;
+ t['omegacyrillic'] = 0x0461;
+ t['omegalatinclosed'] = 0x0277;
+ t['omegaroundcyrillic'] = 0x047B;
+ t['omegatitlocyrillic'] = 0x047D;
+ t['omegatonos'] = 0x03CE;
+ t['omgujarati'] = 0x0AD0;
+ t['omicron'] = 0x03BF;
+ t['omicrontonos'] = 0x03CC;
+ t['omonospace'] = 0xFF4F;
+ t['one'] = 0x0031;
+ t['onearabic'] = 0x0661;
+ t['onebengali'] = 0x09E7;
+ t['onecircle'] = 0x2460;
+ t['onecircleinversesansserif'] = 0x278A;
+ t['onedeva'] = 0x0967;
+ t['onedotenleader'] = 0x2024;
+ t['oneeighth'] = 0x215B;
+ t['onefitted'] = 0xF6DC;
+ t['onegujarati'] = 0x0AE7;
+ t['onegurmukhi'] = 0x0A67;
+ t['onehackarabic'] = 0x0661;
+ t['onehalf'] = 0x00BD;
+ t['onehangzhou'] = 0x3021;
+ t['oneideographicparen'] = 0x3220;
+ t['oneinferior'] = 0x2081;
+ t['onemonospace'] = 0xFF11;
+ t['onenumeratorbengali'] = 0x09F4;
+ t['oneoldstyle'] = 0xF731;
+ t['oneparen'] = 0x2474;
+ t['oneperiod'] = 0x2488;
+ t['onepersian'] = 0x06F1;
+ t['onequarter'] = 0x00BC;
+ t['oneroman'] = 0x2170;
+ t['onesuperior'] = 0x00B9;
+ t['onethai'] = 0x0E51;
+ t['onethird'] = 0x2153;
+ t['oogonek'] = 0x01EB;
+ t['oogonekmacron'] = 0x01ED;
+ t['oogurmukhi'] = 0x0A13;
+ t['oomatragurmukhi'] = 0x0A4B;
+ t['oopen'] = 0x0254;
+ t['oparen'] = 0x24AA;
+ t['openbullet'] = 0x25E6;
+ t['option'] = 0x2325;
+ t['ordfeminine'] = 0x00AA;
+ t['ordmasculine'] = 0x00BA;
+ t['orthogonal'] = 0x221F;
+ t['oshortdeva'] = 0x0912;
+ t['oshortvowelsigndeva'] = 0x094A;
+ t['oslash'] = 0x00F8;
+ t['oslashacute'] = 0x01FF;
+ t['osmallhiragana'] = 0x3049;
+ t['osmallkatakana'] = 0x30A9;
+ t['osmallkatakanahalfwidth'] = 0xFF6B;
+ t['ostrokeacute'] = 0x01FF;
+ t['osuperior'] = 0xF6F0;
+ t['otcyrillic'] = 0x047F;
+ t['otilde'] = 0x00F5;
+ t['otildeacute'] = 0x1E4D;
+ t['otildedieresis'] = 0x1E4F;
+ t['oubopomofo'] = 0x3121;
+ t['overline'] = 0x203E;
+ t['overlinecenterline'] = 0xFE4A;
+ t['overlinecmb'] = 0x0305;
+ t['overlinedashed'] = 0xFE49;
+ t['overlinedblwavy'] = 0xFE4C;
+ t['overlinewavy'] = 0xFE4B;
+ t['overscore'] = 0x00AF;
+ t['ovowelsignbengali'] = 0x09CB;
+ t['ovowelsigndeva'] = 0x094B;
+ t['ovowelsigngujarati'] = 0x0ACB;
+ t['p'] = 0x0070;
+ t['paampssquare'] = 0x3380;
+ t['paasentosquare'] = 0x332B;
+ t['pabengali'] = 0x09AA;
+ t['pacute'] = 0x1E55;
+ t['padeva'] = 0x092A;
+ t['pagedown'] = 0x21DF;
+ t['pageup'] = 0x21DE;
+ t['pagujarati'] = 0x0AAA;
+ t['pagurmukhi'] = 0x0A2A;
+ t['pahiragana'] = 0x3071;
+ t['paiyannoithai'] = 0x0E2F;
+ t['pakatakana'] = 0x30D1;
+ t['palatalizationcyrilliccmb'] = 0x0484;
+ t['palochkacyrillic'] = 0x04C0;
+ t['pansioskorean'] = 0x317F;
+ t['paragraph'] = 0x00B6;
+ t['parallel'] = 0x2225;
+ t['parenleft'] = 0x0028;
+ t['parenleftaltonearabic'] = 0xFD3E;
+ t['parenleftbt'] = 0xF8ED;
+ t['parenleftex'] = 0xF8EC;
+ t['parenleftinferior'] = 0x208D;
+ t['parenleftmonospace'] = 0xFF08;
+ t['parenleftsmall'] = 0xFE59;
+ t['parenleftsuperior'] = 0x207D;
+ t['parenlefttp'] = 0xF8EB;
+ t['parenleftvertical'] = 0xFE35;
+ t['parenright'] = 0x0029;
+ t['parenrightaltonearabic'] = 0xFD3F;
+ t['parenrightbt'] = 0xF8F8;
+ t['parenrightex'] = 0xF8F7;
+ t['parenrightinferior'] = 0x208E;
+ t['parenrightmonospace'] = 0xFF09;
+ t['parenrightsmall'] = 0xFE5A;
+ t['parenrightsuperior'] = 0x207E;
+ t['parenrighttp'] = 0xF8F6;
+ t['parenrightvertical'] = 0xFE36;
+ t['partialdiff'] = 0x2202;
+ t['paseqhebrew'] = 0x05C0;
+ t['pashtahebrew'] = 0x0599;
+ t['pasquare'] = 0x33A9;
+ t['patah'] = 0x05B7;
+ t['patah11'] = 0x05B7;
+ t['patah1d'] = 0x05B7;
+ t['patah2a'] = 0x05B7;
+ t['patahhebrew'] = 0x05B7;
+ t['patahnarrowhebrew'] = 0x05B7;
+ t['patahquarterhebrew'] = 0x05B7;
+ t['patahwidehebrew'] = 0x05B7;
+ t['pazerhebrew'] = 0x05A1;
+ t['pbopomofo'] = 0x3106;
+ t['pcircle'] = 0x24DF;
+ t['pdotaccent'] = 0x1E57;
+ t['pe'] = 0x05E4;
+ t['pecyrillic'] = 0x043F;
+ t['pedagesh'] = 0xFB44;
+ t['pedageshhebrew'] = 0xFB44;
+ t['peezisquare'] = 0x333B;
+ t['pefinaldageshhebrew'] = 0xFB43;
+ t['peharabic'] = 0x067E;
+ t['peharmenian'] = 0x057A;
+ t['pehebrew'] = 0x05E4;
+ t['pehfinalarabic'] = 0xFB57;
+ t['pehinitialarabic'] = 0xFB58;
+ t['pehiragana'] = 0x307A;
+ t['pehmedialarabic'] = 0xFB59;
+ t['pekatakana'] = 0x30DA;
+ t['pemiddlehookcyrillic'] = 0x04A7;
+ t['perafehebrew'] = 0xFB4E;
+ t['percent'] = 0x0025;
+ t['percentarabic'] = 0x066A;
+ t['percentmonospace'] = 0xFF05;
+ t['percentsmall'] = 0xFE6A;
+ t['period'] = 0x002E;
+ t['periodarmenian'] = 0x0589;
+ t['periodcentered'] = 0x00B7;
+ t['periodhalfwidth'] = 0xFF61;
+ t['periodinferior'] = 0xF6E7;
+ t['periodmonospace'] = 0xFF0E;
+ t['periodsmall'] = 0xFE52;
+ t['periodsuperior'] = 0xF6E8;
+ t['perispomenigreekcmb'] = 0x0342;
+ t['perpendicular'] = 0x22A5;
+ t['perthousand'] = 0x2030;
+ t['peseta'] = 0x20A7;
+ t['pfsquare'] = 0x338A;
+ t['phabengali'] = 0x09AB;
+ t['phadeva'] = 0x092B;
+ t['phagujarati'] = 0x0AAB;
+ t['phagurmukhi'] = 0x0A2B;
+ t['phi'] = 0x03C6;
+ t['phi1'] = 0x03D5;
+ t['phieuphacirclekorean'] = 0x327A;
+ t['phieuphaparenkorean'] = 0x321A;
+ t['phieuphcirclekorean'] = 0x326C;
+ t['phieuphkorean'] = 0x314D;
+ t['phieuphparenkorean'] = 0x320C;
+ t['philatin'] = 0x0278;
+ t['phinthuthai'] = 0x0E3A;
+ t['phisymbolgreek'] = 0x03D5;
+ t['phook'] = 0x01A5;
+ t['phophanthai'] = 0x0E1E;
+ t['phophungthai'] = 0x0E1C;
+ t['phosamphaothai'] = 0x0E20;
+ t['pi'] = 0x03C0;
+ t['pieupacirclekorean'] = 0x3273;
+ t['pieupaparenkorean'] = 0x3213;
+ t['pieupcieuckorean'] = 0x3176;
+ t['pieupcirclekorean'] = 0x3265;
+ t['pieupkiyeokkorean'] = 0x3172;
+ t['pieupkorean'] = 0x3142;
+ t['pieupparenkorean'] = 0x3205;
+ t['pieupsioskiyeokkorean'] = 0x3174;
+ t['pieupsioskorean'] = 0x3144;
+ t['pieupsiostikeutkorean'] = 0x3175;
+ t['pieupthieuthkorean'] = 0x3177;
+ t['pieuptikeutkorean'] = 0x3173;
+ t['pihiragana'] = 0x3074;
+ t['pikatakana'] = 0x30D4;
+ t['pisymbolgreek'] = 0x03D6;
+ t['piwrarmenian'] = 0x0583;
+ t['plus'] = 0x002B;
+ t['plusbelowcmb'] = 0x031F;
+ t['pluscircle'] = 0x2295;
+ t['plusminus'] = 0x00B1;
+ t['plusmod'] = 0x02D6;
+ t['plusmonospace'] = 0xFF0B;
+ t['plussmall'] = 0xFE62;
+ t['plussuperior'] = 0x207A;
+ t['pmonospace'] = 0xFF50;
+ t['pmsquare'] = 0x33D8;
+ t['pohiragana'] = 0x307D;
+ t['pointingindexdownwhite'] = 0x261F;
+ t['pointingindexleftwhite'] = 0x261C;
+ t['pointingindexrightwhite'] = 0x261E;
+ t['pointingindexupwhite'] = 0x261D;
+ t['pokatakana'] = 0x30DD;
+ t['poplathai'] = 0x0E1B;
+ t['postalmark'] = 0x3012;
+ t['postalmarkface'] = 0x3020;
+ t['pparen'] = 0x24AB;
+ t['precedes'] = 0x227A;
+ t['prescription'] = 0x211E;
+ t['primemod'] = 0x02B9;
+ t['primereversed'] = 0x2035;
+ t['product'] = 0x220F;
+ t['projective'] = 0x2305;
+ t['prolongedkana'] = 0x30FC;
+ t['propellor'] = 0x2318;
+ t['propersubset'] = 0x2282;
+ t['propersuperset'] = 0x2283;
+ t['proportion'] = 0x2237;
+ t['proportional'] = 0x221D;
+ t['psi'] = 0x03C8;
+ t['psicyrillic'] = 0x0471;
+ t['psilipneumatacyrilliccmb'] = 0x0486;
+ t['pssquare'] = 0x33B0;
+ t['puhiragana'] = 0x3077;
+ t['pukatakana'] = 0x30D7;
+ t['pvsquare'] = 0x33B4;
+ t['pwsquare'] = 0x33BA;
+ t['q'] = 0x0071;
+ t['qadeva'] = 0x0958;
+ t['qadmahebrew'] = 0x05A8;
+ t['qafarabic'] = 0x0642;
+ t['qaffinalarabic'] = 0xFED6;
+ t['qafinitialarabic'] = 0xFED7;
+ t['qafmedialarabic'] = 0xFED8;
+ t['qamats'] = 0x05B8;
+ t['qamats10'] = 0x05B8;
+ t['qamats1a'] = 0x05B8;
+ t['qamats1c'] = 0x05B8;
+ t['qamats27'] = 0x05B8;
+ t['qamats29'] = 0x05B8;
+ t['qamats33'] = 0x05B8;
+ t['qamatsde'] = 0x05B8;
+ t['qamatshebrew'] = 0x05B8;
+ t['qamatsnarrowhebrew'] = 0x05B8;
+ t['qamatsqatanhebrew'] = 0x05B8;
+ t['qamatsqatannarrowhebrew'] = 0x05B8;
+ t['qamatsqatanquarterhebrew'] = 0x05B8;
+ t['qamatsqatanwidehebrew'] = 0x05B8;
+ t['qamatsquarterhebrew'] = 0x05B8;
+ t['qamatswidehebrew'] = 0x05B8;
+ t['qarneyparahebrew'] = 0x059F;
+ t['qbopomofo'] = 0x3111;
+ t['qcircle'] = 0x24E0;
+ t['qhook'] = 0x02A0;
+ t['qmonospace'] = 0xFF51;
+ t['qof'] = 0x05E7;
+ t['qofdagesh'] = 0xFB47;
+ t['qofdageshhebrew'] = 0xFB47;
+ t['qofhebrew'] = 0x05E7;
+ t['qparen'] = 0x24AC;
+ t['quarternote'] = 0x2669;
+ t['qubuts'] = 0x05BB;
+ t['qubuts18'] = 0x05BB;
+ t['qubuts25'] = 0x05BB;
+ t['qubuts31'] = 0x05BB;
+ t['qubutshebrew'] = 0x05BB;
+ t['qubutsnarrowhebrew'] = 0x05BB;
+ t['qubutsquarterhebrew'] = 0x05BB;
+ t['qubutswidehebrew'] = 0x05BB;
+ t['question'] = 0x003F;
+ t['questionarabic'] = 0x061F;
+ t['questionarmenian'] = 0x055E;
+ t['questiondown'] = 0x00BF;
+ t['questiondownsmall'] = 0xF7BF;
+ t['questiongreek'] = 0x037E;
+ t['questionmonospace'] = 0xFF1F;
+ t['questionsmall'] = 0xF73F;
+ t['quotedbl'] = 0x0022;
+ t['quotedblbase'] = 0x201E;
+ t['quotedblleft'] = 0x201C;
+ t['quotedblmonospace'] = 0xFF02;
+ t['quotedblprime'] = 0x301E;
+ t['quotedblprimereversed'] = 0x301D;
+ t['quotedblright'] = 0x201D;
+ t['quoteleft'] = 0x2018;
+ t['quoteleftreversed'] = 0x201B;
+ t['quotereversed'] = 0x201B;
+ t['quoteright'] = 0x2019;
+ t['quoterightn'] = 0x0149;
+ t['quotesinglbase'] = 0x201A;
+ t['quotesingle'] = 0x0027;
+ t['quotesinglemonospace'] = 0xFF07;
+ t['r'] = 0x0072;
+ t['raarmenian'] = 0x057C;
+ t['rabengali'] = 0x09B0;
+ t['racute'] = 0x0155;
+ t['radeva'] = 0x0930;
+ t['radical'] = 0x221A;
+ t['radicalex'] = 0xF8E5;
+ t['radoverssquare'] = 0x33AE;
+ t['radoverssquaredsquare'] = 0x33AF;
+ t['radsquare'] = 0x33AD;
+ t['rafe'] = 0x05BF;
+ t['rafehebrew'] = 0x05BF;
+ t['ragujarati'] = 0x0AB0;
+ t['ragurmukhi'] = 0x0A30;
+ t['rahiragana'] = 0x3089;
+ t['rakatakana'] = 0x30E9;
+ t['rakatakanahalfwidth'] = 0xFF97;
+ t['ralowerdiagonalbengali'] = 0x09F1;
+ t['ramiddlediagonalbengali'] = 0x09F0;
+ t['ramshorn'] = 0x0264;
+ t['ratio'] = 0x2236;
+ t['rbopomofo'] = 0x3116;
+ t['rcaron'] = 0x0159;
+ t['rcedilla'] = 0x0157;
+ t['rcircle'] = 0x24E1;
+ t['rcommaaccent'] = 0x0157;
+ t['rdblgrave'] = 0x0211;
+ t['rdotaccent'] = 0x1E59;
+ t['rdotbelow'] = 0x1E5B;
+ t['rdotbelowmacron'] = 0x1E5D;
+ t['referencemark'] = 0x203B;
+ t['reflexsubset'] = 0x2286;
+ t['reflexsuperset'] = 0x2287;
+ t['registered'] = 0x00AE;
+ t['registersans'] = 0xF8E8;
+ t['registerserif'] = 0xF6DA;
+ t['reharabic'] = 0x0631;
+ t['reharmenian'] = 0x0580;
+ t['rehfinalarabic'] = 0xFEAE;
+ t['rehiragana'] = 0x308C;
+ t['rekatakana'] = 0x30EC;
+ t['rekatakanahalfwidth'] = 0xFF9A;
+ t['resh'] = 0x05E8;
+ t['reshdageshhebrew'] = 0xFB48;
+ t['reshhebrew'] = 0x05E8;
+ t['reversedtilde'] = 0x223D;
+ t['reviahebrew'] = 0x0597;
+ t['reviamugrashhebrew'] = 0x0597;
+ t['revlogicalnot'] = 0x2310;
+ t['rfishhook'] = 0x027E;
+ t['rfishhookreversed'] = 0x027F;
+ t['rhabengali'] = 0x09DD;
+ t['rhadeva'] = 0x095D;
+ t['rho'] = 0x03C1;
+ t['rhook'] = 0x027D;
+ t['rhookturned'] = 0x027B;
+ t['rhookturnedsuperior'] = 0x02B5;
+ t['rhosymbolgreek'] = 0x03F1;
+ t['rhotichookmod'] = 0x02DE;
+ t['rieulacirclekorean'] = 0x3271;
+ t['rieulaparenkorean'] = 0x3211;
+ t['rieulcirclekorean'] = 0x3263;
+ t['rieulhieuhkorean'] = 0x3140;
+ t['rieulkiyeokkorean'] = 0x313A;
+ t['rieulkiyeoksioskorean'] = 0x3169;
+ t['rieulkorean'] = 0x3139;
+ t['rieulmieumkorean'] = 0x313B;
+ t['rieulpansioskorean'] = 0x316C;
+ t['rieulparenkorean'] = 0x3203;
+ t['rieulphieuphkorean'] = 0x313F;
+ t['rieulpieupkorean'] = 0x313C;
+ t['rieulpieupsioskorean'] = 0x316B;
+ t['rieulsioskorean'] = 0x313D;
+ t['rieulthieuthkorean'] = 0x313E;
+ t['rieultikeutkorean'] = 0x316A;
+ t['rieulyeorinhieuhkorean'] = 0x316D;
+ t['rightangle'] = 0x221F;
+ t['righttackbelowcmb'] = 0x0319;
+ t['righttriangle'] = 0x22BF;
+ t['rihiragana'] = 0x308A;
+ t['rikatakana'] = 0x30EA;
+ t['rikatakanahalfwidth'] = 0xFF98;
+ t['ring'] = 0x02DA;
+ t['ringbelowcmb'] = 0x0325;
+ t['ringcmb'] = 0x030A;
+ t['ringhalfleft'] = 0x02BF;
+ t['ringhalfleftarmenian'] = 0x0559;
+ t['ringhalfleftbelowcmb'] = 0x031C;
+ t['ringhalfleftcentered'] = 0x02D3;
+ t['ringhalfright'] = 0x02BE;
+ t['ringhalfrightbelowcmb'] = 0x0339;
+ t['ringhalfrightcentered'] = 0x02D2;
+ t['rinvertedbreve'] = 0x0213;
+ t['rittorusquare'] = 0x3351;
+ t['rlinebelow'] = 0x1E5F;
+ t['rlongleg'] = 0x027C;
+ t['rlonglegturned'] = 0x027A;
+ t['rmonospace'] = 0xFF52;
+ t['rohiragana'] = 0x308D;
+ t['rokatakana'] = 0x30ED;
+ t['rokatakanahalfwidth'] = 0xFF9B;
+ t['roruathai'] = 0x0E23;
+ t['rparen'] = 0x24AD;
+ t['rrabengali'] = 0x09DC;
+ t['rradeva'] = 0x0931;
+ t['rragurmukhi'] = 0x0A5C;
+ t['rreharabic'] = 0x0691;
+ t['rrehfinalarabic'] = 0xFB8D;
+ t['rrvocalicbengali'] = 0x09E0;
+ t['rrvocalicdeva'] = 0x0960;
+ t['rrvocalicgujarati'] = 0x0AE0;
+ t['rrvocalicvowelsignbengali'] = 0x09C4;
+ t['rrvocalicvowelsigndeva'] = 0x0944;
+ t['rrvocalicvowelsigngujarati'] = 0x0AC4;
+ t['rsuperior'] = 0xF6F1;
+ t['rtblock'] = 0x2590;
+ t['rturned'] = 0x0279;
+ t['rturnedsuperior'] = 0x02B4;
+ t['ruhiragana'] = 0x308B;
+ t['rukatakana'] = 0x30EB;
+ t['rukatakanahalfwidth'] = 0xFF99;
+ t['rupeemarkbengali'] = 0x09F2;
+ t['rupeesignbengali'] = 0x09F3;
+ t['rupiah'] = 0xF6DD;
+ t['ruthai'] = 0x0E24;
+ t['rvocalicbengali'] = 0x098B;
+ t['rvocalicdeva'] = 0x090B;
+ t['rvocalicgujarati'] = 0x0A8B;
+ t['rvocalicvowelsignbengali'] = 0x09C3;
+ t['rvocalicvowelsigndeva'] = 0x0943;
+ t['rvocalicvowelsigngujarati'] = 0x0AC3;
+ t['s'] = 0x0073;
+ t['sabengali'] = 0x09B8;
+ t['sacute'] = 0x015B;
+ t['sacutedotaccent'] = 0x1E65;
+ t['sadarabic'] = 0x0635;
+ t['sadeva'] = 0x0938;
+ t['sadfinalarabic'] = 0xFEBA;
+ t['sadinitialarabic'] = 0xFEBB;
+ t['sadmedialarabic'] = 0xFEBC;
+ t['sagujarati'] = 0x0AB8;
+ t['sagurmukhi'] = 0x0A38;
+ t['sahiragana'] = 0x3055;
+ t['sakatakana'] = 0x30B5;
+ t['sakatakanahalfwidth'] = 0xFF7B;
+ t['sallallahoualayhewasallamarabic'] = 0xFDFA;
+ t['samekh'] = 0x05E1;
+ t['samekhdagesh'] = 0xFB41;
+ t['samekhdageshhebrew'] = 0xFB41;
+ t['samekhhebrew'] = 0x05E1;
+ t['saraaathai'] = 0x0E32;
+ t['saraaethai'] = 0x0E41;
+ t['saraaimaimalaithai'] = 0x0E44;
+ t['saraaimaimuanthai'] = 0x0E43;
+ t['saraamthai'] = 0x0E33;
+ t['saraathai'] = 0x0E30;
+ t['saraethai'] = 0x0E40;
+ t['saraiileftthai'] = 0xF886;
+ t['saraiithai'] = 0x0E35;
+ t['saraileftthai'] = 0xF885;
+ t['saraithai'] = 0x0E34;
+ t['saraothai'] = 0x0E42;
+ t['saraueeleftthai'] = 0xF888;
+ t['saraueethai'] = 0x0E37;
+ t['saraueleftthai'] = 0xF887;
+ t['sarauethai'] = 0x0E36;
+ t['sarauthai'] = 0x0E38;
+ t['sarauuthai'] = 0x0E39;
+ t['sbopomofo'] = 0x3119;
+ t['scaron'] = 0x0161;
+ t['scarondotaccent'] = 0x1E67;
+ t['scedilla'] = 0x015F;
+ t['schwa'] = 0x0259;
+ t['schwacyrillic'] = 0x04D9;
+ t['schwadieresiscyrillic'] = 0x04DB;
+ t['schwahook'] = 0x025A;
+ t['scircle'] = 0x24E2;
+ t['scircumflex'] = 0x015D;
+ t['scommaaccent'] = 0x0219;
+ t['sdotaccent'] = 0x1E61;
+ t['sdotbelow'] = 0x1E63;
+ t['sdotbelowdotaccent'] = 0x1E69;
+ t['seagullbelowcmb'] = 0x033C;
+ t['second'] = 0x2033;
+ t['secondtonechinese'] = 0x02CA;
+ t['section'] = 0x00A7;
+ t['seenarabic'] = 0x0633;
+ t['seenfinalarabic'] = 0xFEB2;
+ t['seeninitialarabic'] = 0xFEB3;
+ t['seenmedialarabic'] = 0xFEB4;
+ t['segol'] = 0x05B6;
+ t['segol13'] = 0x05B6;
+ t['segol1f'] = 0x05B6;
+ t['segol2c'] = 0x05B6;
+ t['segolhebrew'] = 0x05B6;
+ t['segolnarrowhebrew'] = 0x05B6;
+ t['segolquarterhebrew'] = 0x05B6;
+ t['segoltahebrew'] = 0x0592;
+ t['segolwidehebrew'] = 0x05B6;
+ t['seharmenian'] = 0x057D;
+ t['sehiragana'] = 0x305B;
+ t['sekatakana'] = 0x30BB;
+ t['sekatakanahalfwidth'] = 0xFF7E;
+ t['semicolon'] = 0x003B;
+ t['semicolonarabic'] = 0x061B;
+ t['semicolonmonospace'] = 0xFF1B;
+ t['semicolonsmall'] = 0xFE54;
+ t['semivoicedmarkkana'] = 0x309C;
+ t['semivoicedmarkkanahalfwidth'] = 0xFF9F;
+ t['sentisquare'] = 0x3322;
+ t['sentosquare'] = 0x3323;
+ t['seven'] = 0x0037;
+ t['sevenarabic'] = 0x0667;
+ t['sevenbengali'] = 0x09ED;
+ t['sevencircle'] = 0x2466;
+ t['sevencircleinversesansserif'] = 0x2790;
+ t['sevendeva'] = 0x096D;
+ t['seveneighths'] = 0x215E;
+ t['sevengujarati'] = 0x0AED;
+ t['sevengurmukhi'] = 0x0A6D;
+ t['sevenhackarabic'] = 0x0667;
+ t['sevenhangzhou'] = 0x3027;
+ t['sevenideographicparen'] = 0x3226;
+ t['seveninferior'] = 0x2087;
+ t['sevenmonospace'] = 0xFF17;
+ t['sevenoldstyle'] = 0xF737;
+ t['sevenparen'] = 0x247A;
+ t['sevenperiod'] = 0x248E;
+ t['sevenpersian'] = 0x06F7;
+ t['sevenroman'] = 0x2176;
+ t['sevensuperior'] = 0x2077;
+ t['seventeencircle'] = 0x2470;
+ t['seventeenparen'] = 0x2484;
+ t['seventeenperiod'] = 0x2498;
+ t['seventhai'] = 0x0E57;
+ t['sfthyphen'] = 0x00AD;
+ t['shaarmenian'] = 0x0577;
+ t['shabengali'] = 0x09B6;
+ t['shacyrillic'] = 0x0448;
+ t['shaddaarabic'] = 0x0651;
+ t['shaddadammaarabic'] = 0xFC61;
+ t['shaddadammatanarabic'] = 0xFC5E;
+ t['shaddafathaarabic'] = 0xFC60;
+ t['shaddakasraarabic'] = 0xFC62;
+ t['shaddakasratanarabic'] = 0xFC5F;
+ t['shade'] = 0x2592;
+ t['shadedark'] = 0x2593;
+ t['shadelight'] = 0x2591;
+ t['shademedium'] = 0x2592;
+ t['shadeva'] = 0x0936;
+ t['shagujarati'] = 0x0AB6;
+ t['shagurmukhi'] = 0x0A36;
+ t['shalshelethebrew'] = 0x0593;
+ t['shbopomofo'] = 0x3115;
+ t['shchacyrillic'] = 0x0449;
+ t['sheenarabic'] = 0x0634;
+ t['sheenfinalarabic'] = 0xFEB6;
+ t['sheeninitialarabic'] = 0xFEB7;
+ t['sheenmedialarabic'] = 0xFEB8;
+ t['sheicoptic'] = 0x03E3;
+ t['sheqel'] = 0x20AA;
+ t['sheqelhebrew'] = 0x20AA;
+ t['sheva'] = 0x05B0;
+ t['sheva115'] = 0x05B0;
+ t['sheva15'] = 0x05B0;
+ t['sheva22'] = 0x05B0;
+ t['sheva2e'] = 0x05B0;
+ t['shevahebrew'] = 0x05B0;
+ t['shevanarrowhebrew'] = 0x05B0;
+ t['shevaquarterhebrew'] = 0x05B0;
+ t['shevawidehebrew'] = 0x05B0;
+ t['shhacyrillic'] = 0x04BB;
+ t['shimacoptic'] = 0x03ED;
+ t['shin'] = 0x05E9;
+ t['shindagesh'] = 0xFB49;
+ t['shindageshhebrew'] = 0xFB49;
+ t['shindageshshindot'] = 0xFB2C;
+ t['shindageshshindothebrew'] = 0xFB2C;
+ t['shindageshsindot'] = 0xFB2D;
+ t['shindageshsindothebrew'] = 0xFB2D;
+ t['shindothebrew'] = 0x05C1;
+ t['shinhebrew'] = 0x05E9;
+ t['shinshindot'] = 0xFB2A;
+ t['shinshindothebrew'] = 0xFB2A;
+ t['shinsindot'] = 0xFB2B;
+ t['shinsindothebrew'] = 0xFB2B;
+ t['shook'] = 0x0282;
+ t['sigma'] = 0x03C3;
+ t['sigma1'] = 0x03C2;
+ t['sigmafinal'] = 0x03C2;
+ t['sigmalunatesymbolgreek'] = 0x03F2;
+ t['sihiragana'] = 0x3057;
+ t['sikatakana'] = 0x30B7;
+ t['sikatakanahalfwidth'] = 0xFF7C;
+ t['siluqhebrew'] = 0x05BD;
+ t['siluqlefthebrew'] = 0x05BD;
+ t['similar'] = 0x223C;
+ t['sindothebrew'] = 0x05C2;
+ t['siosacirclekorean'] = 0x3274;
+ t['siosaparenkorean'] = 0x3214;
+ t['sioscieuckorean'] = 0x317E;
+ t['sioscirclekorean'] = 0x3266;
+ t['sioskiyeokkorean'] = 0x317A;
+ t['sioskorean'] = 0x3145;
+ t['siosnieunkorean'] = 0x317B;
+ t['siosparenkorean'] = 0x3206;
+ t['siospieupkorean'] = 0x317D;
+ t['siostikeutkorean'] = 0x317C;
+ t['six'] = 0x0036;
+ t['sixarabic'] = 0x0666;
+ t['sixbengali'] = 0x09EC;
+ t['sixcircle'] = 0x2465;
+ t['sixcircleinversesansserif'] = 0x278F;
+ t['sixdeva'] = 0x096C;
+ t['sixgujarati'] = 0x0AEC;
+ t['sixgurmukhi'] = 0x0A6C;
+ t['sixhackarabic'] = 0x0666;
+ t['sixhangzhou'] = 0x3026;
+ t['sixideographicparen'] = 0x3225;
+ t['sixinferior'] = 0x2086;
+ t['sixmonospace'] = 0xFF16;
+ t['sixoldstyle'] = 0xF736;
+ t['sixparen'] = 0x2479;
+ t['sixperiod'] = 0x248D;
+ t['sixpersian'] = 0x06F6;
+ t['sixroman'] = 0x2175;
+ t['sixsuperior'] = 0x2076;
+ t['sixteencircle'] = 0x246F;
+ t['sixteencurrencydenominatorbengali'] = 0x09F9;
+ t['sixteenparen'] = 0x2483;
+ t['sixteenperiod'] = 0x2497;
+ t['sixthai'] = 0x0E56;
+ t['slash'] = 0x002F;
+ t['slashmonospace'] = 0xFF0F;
+ t['slong'] = 0x017F;
+ t['slongdotaccent'] = 0x1E9B;
+ t['smileface'] = 0x263A;
+ t['smonospace'] = 0xFF53;
+ t['sofpasuqhebrew'] = 0x05C3;
+ t['softhyphen'] = 0x00AD;
+ t['softsigncyrillic'] = 0x044C;
+ t['sohiragana'] = 0x305D;
+ t['sokatakana'] = 0x30BD;
+ t['sokatakanahalfwidth'] = 0xFF7F;
+ t['soliduslongoverlaycmb'] = 0x0338;
+ t['solidusshortoverlaycmb'] = 0x0337;
+ t['sorusithai'] = 0x0E29;
+ t['sosalathai'] = 0x0E28;
+ t['sosothai'] = 0x0E0B;
+ t['sosuathai'] = 0x0E2A;
+ t['space'] = 0x0020;
+ t['spacehackarabic'] = 0x0020;
+ t['spade'] = 0x2660;
+ t['spadesuitblack'] = 0x2660;
+ t['spadesuitwhite'] = 0x2664;
+ t['sparen'] = 0x24AE;
+ t['squarebelowcmb'] = 0x033B;
+ t['squarecc'] = 0x33C4;
+ t['squarecm'] = 0x339D;
+ t['squarediagonalcrosshatchfill'] = 0x25A9;
+ t['squarehorizontalfill'] = 0x25A4;
+ t['squarekg'] = 0x338F;
+ t['squarekm'] = 0x339E;
+ t['squarekmcapital'] = 0x33CE;
+ t['squareln'] = 0x33D1;
+ t['squarelog'] = 0x33D2;
+ t['squaremg'] = 0x338E;
+ t['squaremil'] = 0x33D5;
+ t['squaremm'] = 0x339C;
+ t['squaremsquared'] = 0x33A1;
+ t['squareorthogonalcrosshatchfill'] = 0x25A6;
+ t['squareupperlefttolowerrightfill'] = 0x25A7;
+ t['squareupperrighttolowerleftfill'] = 0x25A8;
+ t['squareverticalfill'] = 0x25A5;
+ t['squarewhitewithsmallblack'] = 0x25A3;
+ t['srsquare'] = 0x33DB;
+ t['ssabengali'] = 0x09B7;
+ t['ssadeva'] = 0x0937;
+ t['ssagujarati'] = 0x0AB7;
+ t['ssangcieuckorean'] = 0x3149;
+ t['ssanghieuhkorean'] = 0x3185;
+ t['ssangieungkorean'] = 0x3180;
+ t['ssangkiyeokkorean'] = 0x3132;
+ t['ssangnieunkorean'] = 0x3165;
+ t['ssangpieupkorean'] = 0x3143;
+ t['ssangsioskorean'] = 0x3146;
+ t['ssangtikeutkorean'] = 0x3138;
+ t['ssuperior'] = 0xF6F2;
+ t['sterling'] = 0x00A3;
+ t['sterlingmonospace'] = 0xFFE1;
+ t['strokelongoverlaycmb'] = 0x0336;
+ t['strokeshortoverlaycmb'] = 0x0335;
+ t['subset'] = 0x2282;
+ t['subsetnotequal'] = 0x228A;
+ t['subsetorequal'] = 0x2286;
+ t['succeeds'] = 0x227B;
+ t['suchthat'] = 0x220B;
+ t['suhiragana'] = 0x3059;
+ t['sukatakana'] = 0x30B9;
+ t['sukatakanahalfwidth'] = 0xFF7D;
+ t['sukunarabic'] = 0x0652;
+ t['summation'] = 0x2211;
+ t['sun'] = 0x263C;
+ t['superset'] = 0x2283;
+ t['supersetnotequal'] = 0x228B;
+ t['supersetorequal'] = 0x2287;
+ t['svsquare'] = 0x33DC;
+ t['syouwaerasquare'] = 0x337C;
+ t['t'] = 0x0074;
+ t['tabengali'] = 0x09A4;
+ t['tackdown'] = 0x22A4;
+ t['tackleft'] = 0x22A3;
+ t['tadeva'] = 0x0924;
+ t['tagujarati'] = 0x0AA4;
+ t['tagurmukhi'] = 0x0A24;
+ t['taharabic'] = 0x0637;
+ t['tahfinalarabic'] = 0xFEC2;
+ t['tahinitialarabic'] = 0xFEC3;
+ t['tahiragana'] = 0x305F;
+ t['tahmedialarabic'] = 0xFEC4;
+ t['taisyouerasquare'] = 0x337D;
+ t['takatakana'] = 0x30BF;
+ t['takatakanahalfwidth'] = 0xFF80;
+ t['tatweelarabic'] = 0x0640;
+ t['tau'] = 0x03C4;
+ t['tav'] = 0x05EA;
+ t['tavdages'] = 0xFB4A;
+ t['tavdagesh'] = 0xFB4A;
+ t['tavdageshhebrew'] = 0xFB4A;
+ t['tavhebrew'] = 0x05EA;
+ t['tbar'] = 0x0167;
+ t['tbopomofo'] = 0x310A;
+ t['tcaron'] = 0x0165;
+ t['tccurl'] = 0x02A8;
+ t['tcedilla'] = 0x0163;
+ t['tcheharabic'] = 0x0686;
+ t['tchehfinalarabic'] = 0xFB7B;
+ t['tchehinitialarabic'] = 0xFB7C;
+ t['tchehmedialarabic'] = 0xFB7D;
+ t['tcircle'] = 0x24E3;
+ t['tcircumflexbelow'] = 0x1E71;
+ t['tcommaaccent'] = 0x0163;
+ t['tdieresis'] = 0x1E97;
+ t['tdotaccent'] = 0x1E6B;
+ t['tdotbelow'] = 0x1E6D;
+ t['tecyrillic'] = 0x0442;
+ t['tedescendercyrillic'] = 0x04AD;
+ t['teharabic'] = 0x062A;
+ t['tehfinalarabic'] = 0xFE96;
+ t['tehhahinitialarabic'] = 0xFCA2;
+ t['tehhahisolatedarabic'] = 0xFC0C;
+ t['tehinitialarabic'] = 0xFE97;
+ t['tehiragana'] = 0x3066;
+ t['tehjeeminitialarabic'] = 0xFCA1;
+ t['tehjeemisolatedarabic'] = 0xFC0B;
+ t['tehmarbutaarabic'] = 0x0629;
+ t['tehmarbutafinalarabic'] = 0xFE94;
+ t['tehmedialarabic'] = 0xFE98;
+ t['tehmeeminitialarabic'] = 0xFCA4;
+ t['tehmeemisolatedarabic'] = 0xFC0E;
+ t['tehnoonfinalarabic'] = 0xFC73;
+ t['tekatakana'] = 0x30C6;
+ t['tekatakanahalfwidth'] = 0xFF83;
+ t['telephone'] = 0x2121;
+ t['telephoneblack'] = 0x260E;
+ t['telishagedolahebrew'] = 0x05A0;
+ t['telishaqetanahebrew'] = 0x05A9;
+ t['tencircle'] = 0x2469;
+ t['tenideographicparen'] = 0x3229;
+ t['tenparen'] = 0x247D;
+ t['tenperiod'] = 0x2491;
+ t['tenroman'] = 0x2179;
+ t['tesh'] = 0x02A7;
+ t['tet'] = 0x05D8;
+ t['tetdagesh'] = 0xFB38;
+ t['tetdageshhebrew'] = 0xFB38;
+ t['tethebrew'] = 0x05D8;
+ t['tetsecyrillic'] = 0x04B5;
+ t['tevirhebrew'] = 0x059B;
+ t['tevirlefthebrew'] = 0x059B;
+ t['thabengali'] = 0x09A5;
+ t['thadeva'] = 0x0925;
+ t['thagujarati'] = 0x0AA5;
+ t['thagurmukhi'] = 0x0A25;
+ t['thalarabic'] = 0x0630;
+ t['thalfinalarabic'] = 0xFEAC;
+ t['thanthakhatlowleftthai'] = 0xF898;
+ t['thanthakhatlowrightthai'] = 0xF897;
+ t['thanthakhatthai'] = 0x0E4C;
+ t['thanthakhatupperleftthai'] = 0xF896;
+ t['theharabic'] = 0x062B;
+ t['thehfinalarabic'] = 0xFE9A;
+ t['thehinitialarabic'] = 0xFE9B;
+ t['thehmedialarabic'] = 0xFE9C;
+ t['thereexists'] = 0x2203;
+ t['therefore'] = 0x2234;
+ t['theta'] = 0x03B8;
+ t['theta1'] = 0x03D1;
+ t['thetasymbolgreek'] = 0x03D1;
+ t['thieuthacirclekorean'] = 0x3279;
+ t['thieuthaparenkorean'] = 0x3219;
+ t['thieuthcirclekorean'] = 0x326B;
+ t['thieuthkorean'] = 0x314C;
+ t['thieuthparenkorean'] = 0x320B;
+ t['thirteencircle'] = 0x246C;
+ t['thirteenparen'] = 0x2480;
+ t['thirteenperiod'] = 0x2494;
+ t['thonangmonthothai'] = 0x0E11;
+ t['thook'] = 0x01AD;
+ t['thophuthaothai'] = 0x0E12;
+ t['thorn'] = 0x00FE;
+ t['thothahanthai'] = 0x0E17;
+ t['thothanthai'] = 0x0E10;
+ t['thothongthai'] = 0x0E18;
+ t['thothungthai'] = 0x0E16;
+ t['thousandcyrillic'] = 0x0482;
+ t['thousandsseparatorarabic'] = 0x066C;
+ t['thousandsseparatorpersian'] = 0x066C;
+ t['three'] = 0x0033;
+ t['threearabic'] = 0x0663;
+ t['threebengali'] = 0x09E9;
+ t['threecircle'] = 0x2462;
+ t['threecircleinversesansserif'] = 0x278C;
+ t['threedeva'] = 0x0969;
+ t['threeeighths'] = 0x215C;
+ t['threegujarati'] = 0x0AE9;
+ t['threegurmukhi'] = 0x0A69;
+ t['threehackarabic'] = 0x0663;
+ t['threehangzhou'] = 0x3023;
+ t['threeideographicparen'] = 0x3222;
+ t['threeinferior'] = 0x2083;
+ t['threemonospace'] = 0xFF13;
+ t['threenumeratorbengali'] = 0x09F6;
+ t['threeoldstyle'] = 0xF733;
+ t['threeparen'] = 0x2476;
+ t['threeperiod'] = 0x248A;
+ t['threepersian'] = 0x06F3;
+ t['threequarters'] = 0x00BE;
+ t['threequartersemdash'] = 0xF6DE;
+ t['threeroman'] = 0x2172;
+ t['threesuperior'] = 0x00B3;
+ t['threethai'] = 0x0E53;
+ t['thzsquare'] = 0x3394;
+ t['tihiragana'] = 0x3061;
+ t['tikatakana'] = 0x30C1;
+ t['tikatakanahalfwidth'] = 0xFF81;
+ t['tikeutacirclekorean'] = 0x3270;
+ t['tikeutaparenkorean'] = 0x3210;
+ t['tikeutcirclekorean'] = 0x3262;
+ t['tikeutkorean'] = 0x3137;
+ t['tikeutparenkorean'] = 0x3202;
+ t['tilde'] = 0x02DC;
+ t['tildebelowcmb'] = 0x0330;
+ t['tildecmb'] = 0x0303;
+ t['tildecomb'] = 0x0303;
+ t['tildedoublecmb'] = 0x0360;
+ t['tildeoperator'] = 0x223C;
+ t['tildeoverlaycmb'] = 0x0334;
+ t['tildeverticalcmb'] = 0x033E;
+ t['timescircle'] = 0x2297;
+ t['tipehahebrew'] = 0x0596;
+ t['tipehalefthebrew'] = 0x0596;
+ t['tippigurmukhi'] = 0x0A70;
+ t['titlocyrilliccmb'] = 0x0483;
+ t['tiwnarmenian'] = 0x057F;
+ t['tlinebelow'] = 0x1E6F;
+ t['tmonospace'] = 0xFF54;
+ t['toarmenian'] = 0x0569;
+ t['tohiragana'] = 0x3068;
+ t['tokatakana'] = 0x30C8;
+ t['tokatakanahalfwidth'] = 0xFF84;
+ t['tonebarextrahighmod'] = 0x02E5;
+ t['tonebarextralowmod'] = 0x02E9;
+ t['tonebarhighmod'] = 0x02E6;
+ t['tonebarlowmod'] = 0x02E8;
+ t['tonebarmidmod'] = 0x02E7;
+ t['tonefive'] = 0x01BD;
+ t['tonesix'] = 0x0185;
+ t['tonetwo'] = 0x01A8;
+ t['tonos'] = 0x0384;
+ t['tonsquare'] = 0x3327;
+ t['topatakthai'] = 0x0E0F;
+ t['tortoiseshellbracketleft'] = 0x3014;
+ t['tortoiseshellbracketleftsmall'] = 0xFE5D;
+ t['tortoiseshellbracketleftvertical'] = 0xFE39;
+ t['tortoiseshellbracketright'] = 0x3015;
+ t['tortoiseshellbracketrightsmall'] = 0xFE5E;
+ t['tortoiseshellbracketrightvertical'] = 0xFE3A;
+ t['totaothai'] = 0x0E15;
+ t['tpalatalhook'] = 0x01AB;
+ t['tparen'] = 0x24AF;
+ t['trademark'] = 0x2122;
+ t['trademarksans'] = 0xF8EA;
+ t['trademarkserif'] = 0xF6DB;
+ t['tretroflexhook'] = 0x0288;
+ t['triagdn'] = 0x25BC;
+ t['triaglf'] = 0x25C4;
+ t['triagrt'] = 0x25BA;
+ t['triagup'] = 0x25B2;
+ t['ts'] = 0x02A6;
+ t['tsadi'] = 0x05E6;
+ t['tsadidagesh'] = 0xFB46;
+ t['tsadidageshhebrew'] = 0xFB46;
+ t['tsadihebrew'] = 0x05E6;
+ t['tsecyrillic'] = 0x0446;
+ t['tsere'] = 0x05B5;
+ t['tsere12'] = 0x05B5;
+ t['tsere1e'] = 0x05B5;
+ t['tsere2b'] = 0x05B5;
+ t['tserehebrew'] = 0x05B5;
+ t['tserenarrowhebrew'] = 0x05B5;
+ t['tserequarterhebrew'] = 0x05B5;
+ t['tserewidehebrew'] = 0x05B5;
+ t['tshecyrillic'] = 0x045B;
+ t['tsuperior'] = 0xF6F3;
+ t['ttabengali'] = 0x099F;
+ t['ttadeva'] = 0x091F;
+ t['ttagujarati'] = 0x0A9F;
+ t['ttagurmukhi'] = 0x0A1F;
+ t['tteharabic'] = 0x0679;
+ t['ttehfinalarabic'] = 0xFB67;
+ t['ttehinitialarabic'] = 0xFB68;
+ t['ttehmedialarabic'] = 0xFB69;
+ t['tthabengali'] = 0x09A0;
+ t['tthadeva'] = 0x0920;
+ t['tthagujarati'] = 0x0AA0;
+ t['tthagurmukhi'] = 0x0A20;
+ t['tturned'] = 0x0287;
+ t['tuhiragana'] = 0x3064;
+ t['tukatakana'] = 0x30C4;
+ t['tukatakanahalfwidth'] = 0xFF82;
+ t['tusmallhiragana'] = 0x3063;
+ t['tusmallkatakana'] = 0x30C3;
+ t['tusmallkatakanahalfwidth'] = 0xFF6F;
+ t['twelvecircle'] = 0x246B;
+ t['twelveparen'] = 0x247F;
+ t['twelveperiod'] = 0x2493;
+ t['twelveroman'] = 0x217B;
+ t['twentycircle'] = 0x2473;
+ t['twentyhangzhou'] = 0x5344;
+ t['twentyparen'] = 0x2487;
+ t['twentyperiod'] = 0x249B;
+ t['two'] = 0x0032;
+ t['twoarabic'] = 0x0662;
+ t['twobengali'] = 0x09E8;
+ t['twocircle'] = 0x2461;
+ t['twocircleinversesansserif'] = 0x278B;
+ t['twodeva'] = 0x0968;
+ t['twodotenleader'] = 0x2025;
+ t['twodotleader'] = 0x2025;
+ t['twodotleadervertical'] = 0xFE30;
+ t['twogujarati'] = 0x0AE8;
+ t['twogurmukhi'] = 0x0A68;
+ t['twohackarabic'] = 0x0662;
+ t['twohangzhou'] = 0x3022;
+ t['twoideographicparen'] = 0x3221;
+ t['twoinferior'] = 0x2082;
+ t['twomonospace'] = 0xFF12;
+ t['twonumeratorbengali'] = 0x09F5;
+ t['twooldstyle'] = 0xF732;
+ t['twoparen'] = 0x2475;
+ t['twoperiod'] = 0x2489;
+ t['twopersian'] = 0x06F2;
+ t['tworoman'] = 0x2171;
+ t['twostroke'] = 0x01BB;
+ t['twosuperior'] = 0x00B2;
+ t['twothai'] = 0x0E52;
+ t['twothirds'] = 0x2154;
+ t['u'] = 0x0075;
+ t['uacute'] = 0x00FA;
+ t['ubar'] = 0x0289;
+ t['ubengali'] = 0x0989;
+ t['ubopomofo'] = 0x3128;
+ t['ubreve'] = 0x016D;
+ t['ucaron'] = 0x01D4;
+ t['ucircle'] = 0x24E4;
+ t['ucircumflex'] = 0x00FB;
+ t['ucircumflexbelow'] = 0x1E77;
+ t['ucyrillic'] = 0x0443;
+ t['udattadeva'] = 0x0951;
+ t['udblacute'] = 0x0171;
+ t['udblgrave'] = 0x0215;
+ t['udeva'] = 0x0909;
+ t['udieresis'] = 0x00FC;
+ t['udieresisacute'] = 0x01D8;
+ t['udieresisbelow'] = 0x1E73;
+ t['udieresiscaron'] = 0x01DA;
+ t['udieresiscyrillic'] = 0x04F1;
+ t['udieresisgrave'] = 0x01DC;
+ t['udieresismacron'] = 0x01D6;
+ t['udotbelow'] = 0x1EE5;
+ t['ugrave'] = 0x00F9;
+ t['ugujarati'] = 0x0A89;
+ t['ugurmukhi'] = 0x0A09;
+ t['uhiragana'] = 0x3046;
+ t['uhookabove'] = 0x1EE7;
+ t['uhorn'] = 0x01B0;
+ t['uhornacute'] = 0x1EE9;
+ t['uhorndotbelow'] = 0x1EF1;
+ t['uhorngrave'] = 0x1EEB;
+ t['uhornhookabove'] = 0x1EED;
+ t['uhorntilde'] = 0x1EEF;
+ t['uhungarumlaut'] = 0x0171;
+ t['uhungarumlautcyrillic'] = 0x04F3;
+ t['uinvertedbreve'] = 0x0217;
+ t['ukatakana'] = 0x30A6;
+ t['ukatakanahalfwidth'] = 0xFF73;
+ t['ukcyrillic'] = 0x0479;
+ t['ukorean'] = 0x315C;
+ t['umacron'] = 0x016B;
+ t['umacroncyrillic'] = 0x04EF;
+ t['umacrondieresis'] = 0x1E7B;
+ t['umatragurmukhi'] = 0x0A41;
+ t['umonospace'] = 0xFF55;
+ t['underscore'] = 0x005F;
+ t['underscoredbl'] = 0x2017;
+ t['underscoremonospace'] = 0xFF3F;
+ t['underscorevertical'] = 0xFE33;
+ t['underscorewavy'] = 0xFE4F;
+ t['union'] = 0x222A;
+ t['universal'] = 0x2200;
+ t['uogonek'] = 0x0173;
+ t['uparen'] = 0x24B0;
+ t['upblock'] = 0x2580;
+ t['upperdothebrew'] = 0x05C4;
+ t['upsilon'] = 0x03C5;
+ t['upsilondieresis'] = 0x03CB;
+ t['upsilondieresistonos'] = 0x03B0;
+ t['upsilonlatin'] = 0x028A;
+ t['upsilontonos'] = 0x03CD;
+ t['uptackbelowcmb'] = 0x031D;
+ t['uptackmod'] = 0x02D4;
+ t['uragurmukhi'] = 0x0A73;
+ t['uring'] = 0x016F;
+ t['ushortcyrillic'] = 0x045E;
+ t['usmallhiragana'] = 0x3045;
+ t['usmallkatakana'] = 0x30A5;
+ t['usmallkatakanahalfwidth'] = 0xFF69;
+ t['ustraightcyrillic'] = 0x04AF;
+ t['ustraightstrokecyrillic'] = 0x04B1;
+ t['utilde'] = 0x0169;
+ t['utildeacute'] = 0x1E79;
+ t['utildebelow'] = 0x1E75;
+ t['uubengali'] = 0x098A;
+ t['uudeva'] = 0x090A;
+ t['uugujarati'] = 0x0A8A;
+ t['uugurmukhi'] = 0x0A0A;
+ t['uumatragurmukhi'] = 0x0A42;
+ t['uuvowelsignbengali'] = 0x09C2;
+ t['uuvowelsigndeva'] = 0x0942;
+ t['uuvowelsigngujarati'] = 0x0AC2;
+ t['uvowelsignbengali'] = 0x09C1;
+ t['uvowelsigndeva'] = 0x0941;
+ t['uvowelsigngujarati'] = 0x0AC1;
+ t['v'] = 0x0076;
+ t['vadeva'] = 0x0935;
+ t['vagujarati'] = 0x0AB5;
+ t['vagurmukhi'] = 0x0A35;
+ t['vakatakana'] = 0x30F7;
+ t['vav'] = 0x05D5;
+ t['vavdagesh'] = 0xFB35;
+ t['vavdagesh65'] = 0xFB35;
+ t['vavdageshhebrew'] = 0xFB35;
+ t['vavhebrew'] = 0x05D5;
+ t['vavholam'] = 0xFB4B;
+ t['vavholamhebrew'] = 0xFB4B;
+ t['vavvavhebrew'] = 0x05F0;
+ t['vavyodhebrew'] = 0x05F1;
+ t['vcircle'] = 0x24E5;
+ t['vdotbelow'] = 0x1E7F;
+ t['vecyrillic'] = 0x0432;
+ t['veharabic'] = 0x06A4;
+ t['vehfinalarabic'] = 0xFB6B;
+ t['vehinitialarabic'] = 0xFB6C;
+ t['vehmedialarabic'] = 0xFB6D;
+ t['vekatakana'] = 0x30F9;
+ t['venus'] = 0x2640;
+ t['verticalbar'] = 0x007C;
+ t['verticallineabovecmb'] = 0x030D;
+ t['verticallinebelowcmb'] = 0x0329;
+ t['verticallinelowmod'] = 0x02CC;
+ t['verticallinemod'] = 0x02C8;
+ t['vewarmenian'] = 0x057E;
+ t['vhook'] = 0x028B;
+ t['vikatakana'] = 0x30F8;
+ t['viramabengali'] = 0x09CD;
+ t['viramadeva'] = 0x094D;
+ t['viramagujarati'] = 0x0ACD;
+ t['visargabengali'] = 0x0983;
+ t['visargadeva'] = 0x0903;
+ t['visargagujarati'] = 0x0A83;
+ t['vmonospace'] = 0xFF56;
+ t['voarmenian'] = 0x0578;
+ t['voicediterationhiragana'] = 0x309E;
+ t['voicediterationkatakana'] = 0x30FE;
+ t['voicedmarkkana'] = 0x309B;
+ t['voicedmarkkanahalfwidth'] = 0xFF9E;
+ t['vokatakana'] = 0x30FA;
+ t['vparen'] = 0x24B1;
+ t['vtilde'] = 0x1E7D;
+ t['vturned'] = 0x028C;
+ t['vuhiragana'] = 0x3094;
+ t['vukatakana'] = 0x30F4;
+ t['w'] = 0x0077;
+ t['wacute'] = 0x1E83;
+ t['waekorean'] = 0x3159;
+ t['wahiragana'] = 0x308F;
+ t['wakatakana'] = 0x30EF;
+ t['wakatakanahalfwidth'] = 0xFF9C;
+ t['wakorean'] = 0x3158;
+ t['wasmallhiragana'] = 0x308E;
+ t['wasmallkatakana'] = 0x30EE;
+ t['wattosquare'] = 0x3357;
+ t['wavedash'] = 0x301C;
+ t['wavyunderscorevertical'] = 0xFE34;
+ t['wawarabic'] = 0x0648;
+ t['wawfinalarabic'] = 0xFEEE;
+ t['wawhamzaabovearabic'] = 0x0624;
+ t['wawhamzaabovefinalarabic'] = 0xFE86;
+ t['wbsquare'] = 0x33DD;
+ t['wcircle'] = 0x24E6;
+ t['wcircumflex'] = 0x0175;
+ t['wdieresis'] = 0x1E85;
+ t['wdotaccent'] = 0x1E87;
+ t['wdotbelow'] = 0x1E89;
+ t['wehiragana'] = 0x3091;
+ t['weierstrass'] = 0x2118;
+ t['wekatakana'] = 0x30F1;
+ t['wekorean'] = 0x315E;
+ t['weokorean'] = 0x315D;
+ t['wgrave'] = 0x1E81;
+ t['whitebullet'] = 0x25E6;
+ t['whitecircle'] = 0x25CB;
+ t['whitecircleinverse'] = 0x25D9;
+ t['whitecornerbracketleft'] = 0x300E;
+ t['whitecornerbracketleftvertical'] = 0xFE43;
+ t['whitecornerbracketright'] = 0x300F;
+ t['whitecornerbracketrightvertical'] = 0xFE44;
+ t['whitediamond'] = 0x25C7;
+ t['whitediamondcontainingblacksmalldiamond'] = 0x25C8;
+ t['whitedownpointingsmalltriangle'] = 0x25BF;
+ t['whitedownpointingtriangle'] = 0x25BD;
+ t['whiteleftpointingsmalltriangle'] = 0x25C3;
+ t['whiteleftpointingtriangle'] = 0x25C1;
+ t['whitelenticularbracketleft'] = 0x3016;
+ t['whitelenticularbracketright'] = 0x3017;
+ t['whiterightpointingsmalltriangle'] = 0x25B9;
+ t['whiterightpointingtriangle'] = 0x25B7;
+ t['whitesmallsquare'] = 0x25AB;
+ t['whitesmilingface'] = 0x263A;
+ t['whitesquare'] = 0x25A1;
+ t['whitestar'] = 0x2606;
+ t['whitetelephone'] = 0x260F;
+ t['whitetortoiseshellbracketleft'] = 0x3018;
+ t['whitetortoiseshellbracketright'] = 0x3019;
+ t['whiteuppointingsmalltriangle'] = 0x25B5;
+ t['whiteuppointingtriangle'] = 0x25B3;
+ t['wihiragana'] = 0x3090;
+ t['wikatakana'] = 0x30F0;
+ t['wikorean'] = 0x315F;
+ t['wmonospace'] = 0xFF57;
+ t['wohiragana'] = 0x3092;
+ t['wokatakana'] = 0x30F2;
+ t['wokatakanahalfwidth'] = 0xFF66;
+ t['won'] = 0x20A9;
+ t['wonmonospace'] = 0xFFE6;
+ t['wowaenthai'] = 0x0E27;
+ t['wparen'] = 0x24B2;
+ t['wring'] = 0x1E98;
+ t['wsuperior'] = 0x02B7;
+ t['wturned'] = 0x028D;
+ t['wynn'] = 0x01BF;
+ t['x'] = 0x0078;
+ t['xabovecmb'] = 0x033D;
+ t['xbopomofo'] = 0x3112;
+ t['xcircle'] = 0x24E7;
+ t['xdieresis'] = 0x1E8D;
+ t['xdotaccent'] = 0x1E8B;
+ t['xeharmenian'] = 0x056D;
+ t['xi'] = 0x03BE;
+ t['xmonospace'] = 0xFF58;
+ t['xparen'] = 0x24B3;
+ t['xsuperior'] = 0x02E3;
+ t['y'] = 0x0079;
+ t['yaadosquare'] = 0x334E;
+ t['yabengali'] = 0x09AF;
+ t['yacute'] = 0x00FD;
+ t['yadeva'] = 0x092F;
+ t['yaekorean'] = 0x3152;
+ t['yagujarati'] = 0x0AAF;
+ t['yagurmukhi'] = 0x0A2F;
+ t['yahiragana'] = 0x3084;
+ t['yakatakana'] = 0x30E4;
+ t['yakatakanahalfwidth'] = 0xFF94;
+ t['yakorean'] = 0x3151;
+ t['yamakkanthai'] = 0x0E4E;
+ t['yasmallhiragana'] = 0x3083;
+ t['yasmallkatakana'] = 0x30E3;
+ t['yasmallkatakanahalfwidth'] = 0xFF6C;
+ t['yatcyrillic'] = 0x0463;
+ t['ycircle'] = 0x24E8;
+ t['ycircumflex'] = 0x0177;
+ t['ydieresis'] = 0x00FF;
+ t['ydotaccent'] = 0x1E8F;
+ t['ydotbelow'] = 0x1EF5;
+ t['yeharabic'] = 0x064A;
+ t['yehbarreearabic'] = 0x06D2;
+ t['yehbarreefinalarabic'] = 0xFBAF;
+ t['yehfinalarabic'] = 0xFEF2;
+ t['yehhamzaabovearabic'] = 0x0626;
+ t['yehhamzaabovefinalarabic'] = 0xFE8A;
+ t['yehhamzaaboveinitialarabic'] = 0xFE8B;
+ t['yehhamzaabovemedialarabic'] = 0xFE8C;
+ t['yehinitialarabic'] = 0xFEF3;
+ t['yehmedialarabic'] = 0xFEF4;
+ t['yehmeeminitialarabic'] = 0xFCDD;
+ t['yehmeemisolatedarabic'] = 0xFC58;
+ t['yehnoonfinalarabic'] = 0xFC94;
+ t['yehthreedotsbelowarabic'] = 0x06D1;
+ t['yekorean'] = 0x3156;
+ t['yen'] = 0x00A5;
+ t['yenmonospace'] = 0xFFE5;
+ t['yeokorean'] = 0x3155;
+ t['yeorinhieuhkorean'] = 0x3186;
+ t['yerahbenyomohebrew'] = 0x05AA;
+ t['yerahbenyomolefthebrew'] = 0x05AA;
+ t['yericyrillic'] = 0x044B;
+ t['yerudieresiscyrillic'] = 0x04F9;
+ t['yesieungkorean'] = 0x3181;
+ t['yesieungpansioskorean'] = 0x3183;
+ t['yesieungsioskorean'] = 0x3182;
+ t['yetivhebrew'] = 0x059A;
+ t['ygrave'] = 0x1EF3;
+ t['yhook'] = 0x01B4;
+ t['yhookabove'] = 0x1EF7;
+ t['yiarmenian'] = 0x0575;
+ t['yicyrillic'] = 0x0457;
+ t['yikorean'] = 0x3162;
+ t['yinyang'] = 0x262F;
+ t['yiwnarmenian'] = 0x0582;
+ t['ymonospace'] = 0xFF59;
+ t['yod'] = 0x05D9;
+ t['yoddagesh'] = 0xFB39;
+ t['yoddageshhebrew'] = 0xFB39;
+ t['yodhebrew'] = 0x05D9;
+ t['yodyodhebrew'] = 0x05F2;
+ t['yodyodpatahhebrew'] = 0xFB1F;
+ t['yohiragana'] = 0x3088;
+ t['yoikorean'] = 0x3189;
+ t['yokatakana'] = 0x30E8;
+ t['yokatakanahalfwidth'] = 0xFF96;
+ t['yokorean'] = 0x315B;
+ t['yosmallhiragana'] = 0x3087;
+ t['yosmallkatakana'] = 0x30E7;
+ t['yosmallkatakanahalfwidth'] = 0xFF6E;
+ t['yotgreek'] = 0x03F3;
+ t['yoyaekorean'] = 0x3188;
+ t['yoyakorean'] = 0x3187;
+ t['yoyakthai'] = 0x0E22;
+ t['yoyingthai'] = 0x0E0D;
+ t['yparen'] = 0x24B4;
+ t['ypogegrammeni'] = 0x037A;
+ t['ypogegrammenigreekcmb'] = 0x0345;
+ t['yr'] = 0x01A6;
+ t['yring'] = 0x1E99;
+ t['ysuperior'] = 0x02B8;
+ t['ytilde'] = 0x1EF9;
+ t['yturned'] = 0x028E;
+ t['yuhiragana'] = 0x3086;
+ t['yuikorean'] = 0x318C;
+ t['yukatakana'] = 0x30E6;
+ t['yukatakanahalfwidth'] = 0xFF95;
+ t['yukorean'] = 0x3160;
+ t['yusbigcyrillic'] = 0x046B;
+ t['yusbigiotifiedcyrillic'] = 0x046D;
+ t['yuslittlecyrillic'] = 0x0467;
+ t['yuslittleiotifiedcyrillic'] = 0x0469;
+ t['yusmallhiragana'] = 0x3085;
+ t['yusmallkatakana'] = 0x30E5;
+ t['yusmallkatakanahalfwidth'] = 0xFF6D;
+ t['yuyekorean'] = 0x318B;
+ t['yuyeokorean'] = 0x318A;
+ t['yyabengali'] = 0x09DF;
+ t['yyadeva'] = 0x095F;
+ t['z'] = 0x007A;
+ t['zaarmenian'] = 0x0566;
+ t['zacute'] = 0x017A;
+ t['zadeva'] = 0x095B;
+ t['zagurmukhi'] = 0x0A5B;
+ t['zaharabic'] = 0x0638;
+ t['zahfinalarabic'] = 0xFEC6;
+ t['zahinitialarabic'] = 0xFEC7;
+ t['zahiragana'] = 0x3056;
+ t['zahmedialarabic'] = 0xFEC8;
+ t['zainarabic'] = 0x0632;
+ t['zainfinalarabic'] = 0xFEB0;
+ t['zakatakana'] = 0x30B6;
+ t['zaqefgadolhebrew'] = 0x0595;
+ t['zaqefqatanhebrew'] = 0x0594;
+ t['zarqahebrew'] = 0x0598;
+ t['zayin'] = 0x05D6;
+ t['zayindagesh'] = 0xFB36;
+ t['zayindageshhebrew'] = 0xFB36;
+ t['zayinhebrew'] = 0x05D6;
+ t['zbopomofo'] = 0x3117;
+ t['zcaron'] = 0x017E;
+ t['zcircle'] = 0x24E9;
+ t['zcircumflex'] = 0x1E91;
+ t['zcurl'] = 0x0291;
+ t['zdot'] = 0x017C;
+ t['zdotaccent'] = 0x017C;
+ t['zdotbelow'] = 0x1E93;
+ t['zecyrillic'] = 0x0437;
+ t['zedescendercyrillic'] = 0x0499;
+ t['zedieresiscyrillic'] = 0x04DF;
+ t['zehiragana'] = 0x305C;
+ t['zekatakana'] = 0x30BC;
+ t['zero'] = 0x0030;
+ t['zeroarabic'] = 0x0660;
+ t['zerobengali'] = 0x09E6;
+ t['zerodeva'] = 0x0966;
+ t['zerogujarati'] = 0x0AE6;
+ t['zerogurmukhi'] = 0x0A66;
+ t['zerohackarabic'] = 0x0660;
+ t['zeroinferior'] = 0x2080;
+ t['zeromonospace'] = 0xFF10;
+ t['zerooldstyle'] = 0xF730;
+ t['zeropersian'] = 0x06F0;
+ t['zerosuperior'] = 0x2070;
+ t['zerothai'] = 0x0E50;
+ t['zerowidthjoiner'] = 0xFEFF;
+ t['zerowidthnonjoiner'] = 0x200C;
+ t['zerowidthspace'] = 0x200B;
+ t['zeta'] = 0x03B6;
+ t['zhbopomofo'] = 0x3113;
+ t['zhearmenian'] = 0x056A;
+ t['zhebrevecyrillic'] = 0x04C2;
+ t['zhecyrillic'] = 0x0436;
+ t['zhedescendercyrillic'] = 0x0497;
+ t['zhedieresiscyrillic'] = 0x04DD;
+ t['zihiragana'] = 0x3058;
+ t['zikatakana'] = 0x30B8;
+ t['zinorhebrew'] = 0x05AE;
+ t['zlinebelow'] = 0x1E95;
+ t['zmonospace'] = 0xFF5A;
+ t['zohiragana'] = 0x305E;
+ t['zokatakana'] = 0x30BE;
+ t['zparen'] = 0x24B5;
+ t['zretroflexhook'] = 0x0290;
+ t['zstroke'] = 0x01B6;
+ t['zuhiragana'] = 0x305A;
+ t['zukatakana'] = 0x30BA;
+ t['.notdef'] = 0x0000;
+ t['angbracketleftbig'] = 0x2329;
+ t['angbracketleftBig'] = 0x2329;
+ t['angbracketleftbigg'] = 0x2329;
+ t['angbracketleftBigg'] = 0x2329;
+ t['angbracketrightBig'] = 0x232A;
+ t['angbracketrightbig'] = 0x232A;
+ t['angbracketrightBigg'] = 0x232A;
+ t['angbracketrightbigg'] = 0x232A;
+ t['arrowhookleft'] = 0x21AA;
+ t['arrowhookright'] = 0x21A9;
+ t['arrowlefttophalf'] = 0x21BC;
+ t['arrowleftbothalf'] = 0x21BD;
+ t['arrownortheast'] = 0x2197;
+ t['arrownorthwest'] = 0x2196;
+ t['arrowrighttophalf'] = 0x21C0;
+ t['arrowrightbothalf'] = 0x21C1;
+ t['arrowsoutheast'] = 0x2198;
+ t['arrowsouthwest'] = 0x2199;
+ t['backslashbig'] = 0x2216;
+ t['backslashBig'] = 0x2216;
+ t['backslashBigg'] = 0x2216;
+ t['backslashbigg'] = 0x2216;
+ t['bardbl'] = 0x2016;
+ t['bracehtipdownleft'] = 0xFE37;
+ t['bracehtipdownright'] = 0xFE37;
+ t['bracehtipupleft'] = 0xFE38;
+ t['bracehtipupright'] = 0xFE38;
+ t['braceleftBig'] = 0x007B;
+ t['braceleftbig'] = 0x007B;
+ t['braceleftbigg'] = 0x007B;
+ t['braceleftBigg'] = 0x007B;
+ t['bracerightBig'] = 0x007D;
+ t['bracerightbig'] = 0x007D;
+ t['bracerightbigg'] = 0x007D;
+ t['bracerightBigg'] = 0x007D;
+ t['bracketleftbig'] = 0x005B;
+ t['bracketleftBig'] = 0x005B;
+ t['bracketleftbigg'] = 0x005B;
+ t['bracketleftBigg'] = 0x005B;
+ t['bracketrightBig'] = 0x005D;
+ t['bracketrightbig'] = 0x005D;
+ t['bracketrightbigg'] = 0x005D;
+ t['bracketrightBigg'] = 0x005D;
+ t['ceilingleftbig'] = 0x2308;
+ t['ceilingleftBig'] = 0x2308;
+ t['ceilingleftBigg'] = 0x2308;
+ t['ceilingleftbigg'] = 0x2308;
+ t['ceilingrightbig'] = 0x2309;
+ t['ceilingrightBig'] = 0x2309;
+ t['ceilingrightbigg'] = 0x2309;
+ t['ceilingrightBigg'] = 0x2309;
+ t['circledotdisplay'] = 0x2299;
+ t['circledottext'] = 0x2299;
+ t['circlemultiplydisplay'] = 0x2297;
+ t['circlemultiplytext'] = 0x2297;
+ t['circleplusdisplay'] = 0x2295;
+ t['circleplustext'] = 0x2295;
+ t['contintegraldisplay'] = 0x222E;
+ t['contintegraltext'] = 0x222E;
+ t['coproductdisplay'] = 0x2210;
+ t['coproducttext'] = 0x2210;
+ t['floorleftBig'] = 0x230A;
+ t['floorleftbig'] = 0x230A;
+ t['floorleftbigg'] = 0x230A;
+ t['floorleftBigg'] = 0x230A;
+ t['floorrightbig'] = 0x230B;
+ t['floorrightBig'] = 0x230B;
+ t['floorrightBigg'] = 0x230B;
+ t['floorrightbigg'] = 0x230B;
+ t['hatwide'] = 0x0302;
+ t['hatwider'] = 0x0302;
+ t['hatwidest'] = 0x0302;
+ t['intercal'] = 0x1D40;
+ t['integraldisplay'] = 0x222B;
+ t['integraltext'] = 0x222B;
+ t['intersectiondisplay'] = 0x22C2;
+ t['intersectiontext'] = 0x22C2;
+ t['logicalanddisplay'] = 0x2227;
+ t['logicalandtext'] = 0x2227;
+ t['logicalordisplay'] = 0x2228;
+ t['logicalortext'] = 0x2228;
+ t['parenleftBig'] = 0x0028;
+ t['parenleftbig'] = 0x0028;
+ t['parenleftBigg'] = 0x0028;
+ t['parenleftbigg'] = 0x0028;
+ t['parenrightBig'] = 0x0029;
+ t['parenrightbig'] = 0x0029;
+ t['parenrightBigg'] = 0x0029;
+ t['parenrightbigg'] = 0x0029;
+ t['prime'] = 0x2032;
+ t['productdisplay'] = 0x220F;
+ t['producttext'] = 0x220F;
+ t['radicalbig'] = 0x221A;
+ t['radicalBig'] = 0x221A;
+ t['radicalBigg'] = 0x221A;
+ t['radicalbigg'] = 0x221A;
+ t['radicalbt'] = 0x221A;
+ t['radicaltp'] = 0x221A;
+ t['radicalvertex'] = 0x221A;
+ t['slashbig'] = 0x002F;
+ t['slashBig'] = 0x002F;
+ t['slashBigg'] = 0x002F;
+ t['slashbigg'] = 0x002F;
+ t['summationdisplay'] = 0x2211;
+ t['summationtext'] = 0x2211;
+ t['tildewide'] = 0x02DC;
+ t['tildewider'] = 0x02DC;
+ t['tildewidest'] = 0x02DC;
+ t['uniondisplay'] = 0x22C3;
+ t['unionmultidisplay'] = 0x228E;
+ t['unionmultitext'] = 0x228E;
+ t['unionsqdisplay'] = 0x2294;
+ t['unionsqtext'] = 0x2294;
+ t['uniontext'] = 0x22C3;
+ t['vextenddouble'] = 0x2225;
+ t['vextendsingle'] = 0x2223;
+});
+var getDingbatsGlyphsUnicode = getLookupTableFactory(function (t) {
+ t['space'] = 0x0020;
+ t['a1'] = 0x2701;
+ t['a2'] = 0x2702;
+ t['a202'] = 0x2703;
+ t['a3'] = 0x2704;
+ t['a4'] = 0x260E;
+ t['a5'] = 0x2706;
+ t['a119'] = 0x2707;
+ t['a118'] = 0x2708;
+ t['a117'] = 0x2709;
+ t['a11'] = 0x261B;
+ t['a12'] = 0x261E;
+ t['a13'] = 0x270C;
+ t['a14'] = 0x270D;
+ t['a15'] = 0x270E;
+ t['a16'] = 0x270F;
+ t['a105'] = 0x2710;
+ t['a17'] = 0x2711;
+ t['a18'] = 0x2712;
+ t['a19'] = 0x2713;
+ t['a20'] = 0x2714;
+ t['a21'] = 0x2715;
+ t['a22'] = 0x2716;
+ t['a23'] = 0x2717;
+ t['a24'] = 0x2718;
+ t['a25'] = 0x2719;
+ t['a26'] = 0x271A;
+ t['a27'] = 0x271B;
+ t['a28'] = 0x271C;
+ t['a6'] = 0x271D;
+ t['a7'] = 0x271E;
+ t['a8'] = 0x271F;
+ t['a9'] = 0x2720;
+ t['a10'] = 0x2721;
+ t['a29'] = 0x2722;
+ t['a30'] = 0x2723;
+ t['a31'] = 0x2724;
+ t['a32'] = 0x2725;
+ t['a33'] = 0x2726;
+ t['a34'] = 0x2727;
+ t['a35'] = 0x2605;
+ t['a36'] = 0x2729;
+ t['a37'] = 0x272A;
+ t['a38'] = 0x272B;
+ t['a39'] = 0x272C;
+ t['a40'] = 0x272D;
+ t['a41'] = 0x272E;
+ t['a42'] = 0x272F;
+ t['a43'] = 0x2730;
+ t['a44'] = 0x2731;
+ t['a45'] = 0x2732;
+ t['a46'] = 0x2733;
+ t['a47'] = 0x2734;
+ t['a48'] = 0x2735;
+ t['a49'] = 0x2736;
+ t['a50'] = 0x2737;
+ t['a51'] = 0x2738;
+ t['a52'] = 0x2739;
+ t['a53'] = 0x273A;
+ t['a54'] = 0x273B;
+ t['a55'] = 0x273C;
+ t['a56'] = 0x273D;
+ t['a57'] = 0x273E;
+ t['a58'] = 0x273F;
+ t['a59'] = 0x2740;
+ t['a60'] = 0x2741;
+ t['a61'] = 0x2742;
+ t['a62'] = 0x2743;
+ t['a63'] = 0x2744;
+ t['a64'] = 0x2745;
+ t['a65'] = 0x2746;
+ t['a66'] = 0x2747;
+ t['a67'] = 0x2748;
+ t['a68'] = 0x2749;
+ t['a69'] = 0x274A;
+ t['a70'] = 0x274B;
+ t['a71'] = 0x25CF;
+ t['a72'] = 0x274D;
+ t['a73'] = 0x25A0;
+ t['a74'] = 0x274F;
+ t['a203'] = 0x2750;
+ t['a75'] = 0x2751;
+ t['a204'] = 0x2752;
+ t['a76'] = 0x25B2;
+ t['a77'] = 0x25BC;
+ t['a78'] = 0x25C6;
+ t['a79'] = 0x2756;
+ t['a81'] = 0x25D7;
+ t['a82'] = 0x2758;
+ t['a83'] = 0x2759;
+ t['a84'] = 0x275A;
+ t['a97'] = 0x275B;
+ t['a98'] = 0x275C;
+ t['a99'] = 0x275D;
+ t['a100'] = 0x275E;
+ t['a101'] = 0x2761;
+ t['a102'] = 0x2762;
+ t['a103'] = 0x2763;
+ t['a104'] = 0x2764;
+ t['a106'] = 0x2765;
+ t['a107'] = 0x2766;
+ t['a108'] = 0x2767;
+ t['a112'] = 0x2663;
+ t['a111'] = 0x2666;
+ t['a110'] = 0x2665;
+ t['a109'] = 0x2660;
+ t['a120'] = 0x2460;
+ t['a121'] = 0x2461;
+ t['a122'] = 0x2462;
+ t['a123'] = 0x2463;
+ t['a124'] = 0x2464;
+ t['a125'] = 0x2465;
+ t['a126'] = 0x2466;
+ t['a127'] = 0x2467;
+ t['a128'] = 0x2468;
+ t['a129'] = 0x2469;
+ t['a130'] = 0x2776;
+ t['a131'] = 0x2777;
+ t['a132'] = 0x2778;
+ t['a133'] = 0x2779;
+ t['a134'] = 0x277A;
+ t['a135'] = 0x277B;
+ t['a136'] = 0x277C;
+ t['a137'] = 0x277D;
+ t['a138'] = 0x277E;
+ t['a139'] = 0x277F;
+ t['a140'] = 0x2780;
+ t['a141'] = 0x2781;
+ t['a142'] = 0x2782;
+ t['a143'] = 0x2783;
+ t['a144'] = 0x2784;
+ t['a145'] = 0x2785;
+ t['a146'] = 0x2786;
+ t['a147'] = 0x2787;
+ t['a148'] = 0x2788;
+ t['a149'] = 0x2789;
+ t['a150'] = 0x278A;
+ t['a151'] = 0x278B;
+ t['a152'] = 0x278C;
+ t['a153'] = 0x278D;
+ t['a154'] = 0x278E;
+ t['a155'] = 0x278F;
+ t['a156'] = 0x2790;
+ t['a157'] = 0x2791;
+ t['a158'] = 0x2792;
+ t['a159'] = 0x2793;
+ t['a160'] = 0x2794;
+ t['a161'] = 0x2192;
+ t['a163'] = 0x2194;
+ t['a164'] = 0x2195;
+ t['a196'] = 0x2798;
+ t['a165'] = 0x2799;
+ t['a192'] = 0x279A;
+ t['a166'] = 0x279B;
+ t['a167'] = 0x279C;
+ t['a168'] = 0x279D;
+ t['a169'] = 0x279E;
+ t['a170'] = 0x279F;
+ t['a171'] = 0x27A0;
+ t['a172'] = 0x27A1;
+ t['a173'] = 0x27A2;
+ t['a162'] = 0x27A3;
+ t['a174'] = 0x27A4;
+ t['a175'] = 0x27A5;
+ t['a176'] = 0x27A6;
+ t['a177'] = 0x27A7;
+ t['a178'] = 0x27A8;
+ t['a179'] = 0x27A9;
+ t['a193'] = 0x27AA;
+ t['a180'] = 0x27AB;
+ t['a199'] = 0x27AC;
+ t['a181'] = 0x27AD;
+ t['a200'] = 0x27AE;
+ t['a182'] = 0x27AF;
+ t['a201'] = 0x27B1;
+ t['a183'] = 0x27B2;
+ t['a184'] = 0x27B3;
+ t['a197'] = 0x27B4;
+ t['a185'] = 0x27B5;
+ t['a194'] = 0x27B6;
+ t['a198'] = 0x27B7;
+ t['a186'] = 0x27B8;
+ t['a195'] = 0x27B9;
+ t['a187'] = 0x27BA;
+ t['a188'] = 0x27BB;
+ t['a189'] = 0x27BC;
+ t['a190'] = 0x27BD;
+ t['a191'] = 0x27BE;
+ t['a89'] = 0x2768;
+ t['a90'] = 0x2769;
+ t['a93'] = 0x276A;
+ t['a94'] = 0x276B;
+ t['a91'] = 0x276C;
+ t['a92'] = 0x276D;
+ t['a205'] = 0x276E;
+ t['a85'] = 0x276F;
+ t['a206'] = 0x2770;
+ t['a86'] = 0x2771;
+ t['a87'] = 0x2772;
+ t['a88'] = 0x2773;
+ t['a95'] = 0x2774;
+ t['a96'] = 0x2775;
+ t['.notdef'] = 0x0000;
+});
+exports.getGlyphsUnicode = getGlyphsUnicode;
+exports.getDingbatsGlyphsUnicode = getDingbatsGlyphsUnicode;
+
+/***/ }),
+/* 179 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getSupplementalGlyphMapForCalibri = exports.getSupplementalGlyphMapForArialBlack = exports.getGlyphMapForStandardFonts = exports.getSymbolsFonts = exports.getSerifFonts = exports.getNonStdFontMap = exports.getStdFontMap = void 0;
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var getStdFontMap = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t['ArialNarrow'] = 'Helvetica';
+  t['ArialNarrow-Bold'] = 'Helvetica-Bold';
+  t['ArialNarrow-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['ArialNarrow-Italic'] = 'Helvetica-Oblique';
+  t['ArialBlack'] = 'Helvetica';
+  t['ArialBlack-Bold'] = 'Helvetica-Bold';
+  t['ArialBlack-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['ArialBlack-Italic'] = 'Helvetica-Oblique';
+  t['Arial-Black'] = 'Helvetica';
+  t['Arial-Black-Bold'] = 'Helvetica-Bold';
+  t['Arial-Black-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['Arial-Black-Italic'] = 'Helvetica-Oblique';
+  t['Arial'] = 'Helvetica';
+  t['Arial-Bold'] = 'Helvetica-Bold';
+  t['Arial-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['Arial-Italic'] = 'Helvetica-Oblique';
+  t['Arial-BoldItalicMT'] = 'Helvetica-BoldOblique';
+  t['Arial-BoldMT'] = 'Helvetica-Bold';
+  t['Arial-ItalicMT'] = 'Helvetica-Oblique';
+  t['ArialMT'] = 'Helvetica';
+  t['Courier-Bold'] = 'Courier-Bold';
+  t['Courier-BoldItalic'] = 'Courier-BoldOblique';
+  t['Courier-Italic'] = 'Courier-Oblique';
+  t['CourierNew'] = 'Courier';
+  t['CourierNew-Bold'] = 'Courier-Bold';
+  t['CourierNew-BoldItalic'] = 'Courier-BoldOblique';
+  t['CourierNew-Italic'] = 'Courier-Oblique';
+  t['CourierNewPS-BoldItalicMT'] = 'Courier-BoldOblique';
+  t['CourierNewPS-BoldMT'] = 'Courier-Bold';
+  t['CourierNewPS-ItalicMT'] = 'Courier-Oblique';
+  t['CourierNewPSMT'] = 'Courier';
+  t['Helvetica'] = 'Helvetica';
+  t['Helvetica-Bold'] = 'Helvetica-Bold';
+  t['Helvetica-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['Helvetica-BoldOblique'] = 'Helvetica-BoldOblique';
+  t['Helvetica-Italic'] = 'Helvetica-Oblique';
+  t['Helvetica-Oblique'] = 'Helvetica-Oblique';
+  t['SegoeUISymbol'] = 'Helvetica';
+  t['Symbol-Bold'] = 'Symbol';
+  t['Symbol-BoldItalic'] = 'Symbol';
+  t['Symbol-Italic'] = 'Symbol';
+  t['TimesNewRoman'] = 'Times-Roman';
+  t['TimesNewRoman-Bold'] = 'Times-Bold';
+  t['TimesNewRoman-BoldItalic'] = 'Times-BoldItalic';
+  t['TimesNewRoman-Italic'] = 'Times-Italic';
+  t['TimesNewRomanPS'] = 'Times-Roman';
+  t['TimesNewRomanPS-Bold'] = 'Times-Bold';
+  t['TimesNewRomanPS-BoldItalic'] = 'Times-BoldItalic';
+  t['TimesNewRomanPS-BoldItalicMT'] = 'Times-BoldItalic';
+  t['TimesNewRomanPS-BoldMT'] = 'Times-Bold';
+  t['TimesNewRomanPS-Italic'] = 'Times-Italic';
+  t['TimesNewRomanPS-ItalicMT'] = 'Times-Italic';
+  t['TimesNewRomanPSMT'] = 'Times-Roman';
+  t['TimesNewRomanPSMT-Bold'] = 'Times-Bold';
+  t['TimesNewRomanPSMT-BoldItalic'] = 'Times-BoldItalic';
+  t['TimesNewRomanPSMT-Italic'] = 'Times-Italic';
+});
+exports.getStdFontMap = getStdFontMap;
+var getNonStdFontMap = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t['Calibri'] = 'Helvetica';
+  t['Calibri-Bold'] = 'Helvetica-Bold';
+  t['Calibri-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['Calibri-Italic'] = 'Helvetica-Oblique';
+  t['CenturyGothic'] = 'Helvetica';
+  t['CenturyGothic-Bold'] = 'Helvetica-Bold';
+  t['CenturyGothic-BoldItalic'] = 'Helvetica-BoldOblique';
+  t['CenturyGothic-Italic'] = 'Helvetica-Oblique';
+  t['ComicSansMS'] = 'Comic Sans MS';
+  t['ComicSansMS-Bold'] = 'Comic Sans MS-Bold';
+  t['ComicSansMS-BoldItalic'] = 'Comic Sans MS-BoldItalic';
+  t['ComicSansMS-Italic'] = 'Comic Sans MS-Italic';
+  t['LucidaConsole'] = 'Courier';
+  t['LucidaConsole-Bold'] = 'Courier-Bold';
+  t['LucidaConsole-BoldItalic'] = 'Courier-BoldOblique';
+  t['LucidaConsole-Italic'] = 'Courier-Oblique';
+  t['LucidaSans-Demi'] = 'Helvetica-Bold';
+  t['MS-Gothic'] = 'MS Gothic';
+  t['MS-Gothic-Bold'] = 'MS Gothic-Bold';
+  t['MS-Gothic-BoldItalic'] = 'MS Gothic-BoldItalic';
+  t['MS-Gothic-Italic'] = 'MS Gothic-Italic';
+  t['MS-Mincho'] = 'MS Mincho';
+  t['MS-Mincho-Bold'] = 'MS Mincho-Bold';
+  t['MS-Mincho-BoldItalic'] = 'MS Mincho-BoldItalic';
+  t['MS-Mincho-Italic'] = 'MS Mincho-Italic';
+  t['MS-PGothic'] = 'MS PGothic';
+  t['MS-PGothic-Bold'] = 'MS PGothic-Bold';
+  t['MS-PGothic-BoldItalic'] = 'MS PGothic-BoldItalic';
+  t['MS-PGothic-Italic'] = 'MS PGothic-Italic';
+  t['MS-PMincho'] = 'MS PMincho';
+  t['MS-PMincho-Bold'] = 'MS PMincho-Bold';
+  t['MS-PMincho-BoldItalic'] = 'MS PMincho-BoldItalic';
+  t['MS-PMincho-Italic'] = 'MS PMincho-Italic';
+  t['NuptialScript'] = 'Times-Italic';
+  t['Wingdings'] = 'ZapfDingbats';
+});
+exports.getNonStdFontMap = getNonStdFontMap;
+var getSerifFonts = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t['Adobe Jenson'] = true;
+  t['Adobe Text'] = true;
+  t['Albertus'] = true;
+  t['Aldus'] = true;
+  t['Alexandria'] = true;
+  t['Algerian'] = true;
+  t['American Typewriter'] = true;
+  t['Antiqua'] = true;
+  t['Apex'] = true;
+  t['Arno'] = true;
+  t['Aster'] = true;
+  t['Aurora'] = true;
+  t['Baskerville'] = true;
+  t['Bell'] = true;
+  t['Bembo'] = true;
+  t['Bembo Schoolbook'] = true;
+  t['Benguiat'] = true;
+  t['Berkeley Old Style'] = true;
+  t['Bernhard Modern'] = true;
+  t['Berthold City'] = true;
+  t['Bodoni'] = true;
+  t['Bauer Bodoni'] = true;
+  t['Book Antiqua'] = true;
+  t['Bookman'] = true;
+  t['Bordeaux Roman'] = true;
+  t['Californian FB'] = true;
+  t['Calisto'] = true;
+  t['Calvert'] = true;
+  t['Capitals'] = true;
+  t['Cambria'] = true;
+  t['Cartier'] = true;
+  t['Caslon'] = true;
+  t['Catull'] = true;
+  t['Centaur'] = true;
+  t['Century Old Style'] = true;
+  t['Century Schoolbook'] = true;
+  t['Chaparral'] = true;
+  t['Charis SIL'] = true;
+  t['Cheltenham'] = true;
+  t['Cholla Slab'] = true;
+  t['Clarendon'] = true;
+  t['Clearface'] = true;
+  t['Cochin'] = true;
+  t['Colonna'] = true;
+  t['Computer Modern'] = true;
+  t['Concrete Roman'] = true;
+  t['Constantia'] = true;
+  t['Cooper Black'] = true;
+  t['Corona'] = true;
+  t['Ecotype'] = true;
+  t['Egyptienne'] = true;
+  t['Elephant'] = true;
+  t['Excelsior'] = true;
+  t['Fairfield'] = true;
+  t['FF Scala'] = true;
+  t['Folkard'] = true;
+  t['Footlight'] = true;
+  t['FreeSerif'] = true;
+  t['Friz Quadrata'] = true;
+  t['Garamond'] = true;
+  t['Gentium'] = true;
+  t['Georgia'] = true;
+  t['Gloucester'] = true;
+  t['Goudy Old Style'] = true;
+  t['Goudy Schoolbook'] = true;
+  t['Goudy Pro Font'] = true;
+  t['Granjon'] = true;
+  t['Guardian Egyptian'] = true;
+  t['Heather'] = true;
+  t['Hercules'] = true;
+  t['High Tower Text'] = true;
+  t['Hiroshige'] = true;
+  t['Hoefler Text'] = true;
+  t['Humana Serif'] = true;
+  t['Imprint'] = true;
+  t['Ionic No. 5'] = true;
+  t['Janson'] = true;
+  t['Joanna'] = true;
+  t['Korinna'] = true;
+  t['Lexicon'] = true;
+  t['Liberation Serif'] = true;
+  t['Linux Libertine'] = true;
+  t['Literaturnaya'] = true;
+  t['Lucida'] = true;
+  t['Lucida Bright'] = true;
+  t['Melior'] = true;
+  t['Memphis'] = true;
+  t['Miller'] = true;
+  t['Minion'] = true;
+  t['Modern'] = true;
+  t['Mona Lisa'] = true;
+  t['Mrs Eaves'] = true;
+  t['MS Serif'] = true;
+  t['Museo Slab'] = true;
+  t['New York'] = true;
+  t['Nimbus Roman'] = true;
+  t['NPS Rawlinson Roadway'] = true;
+  t['NuptialScript'] = true;
+  t['Palatino'] = true;
+  t['Perpetua'] = true;
+  t['Plantin'] = true;
+  t['Plantin Schoolbook'] = true;
+  t['Playbill'] = true;
+  t['Poor Richard'] = true;
+  t['Rawlinson Roadway'] = true;
+  t['Renault'] = true;
+  t['Requiem'] = true;
+  t['Rockwell'] = true;
+  t['Roman'] = true;
+  t['Rotis Serif'] = true;
+  t['Sabon'] = true;
+  t['Scala'] = true;
+  t['Seagull'] = true;
+  t['Sistina'] = true;
+  t['Souvenir'] = true;
+  t['STIX'] = true;
+  t['Stone Informal'] = true;
+  t['Stone Serif'] = true;
+  t['Sylfaen'] = true;
+  t['Times'] = true;
+  t['Trajan'] = true;
+  t['Trinité'] = true;
+  t['Trump Mediaeval'] = true;
+  t['Utopia'] = true;
+  t['Vale Type'] = true;
+  t['Bitstream Vera'] = true;
+  t['Vera Serif'] = true;
+  t['Versailles'] = true;
+  t['Wanted'] = true;
+  t['Weiss'] = true;
+  t['Wide Latin'] = true;
+  t['Windsor'] = true;
+  t['XITS'] = true;
+});
+exports.getSerifFonts = getSerifFonts;
+var getSymbolsFonts = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t['Dingbats'] = true;
+  t['Symbol'] = true;
+  t['ZapfDingbats'] = true;
+});
+exports.getSymbolsFonts = getSymbolsFonts;
+var getGlyphMapForStandardFonts = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t[2] = 10;
+  t[3] = 32;
+  t[4] = 33;
+  t[5] = 34;
+  t[6] = 35;
+  t[7] = 36;
+  t[8] = 37;
+  t[9] = 38;
+  t[10] = 39;
+  t[11] = 40;
+  t[12] = 41;
+  t[13] = 42;
+  t[14] = 43;
+  t[15] = 44;
+  t[16] = 45;
+  t[17] = 46;
+  t[18] = 47;
+  t[19] = 48;
+  t[20] = 49;
+  t[21] = 50;
+  t[22] = 51;
+  t[23] = 52;
+  t[24] = 53;
+  t[25] = 54;
+  t[26] = 55;
+  t[27] = 56;
+  t[28] = 57;
+  t[29] = 58;
+  t[30] = 894;
+  t[31] = 60;
+  t[32] = 61;
+  t[33] = 62;
+  t[34] = 63;
+  t[35] = 64;
+  t[36] = 65;
+  t[37] = 66;
+  t[38] = 67;
+  t[39] = 68;
+  t[40] = 69;
+  t[41] = 70;
+  t[42] = 71;
+  t[43] = 72;
+  t[44] = 73;
+  t[45] = 74;
+  t[46] = 75;
+  t[47] = 76;
+  t[48] = 77;
+  t[49] = 78;
+  t[50] = 79;
+  t[51] = 80;
+  t[52] = 81;
+  t[53] = 82;
+  t[54] = 83;
+  t[55] = 84;
+  t[56] = 85;
+  t[57] = 86;
+  t[58] = 87;
+  t[59] = 88;
+  t[60] = 89;
+  t[61] = 90;
+  t[62] = 91;
+  t[63] = 92;
+  t[64] = 93;
+  t[65] = 94;
+  t[66] = 95;
+  t[67] = 96;
+  t[68] = 97;
+  t[69] = 98;
+  t[70] = 99;
+  t[71] = 100;
+  t[72] = 101;
+  t[73] = 102;
+  t[74] = 103;
+  t[75] = 104;
+  t[76] = 105;
+  t[77] = 106;
+  t[78] = 107;
+  t[79] = 108;
+  t[80] = 109;
+  t[81] = 110;
+  t[82] = 111;
+  t[83] = 112;
+  t[84] = 113;
+  t[85] = 114;
+  t[86] = 115;
+  t[87] = 116;
+  t[88] = 117;
+  t[89] = 118;
+  t[90] = 119;
+  t[91] = 120;
+  t[92] = 121;
+  t[93] = 122;
+  t[94] = 123;
+  t[95] = 124;
+  t[96] = 125;
+  t[97] = 126;
+  t[98] = 196;
+  t[99] = 197;
+  t[100] = 199;
+  t[101] = 201;
+  t[102] = 209;
+  t[103] = 214;
+  t[104] = 220;
+  t[105] = 225;
+  t[106] = 224;
+  t[107] = 226;
+  t[108] = 228;
+  t[109] = 227;
+  t[110] = 229;
+  t[111] = 231;
+  t[112] = 233;
+  t[113] = 232;
+  t[114] = 234;
+  t[115] = 235;
+  t[116] = 237;
+  t[117] = 236;
+  t[118] = 238;
+  t[119] = 239;
+  t[120] = 241;
+  t[121] = 243;
+  t[122] = 242;
+  t[123] = 244;
+  t[124] = 246;
+  t[125] = 245;
+  t[126] = 250;
+  t[127] = 249;
+  t[128] = 251;
+  t[129] = 252;
+  t[130] = 8224;
+  t[131] = 176;
+  t[132] = 162;
+  t[133] = 163;
+  t[134] = 167;
+  t[135] = 8226;
+  t[136] = 182;
+  t[137] = 223;
+  t[138] = 174;
+  t[139] = 169;
+  t[140] = 8482;
+  t[141] = 180;
+  t[142] = 168;
+  t[143] = 8800;
+  t[144] = 198;
+  t[145] = 216;
+  t[146] = 8734;
+  t[147] = 177;
+  t[148] = 8804;
+  t[149] = 8805;
+  t[150] = 165;
+  t[151] = 181;
+  t[152] = 8706;
+  t[153] = 8721;
+  t[154] = 8719;
+  t[156] = 8747;
+  t[157] = 170;
+  t[158] = 186;
+  t[159] = 8486;
+  t[160] = 230;
+  t[161] = 248;
+  t[162] = 191;
+  t[163] = 161;
+  t[164] = 172;
+  t[165] = 8730;
+  t[166] = 402;
+  t[167] = 8776;
+  t[168] = 8710;
+  t[169] = 171;
+  t[170] = 187;
+  t[171] = 8230;
+  t[210] = 218;
+  t[223] = 711;
+  t[224] = 321;
+  t[225] = 322;
+  t[227] = 353;
+  t[229] = 382;
+  t[234] = 253;
+  t[252] = 263;
+  t[253] = 268;
+  t[254] = 269;
+  t[258] = 258;
+  t[260] = 260;
+  t[261] = 261;
+  t[265] = 280;
+  t[266] = 281;
+  t[268] = 283;
+  t[269] = 313;
+  t[275] = 323;
+  t[276] = 324;
+  t[278] = 328;
+  t[284] = 345;
+  t[285] = 346;
+  t[286] = 347;
+  t[292] = 367;
+  t[295] = 377;
+  t[296] = 378;
+  t[298] = 380;
+  t[305] = 963;
+  t[306] = 964;
+  t[307] = 966;
+  t[308] = 8215;
+  t[309] = 8252;
+  t[310] = 8319;
+  t[311] = 8359;
+  t[312] = 8592;
+  t[313] = 8593;
+  t[337] = 9552;
+  t[493] = 1039;
+  t[494] = 1040;
+  t[705] = 1524;
+  t[706] = 8362;
+  t[710] = 64288;
+  t[711] = 64298;
+  t[759] = 1617;
+  t[761] = 1776;
+  t[763] = 1778;
+  t[775] = 1652;
+  t[777] = 1764;
+  t[778] = 1780;
+  t[779] = 1781;
+  t[780] = 1782;
+  t[782] = 771;
+  t[783] = 64726;
+  t[786] = 8363;
+  t[788] = 8532;
+  t[790] = 768;
+  t[791] = 769;
+  t[792] = 768;
+  t[795] = 803;
+  t[797] = 64336;
+  t[798] = 64337;
+  t[799] = 64342;
+  t[800] = 64343;
+  t[801] = 64344;
+  t[802] = 64345;
+  t[803] = 64362;
+  t[804] = 64363;
+  t[805] = 64364;
+  t[2424] = 7821;
+  t[2425] = 7822;
+  t[2426] = 7823;
+  t[2427] = 7824;
+  t[2428] = 7825;
+  t[2429] = 7826;
+  t[2430] = 7827;
+  t[2433] = 7682;
+  t[2678] = 8045;
+  t[2679] = 8046;
+  t[2830] = 1552;
+  t[2838] = 686;
+  t[2840] = 751;
+  t[2842] = 753;
+  t[2843] = 754;
+  t[2844] = 755;
+  t[2846] = 757;
+  t[2856] = 767;
+  t[2857] = 848;
+  t[2858] = 849;
+  t[2862] = 853;
+  t[2863] = 854;
+  t[2864] = 855;
+  t[2865] = 861;
+  t[2866] = 862;
+  t[2906] = 7460;
+  t[2908] = 7462;
+  t[2909] = 7463;
+  t[2910] = 7464;
+  t[2912] = 7466;
+  t[2913] = 7467;
+  t[2914] = 7468;
+  t[2916] = 7470;
+  t[2917] = 7471;
+  t[2918] = 7472;
+  t[2920] = 7474;
+  t[2921] = 7475;
+  t[2922] = 7476;
+  t[2924] = 7478;
+  t[2925] = 7479;
+  t[2926] = 7480;
+  t[2928] = 7482;
+  t[2929] = 7483;
+  t[2930] = 7484;
+  t[2932] = 7486;
+  t[2933] = 7487;
+  t[2934] = 7488;
+  t[2936] = 7490;
+  t[2937] = 7491;
+  t[2938] = 7492;
+  t[2940] = 7494;
+  t[2941] = 7495;
+  t[2942] = 7496;
+  t[2944] = 7498;
+  t[2946] = 7500;
+  t[2948] = 7502;
+  t[2950] = 7504;
+  t[2951] = 7505;
+  t[2952] = 7506;
+  t[2954] = 7508;
+  t[2955] = 7509;
+  t[2956] = 7510;
+  t[2958] = 7512;
+  t[2959] = 7513;
+  t[2960] = 7514;
+  t[2962] = 7516;
+  t[2963] = 7517;
+  t[2964] = 7518;
+  t[2966] = 7520;
+  t[2967] = 7521;
+  t[2968] = 7522;
+  t[2970] = 7524;
+  t[2971] = 7525;
+  t[2972] = 7526;
+  t[2974] = 7528;
+  t[2975] = 7529;
+  t[2976] = 7530;
+  t[2978] = 1537;
+  t[2979] = 1538;
+  t[2980] = 1539;
+  t[2982] = 1549;
+  t[2983] = 1551;
+  t[2984] = 1552;
+  t[2986] = 1554;
+  t[2987] = 1555;
+  t[2988] = 1556;
+  t[2990] = 1623;
+  t[2991] = 1624;
+  t[2995] = 1775;
+  t[2999] = 1791;
+  t[3002] = 64290;
+  t[3003] = 64291;
+  t[3004] = 64292;
+  t[3006] = 64294;
+  t[3007] = 64295;
+  t[3008] = 64296;
+  t[3011] = 1900;
+  t[3014] = 8223;
+  t[3015] = 8244;
+  t[3017] = 7532;
+  t[3018] = 7533;
+  t[3019] = 7534;
+  t[3075] = 7590;
+  t[3076] = 7591;
+  t[3079] = 7594;
+  t[3080] = 7595;
+  t[3083] = 7598;
+  t[3084] = 7599;
+  t[3087] = 7602;
+  t[3088] = 7603;
+  t[3091] = 7606;
+  t[3092] = 7607;
+  t[3095] = 7610;
+  t[3096] = 7611;
+  t[3099] = 7614;
+  t[3100] = 7615;
+  t[3103] = 7618;
+  t[3104] = 7619;
+  t[3107] = 8337;
+  t[3108] = 8338;
+  t[3116] = 1884;
+  t[3119] = 1885;
+  t[3120] = 1885;
+  t[3123] = 1886;
+  t[3124] = 1886;
+  t[3127] = 1887;
+  t[3128] = 1887;
+  t[3131] = 1888;
+  t[3132] = 1888;
+  t[3135] = 1889;
+  t[3136] = 1889;
+  t[3139] = 1890;
+  t[3140] = 1890;
+  t[3143] = 1891;
+  t[3144] = 1891;
+  t[3147] = 1892;
+  t[3148] = 1892;
+  t[3153] = 580;
+  t[3154] = 581;
+  t[3157] = 584;
+  t[3158] = 585;
+  t[3161] = 588;
+  t[3162] = 589;
+  t[3165] = 891;
+  t[3166] = 892;
+  t[3169] = 1274;
+  t[3170] = 1275;
+  t[3173] = 1278;
+  t[3174] = 1279;
+  t[3181] = 7622;
+  t[3182] = 7623;
+  t[3282] = 11799;
+  t[3316] = 578;
+  t[3379] = 42785;
+  t[3393] = 1159;
+  t[3416] = 8377;
+});
+exports.getGlyphMapForStandardFonts = getGlyphMapForStandardFonts;
+var getSupplementalGlyphMapForArialBlack = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t[227] = 322;
+  t[264] = 261;
+  t[291] = 346;
+});
+exports.getSupplementalGlyphMapForArialBlack = getSupplementalGlyphMapForArialBlack;
+var getSupplementalGlyphMapForCalibri = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t[1] = 32;
+  t[4] = 65;
+  t[17] = 66;
+  t[18] = 67;
+  t[24] = 68;
+  t[28] = 69;
+  t[38] = 70;
+  t[39] = 71;
+  t[44] = 72;
+  t[47] = 73;
+  t[58] = 74;
+  t[60] = 75;
+  t[62] = 76;
+  t[68] = 77;
+  t[69] = 78;
+  t[75] = 79;
+  t[87] = 80;
+  t[89] = 81;
+  t[90] = 82;
+  t[94] = 83;
+  t[100] = 84;
+  t[104] = 85;
+  t[115] = 86;
+  t[116] = 87;
+  t[121] = 88;
+  t[122] = 89;
+  t[127] = 90;
+  t[258] = 97;
+  t[268] = 261;
+  t[271] = 98;
+  t[272] = 99;
+  t[273] = 263;
+  t[282] = 100;
+  t[286] = 101;
+  t[295] = 281;
+  t[296] = 102;
+  t[336] = 103;
+  t[346] = 104;
+  t[349] = 105;
+  t[361] = 106;
+  t[364] = 107;
+  t[367] = 108;
+  t[371] = 322;
+  t[373] = 109;
+  t[374] = 110;
+  t[381] = 111;
+  t[383] = 243;
+  t[393] = 112;
+  t[395] = 113;
+  t[396] = 114;
+  t[400] = 115;
+  t[401] = 347;
+  t[410] = 116;
+  t[437] = 117;
+  t[448] = 118;
+  t[449] = 119;
+  t[454] = 120;
+  t[455] = 121;
+  t[460] = 122;
+  t[463] = 380;
+  t[853] = 44;
+  t[855] = 58;
+  t[856] = 46;
+  t[876] = 47;
+  t[878] = 45;
+  t[882] = 45;
+  t[894] = 40;
+  t[895] = 41;
+  t[896] = 91;
+  t[897] = 93;
+  t[923] = 64;
+  t[1004] = 48;
+  t[1005] = 49;
+  t[1006] = 50;
+  t[1007] = 51;
+  t[1008] = 52;
+  t[1009] = 53;
+  t[1010] = 54;
+  t[1011] = 55;
+  t[1012] = 56;
+  t[1013] = 57;
+  t[1081] = 37;
+  t[1085] = 43;
+  t[1086] = 45;
+});
+exports.getSupplementalGlyphMapForCalibri = getSupplementalGlyphMapForCalibri;
+
+/***/ }),
+/* 180 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+var getLookupTableFactory = __w_pdfjs_require__(154).getLookupTableFactory;
+var getSpecialPUASymbols = getLookupTableFactory(function (t) {
+ t[63721] = 0x00A9;
+ t[63193] = 0x00A9;
+ t[63720] = 0x00AE;
+ t[63194] = 0x00AE;
+ t[63722] = 0x2122;
+ t[63195] = 0x2122;
+ t[63729] = 0x23A7;
+ t[63730] = 0x23A8;
+ t[63731] = 0x23A9;
+ t[63740] = 0x23AB;
+ t[63741] = 0x23AC;
+ t[63742] = 0x23AD;
+ t[63726] = 0x23A1;
+ t[63727] = 0x23A2;
+ t[63728] = 0x23A3;
+ t[63737] = 0x23A4;
+ t[63738] = 0x23A5;
+ t[63739] = 0x23A6;
+ t[63723] = 0x239B;
+ t[63724] = 0x239C;
+ t[63725] = 0x239D;
+ t[63734] = 0x239E;
+ t[63735] = 0x239F;
+ t[63736] = 0x23A0;
+});
+function mapSpecialUnicodeValues(code) {
+ if (code >= 0xFFF0 && code <= 0xFFFF) {
+  return 0;
+ } else if (code >= 0xF600 && code <= 0xF8FF) {
+  return getSpecialPUASymbols()[code] || code;
+ } else if (code === 0x00AD) {
+  return 0x002D;
+ }
+ return code;
+}
+function getUnicodeForGlyph(name, glyphsUnicodeMap) {
+ var unicode = glyphsUnicodeMap[name];
+ if (unicode !== undefined) {
+  return unicode;
+ }
+ if (!name) {
+  return -1;
+ }
+ if (name[0] === 'u') {
+  var nameLen = name.length, hexStr;
+  if (nameLen === 7 && name[1] === 'n' && name[2] === 'i') {
+   hexStr = name.substring(3);
+  } else if (nameLen >= 5 && nameLen <= 7) {
+   hexStr = name.substring(1);
+  } else {
+   return -1;
+  }
+  if (hexStr === hexStr.toUpperCase()) {
+   unicode = parseInt(hexStr, 16);
+   if (unicode >= 0) {
+    return unicode;
+   }
+  }
+ }
+ return -1;
+}
+var UnicodeRanges = [
+ {
+  'begin': 0x0000,
+  'end': 0x007F
+ },
+ {
+  'begin': 0x0080,
+  'end': 0x00FF
+ },
+ {
+  'begin': 0x0100,
+  'end': 0x017F
+ },
+ {
+  'begin': 0x0180,
+  'end': 0x024F
+ },
+ {
+  'begin': 0x0250,
+  'end': 0x02AF
+ },
+ {
+  'begin': 0x02B0,
+  'end': 0x02FF
+ },
+ {
+  'begin': 0x0300,
+  'end': 0x036F
+ },
+ {
+  'begin': 0x0370,
+  'end': 0x03FF
+ },
+ {
+  'begin': 0x2C80,
+  'end': 0x2CFF
+ },
+ {
+  'begin': 0x0400,
+  'end': 0x04FF
+ },
+ {
+  'begin': 0x0530,
+  'end': 0x058F
+ },
+ {
+  'begin': 0x0590,
+  'end': 0x05FF
+ },
+ {
+  'begin': 0xA500,
+  'end': 0xA63F
+ },
+ {
+  'begin': 0x0600,
+  'end': 0x06FF
+ },
+ {
+  'begin': 0x07C0,
+  'end': 0x07FF
+ },
+ {
+  'begin': 0x0900,
+  'end': 0x097F
+ },
+ {
+  'begin': 0x0980,
+  'end': 0x09FF
+ },
+ {
+  'begin': 0x0A00,
+  'end': 0x0A7F
+ },
+ {
+  'begin': 0x0A80,
+  'end': 0x0AFF
+ },
+ {
+  'begin': 0x0B00,
+  'end': 0x0B7F
+ },
+ {
+  'begin': 0x0B80,
+  'end': 0x0BFF
+ },
+ {
+  'begin': 0x0C00,
+  'end': 0x0C7F
+ },
+ {
+  'begin': 0x0C80,
+  'end': 0x0CFF
+ },
+ {
+  'begin': 0x0D00,
+  'end': 0x0D7F
+ },
+ {
+  'begin': 0x0E00,
+  'end': 0x0E7F
+ },
+ {
+  'begin': 0x0E80,
+  'end': 0x0EFF
+ },
+ {
+  'begin': 0x10A0,
+  'end': 0x10FF
+ },
+ {
+  'begin': 0x1B00,
+  'end': 0x1B7F
+ },
+ {
+  'begin': 0x1100,
+  'end': 0x11FF
+ },
+ {
+  'begin': 0x1E00,
+  'end': 0x1EFF
+ },
+ {
+  'begin': 0x1F00,
+  'end': 0x1FFF
+ },
+ {
+  'begin': 0x2000,
+  'end': 0x206F
+ },
+ {
+  'begin': 0x2070,
+  'end': 0x209F
+ },
+ {
+  'begin': 0x20A0,
+  'end': 0x20CF
+ },
+ {
+  'begin': 0x20D0,
+  'end': 0x20FF
+ },
+ {
+  'begin': 0x2100,
+  'end': 0x214F
+ },
+ {
+  'begin': 0x2150,
+  'end': 0x218F
+ },
+ {
+  'begin': 0x2190,
+  'end': 0x21FF
+ },
+ {
+  'begin': 0x2200,
+  'end': 0x22FF
+ },
+ {
+  'begin': 0x2300,
+  'end': 0x23FF
+ },
+ {
+  'begin': 0x2400,
+  'end': 0x243F
+ },
+ {
+  'begin': 0x2440,
+  'end': 0x245F
+ },
+ {
+  'begin': 0x2460,
+  'end': 0x24FF
+ },
+ {
+  'begin': 0x2500,
+  'end': 0x257F
+ },
+ {
+  'begin': 0x2580,
+  'end': 0x259F
+ },
+ {
+  'begin': 0x25A0,
+  'end': 0x25FF
+ },
+ {
+  'begin': 0x2600,
+  'end': 0x26FF
+ },
+ {
+  'begin': 0x2700,
+  'end': 0x27BF
+ },
+ {
+  'begin': 0x3000,
+  'end': 0x303F
+ },
+ {
+  'begin': 0x3040,
+  'end': 0x309F
+ },
+ {
+  'begin': 0x30A0,
+  'end': 0x30FF
+ },
+ {
+  'begin': 0x3100,
+  'end': 0x312F
+ },
+ {
+  'begin': 0x3130,
+  'end': 0x318F
+ },
+ {
+  'begin': 0xA840,
+  'end': 0xA87F
+ },
+ {
+  'begin': 0x3200,
+  'end': 0x32FF
+ },
+ {
+  'begin': 0x3300,
+  'end': 0x33FF
+ },
+ {
+  'begin': 0xAC00,
+  'end': 0xD7AF
+ },
+ {
+  'begin': 0xD800,
+  'end': 0xDFFF
+ },
+ {
+  'begin': 0x10900,
+  'end': 0x1091F
+ },
+ {
+  'begin': 0x4E00,
+  'end': 0x9FFF
+ },
+ {
+  'begin': 0xE000,
+  'end': 0xF8FF
+ },
+ {
+  'begin': 0x31C0,
+  'end': 0x31EF
+ },
+ {
+  'begin': 0xFB00,
+  'end': 0xFB4F
+ },
+ {
+  'begin': 0xFB50,
+  'end': 0xFDFF
+ },
+ {
+  'begin': 0xFE20,
+  'end': 0xFE2F
+ },
+ {
+  'begin': 0xFE10,
+  'end': 0xFE1F
+ },
+ {
+  'begin': 0xFE50,
+  'end': 0xFE6F
+ },
+ {
+  'begin': 0xFE70,
+  'end': 0xFEFF
+ },
+ {
+  'begin': 0xFF00,
+  'end': 0xFFEF
+ },
+ {
+  'begin': 0xFFF0,
+  'end': 0xFFFF
+ },
+ {
+  'begin': 0x0F00,
+  'end': 0x0FFF
+ },
+ {
+  'begin': 0x0700,
+  'end': 0x074F
+ },
+ {
+  'begin': 0x0780,
+  'end': 0x07BF
+ },
+ {
+  'begin': 0x0D80,
+  'end': 0x0DFF
+ },
+ {
+  'begin': 0x1000,
+  'end': 0x109F
+ },
+ {
+  'begin': 0x1200,
+  'end': 0x137F
+ },
+ {
+  'begin': 0x13A0,
+  'end': 0x13FF
+ },
+ {
+  'begin': 0x1400,
+  'end': 0x167F
+ },
+ {
+  'begin': 0x1680,
+  'end': 0x169F
+ },
+ {
+  'begin': 0x16A0,
+  'end': 0x16FF
+ },
+ {
+  'begin': 0x1780,
+  'end': 0x17FF
+ },
+ {
+  'begin': 0x1800,
+  'end': 0x18AF
+ },
+ {
+  'begin': 0x2800,
+  'end': 0x28FF
+ },
+ {
+  'begin': 0xA000,
+  'end': 0xA48F
+ },
+ {
+  'begin': 0x1700,
+  'end': 0x171F
+ },
+ {
+  'begin': 0x10300,
+  'end': 0x1032F
+ },
+ {
+  'begin': 0x10330,
+  'end': 0x1034F
+ },
+ {
+  'begin': 0x10400,
+  'end': 0x1044F
+ },
+ {
+  'begin': 0x1D000,
+  'end': 0x1D0FF
+ },
+ {
+  'begin': 0x1D400,
+  'end': 0x1D7FF
+ },
+ {
+  'begin': 0xFF000,
+  'end': 0xFFFFD
+ },
+ {
+  'begin': 0xFE00,
+  'end': 0xFE0F
+ },
+ {
+  'begin': 0xE0000,
+  'end': 0xE007F
+ },
+ {
+  'begin': 0x1900,
+  'end': 0x194F
+ },
+ {
+  'begin': 0x1950,
+  'end': 0x197F
+ },
+ {
+  'begin': 0x1980,
+  'end': 0x19DF
+ },
+ {
+  'begin': 0x1A00,
+  'end': 0x1A1F
+ },
+ {
+  'begin': 0x2C00,
+  'end': 0x2C5F
+ },
+ {
+  'begin': 0x2D30,
+  'end': 0x2D7F
+ },
+ {
+  'begin': 0x4DC0,
+  'end': 0x4DFF
+ },
+ {
+  'begin': 0xA800,
+  'end': 0xA82F
+ },
+ {
+  'begin': 0x10000,
+  'end': 0x1007F
+ },
+ {
+  'begin': 0x10140,
+  'end': 0x1018F
+ },
+ {
+  'begin': 0x10380,
+  'end': 0x1039F
+ },
+ {
+  'begin': 0x103A0,
+  'end': 0x103DF
+ },
+ {
+  'begin': 0x10450,
+  'end': 0x1047F
+ },
+ {
+  'begin': 0x10480,
+  'end': 0x104AF
+ },
+ {
+  'begin': 0x10800,
+  'end': 0x1083F
+ },
+ {
+  'begin': 0x10A00,
+  'end': 0x10A5F
+ },
+ {
+  'begin': 0x1D300,
+  'end': 0x1D35F
+ },
+ {
+  'begin': 0x12000,
+  'end': 0x123FF
+ },
+ {
+  'begin': 0x1D360,
+  'end': 0x1D37F
+ },
+ {
+  'begin': 0x1B80,
+  'end': 0x1BBF
+ },
+ {
+  'begin': 0x1C00,
+  'end': 0x1C4F
+ },
+ {
+  'begin': 0x1C50,
+  'end': 0x1C7F
+ },
+ {
+  'begin': 0xA880,
+  'end': 0xA8DF
+ },
+ {
+  'begin': 0xA900,
+  'end': 0xA92F
+ },
+ {
+  'begin': 0xA930,
+  'end': 0xA95F
+ },
+ {
+  'begin': 0xAA00,
+  'end': 0xAA5F
+ },
+ {
+  'begin': 0x10190,
+  'end': 0x101CF
+ },
+ {
+  'begin': 0x101D0,
+  'end': 0x101FF
+ },
+ {
+  'begin': 0x102A0,
+  'end': 0x102DF
+ },
+ {
+  'begin': 0x1F030,
+  'end': 0x1F09F
+ }
+];
+function getUnicodeRangeFor(value) {
+ for (var i = 0, ii = UnicodeRanges.length; i < ii; i++) {
+  var range = UnicodeRanges[i];
+  if (value >= range.begin && value < range.end) {
+   return i;
+  }
+ }
+ return -1;
+}
+function isRTLRangeFor(value) {
+ var range = UnicodeRanges[13];
+ if (value >= range.begin && value < range.end) {
+  return true;
+ }
+ range = UnicodeRanges[11];
+ if (value >= range.begin && value < range.end) {
+  return true;
+ }
+ return false;
+}
+var getNormalizedUnicodes = getLookupTableFactory(function (t) {
+ t['\u00A8'] = '\u0020\u0308';
+ t['\u00AF'] = '\u0020\u0304';
+ t['\u00B4'] = '\u0020\u0301';
+ t['\u00B5'] = '\u03BC';
+ t['\u00B8'] = '\u0020\u0327';
+ t['\u0132'] = '\u0049\u004A';
+ t['\u0133'] = '\u0069\u006A';
+ t['\u013F'] = '\u004C\u00B7';
+ t['\u0140'] = '\u006C\u00B7';
+ t['\u0149'] = '\u02BC\u006E';
+ t['\u017F'] = '\u0073';
+ t['\u01C4'] = '\u0044\u017D';
+ t['\u01C5'] = '\u0044\u017E';
+ t['\u01C6'] = '\u0064\u017E';
+ t['\u01C7'] = '\u004C\u004A';
+ t['\u01C8'] = '\u004C\u006A';
+ t['\u01C9'] = '\u006C\u006A';
+ t['\u01CA'] = '\u004E\u004A';
+ t['\u01CB'] = '\u004E\u006A';
+ t['\u01CC'] = '\u006E\u006A';
+ t['\u01F1'] = '\u0044\u005A';
+ t['\u01F2'] = '\u0044\u007A';
+ t['\u01F3'] = '\u0064\u007A';
+ t['\u02D8'] = '\u0020\u0306';
+ t['\u02D9'] = '\u0020\u0307';
+ t['\u02DA'] = '\u0020\u030A';
+ t['\u02DB'] = '\u0020\u0328';
+ t['\u02DC'] = '\u0020\u0303';
+ t['\u02DD'] = '\u0020\u030B';
+ t['\u037A'] = '\u0020\u0345';
+ t['\u0384'] = '\u0020\u0301';
+ t['\u03D0'] = '\u03B2';
+ t['\u03D1'] = '\u03B8';
+ t['\u03D2'] = '\u03A5';
+ t['\u03D5'] = '\u03C6';
+ t['\u03D6'] = '\u03C0';
+ t['\u03F0'] = '\u03BA';
+ t['\u03F1'] = '\u03C1';
+ t['\u03F2'] = '\u03C2';
+ t['\u03F4'] = '\u0398';
+ t['\u03F5'] = '\u03B5';
+ t['\u03F9'] = '\u03A3';
+ t['\u0587'] = '\u0565\u0582';
+ t['\u0675'] = '\u0627\u0674';
+ t['\u0676'] = '\u0648\u0674';
+ t['\u0677'] = '\u06C7\u0674';
+ t['\u0678'] = '\u064A\u0674';
+ t['\u0E33'] = '\u0E4D\u0E32';
+ t['\u0EB3'] = '\u0ECD\u0EB2';
+ t['\u0EDC'] = '\u0EAB\u0E99';
+ t['\u0EDD'] = '\u0EAB\u0EA1';
+ t['\u0F77'] = '\u0FB2\u0F81';
+ t['\u0F79'] = '\u0FB3\u0F81';
+ t['\u1E9A'] = '\u0061\u02BE';
+ t['\u1FBD'] = '\u0020\u0313';
+ t['\u1FBF'] = '\u0020\u0313';
+ t['\u1FC0'] = '\u0020\u0342';
+ t['\u1FFE'] = '\u0020\u0314';
+ t['\u2002'] = '\u0020';
+ t['\u2003'] = '\u0020';
+ t['\u2004'] = '\u0020';
+ t['\u2005'] = '\u0020';
+ t['\u2006'] = '\u0020';
+ t['\u2008'] = '\u0020';
+ t['\u2009'] = '\u0020';
+ t['\u200A'] = '\u0020';
+ t['\u2017'] = '\u0020\u0333';
+ t['\u2024'] = '\u002E';
+ t['\u2025'] = '\u002E\u002E';
+ t['\u2026'] = '\u002E\u002E\u002E';
+ t['\u2033'] = '\u2032\u2032';
+ t['\u2034'] = '\u2032\u2032\u2032';
+ t['\u2036'] = '\u2035\u2035';
+ t['\u2037'] = '\u2035\u2035\u2035';
+ t['\u203C'] = '\u0021\u0021';
+ t['\u203E'] = '\u0020\u0305';
+ t['\u2047'] = '\u003F\u003F';
+ t['\u2048'] = '\u003F\u0021';
+ t['\u2049'] = '\u0021\u003F';
+ t['\u2057'] = '\u2032\u2032\u2032\u2032';
+ t['\u205F'] = '\u0020';
+ t['\u20A8'] = '\u0052\u0073';
+ t['\u2100'] = '\u0061\u002F\u0063';
+ t['\u2101'] = '\u0061\u002F\u0073';
+ t['\u2103'] = '\u00B0\u0043';
+ t['\u2105'] = '\u0063\u002F\u006F';
+ t['\u2106'] = '\u0063\u002F\u0075';
+ t['\u2107'] = '\u0190';
+ t['\u2109'] = '\u00B0\u0046';
+ t['\u2116'] = '\u004E\u006F';
+ t['\u2121'] = '\u0054\u0045\u004C';
+ t['\u2135'] = '\u05D0';
+ t['\u2136'] = '\u05D1';
+ t['\u2137'] = '\u05D2';
+ t['\u2138'] = '\u05D3';
+ t['\u213B'] = '\u0046\u0041\u0058';
+ t['\u2160'] = '\u0049';
+ t['\u2161'] = '\u0049\u0049';
+ t['\u2162'] = '\u0049\u0049\u0049';
+ t['\u2163'] = '\u0049\u0056';
+ t['\u2164'] = '\u0056';
+ t['\u2165'] = '\u0056\u0049';
+ t['\u2166'] = '\u0056\u0049\u0049';
+ t['\u2167'] = '\u0056\u0049\u0049\u0049';
+ t['\u2168'] = '\u0049\u0058';
+ t['\u2169'] = '\u0058';
+ t['\u216A'] = '\u0058\u0049';
+ t['\u216B'] = '\u0058\u0049\u0049';
+ t['\u216C'] = '\u004C';
+ t['\u216D'] = '\u0043';
+ t['\u216E'] = '\u0044';
+ t['\u216F'] = '\u004D';
+ t['\u2170'] = '\u0069';
+ t['\u2171'] = '\u0069\u0069';
+ t['\u2172'] = '\u0069\u0069\u0069';
+ t['\u2173'] = '\u0069\u0076';
+ t['\u2174'] = '\u0076';
+ t['\u2175'] = '\u0076\u0069';
+ t['\u2176'] = '\u0076\u0069\u0069';
+ t['\u2177'] = '\u0076\u0069\u0069\u0069';
+ t['\u2178'] = '\u0069\u0078';
+ t['\u2179'] = '\u0078';
+ t['\u217A'] = '\u0078\u0069';
+ t['\u217B'] = '\u0078\u0069\u0069';
+ t['\u217C'] = '\u006C';
+ t['\u217D'] = '\u0063';
+ t['\u217E'] = '\u0064';
+ t['\u217F'] = '\u006D';
+ t['\u222C'] = '\u222B\u222B';
+ t['\u222D'] = '\u222B\u222B\u222B';
+ t['\u222F'] = '\u222E\u222E';
+ t['\u2230'] = '\u222E\u222E\u222E';
+ t['\u2474'] = '\u0028\u0031\u0029';
+ t['\u2475'] = '\u0028\u0032\u0029';
+ t['\u2476'] = '\u0028\u0033\u0029';
+ t['\u2477'] = '\u0028\u0034\u0029';
+ t['\u2478'] = '\u0028\u0035\u0029';
+ t['\u2479'] = '\u0028\u0036\u0029';
+ t['\u247A'] = '\u0028\u0037\u0029';
+ t['\u247B'] = '\u0028\u0038\u0029';
+ t['\u247C'] = '\u0028\u0039\u0029';
+ t['\u247D'] = '\u0028\u0031\u0030\u0029';
+ t['\u247E'] = '\u0028\u0031\u0031\u0029';
+ t['\u247F'] = '\u0028\u0031\u0032\u0029';
+ t['\u2480'] = '\u0028\u0031\u0033\u0029';
+ t['\u2481'] = '\u0028\u0031\u0034\u0029';
+ t['\u2482'] = '\u0028\u0031\u0035\u0029';
+ t['\u2483'] = '\u0028\u0031\u0036\u0029';
+ t['\u2484'] = '\u0028\u0031\u0037\u0029';
+ t['\u2485'] = '\u0028\u0031\u0038\u0029';
+ t['\u2486'] = '\u0028\u0031\u0039\u0029';
+ t['\u2487'] = '\u0028\u0032\u0030\u0029';
+ t['\u2488'] = '\u0031\u002E';
+ t['\u2489'] = '\u0032\u002E';
+ t['\u248A'] = '\u0033\u002E';
+ t['\u248B'] = '\u0034\u002E';
+ t['\u248C'] = '\u0035\u002E';
+ t['\u248D'] = '\u0036\u002E';
+ t['\u248E'] = '\u0037\u002E';
+ t['\u248F'] = '\u0038\u002E';
+ t['\u2490'] = '\u0039\u002E';
+ t['\u2491'] = '\u0031\u0030\u002E';
+ t['\u2492'] = '\u0031\u0031\u002E';
+ t['\u2493'] = '\u0031\u0032\u002E';
+ t['\u2494'] = '\u0031\u0033\u002E';
+ t['\u2495'] = '\u0031\u0034\u002E';
+ t['\u2496'] = '\u0031\u0035\u002E';
+ t['\u2497'] = '\u0031\u0036\u002E';
+ t['\u2498'] = '\u0031\u0037\u002E';
+ t['\u2499'] = '\u0031\u0038\u002E';
+ t['\u249A'] = '\u0031\u0039\u002E';
+ t['\u249B'] = '\u0032\u0030\u002E';
+ t['\u249C'] = '\u0028\u0061\u0029';
+ t['\u249D'] = '\u0028\u0062\u0029';
+ t['\u249E'] = '\u0028\u0063\u0029';
+ t['\u249F'] = '\u0028\u0064\u0029';
+ t['\u24A0'] = '\u0028\u0065\u0029';
+ t['\u24A1'] = '\u0028\u0066\u0029';
+ t['\u24A2'] = '\u0028\u0067\u0029';
+ t['\u24A3'] = '\u0028\u0068\u0029';
+ t['\u24A4'] = '\u0028\u0069\u0029';
+ t['\u24A5'] = '\u0028\u006A\u0029';
+ t['\u24A6'] = '\u0028\u006B\u0029';
+ t['\u24A7'] = '\u0028\u006C\u0029';
+ t['\u24A8'] = '\u0028\u006D\u0029';
+ t['\u24A9'] = '\u0028\u006E\u0029';
+ t['\u24AA'] = '\u0028\u006F\u0029';
+ t['\u24AB'] = '\u0028\u0070\u0029';
+ t['\u24AC'] = '\u0028\u0071\u0029';
+ t['\u24AD'] = '\u0028\u0072\u0029';
+ t['\u24AE'] = '\u0028\u0073\u0029';
+ t['\u24AF'] = '\u0028\u0074\u0029';
+ t['\u24B0'] = '\u0028\u0075\u0029';
+ t['\u24B1'] = '\u0028\u0076\u0029';
+ t['\u24B2'] = '\u0028\u0077\u0029';
+ t['\u24B3'] = '\u0028\u0078\u0029';
+ t['\u24B4'] = '\u0028\u0079\u0029';
+ t['\u24B5'] = '\u0028\u007A\u0029';
+ t['\u2A0C'] = '\u222B\u222B\u222B\u222B';
+ t['\u2A74'] = '\u003A\u003A\u003D';
+ t['\u2A75'] = '\u003D\u003D';
+ t['\u2A76'] = '\u003D\u003D\u003D';
+ t['\u2E9F'] = '\u6BCD';
+ t['\u2EF3'] = '\u9F9F';
+ t['\u2F00'] = '\u4E00';
+ t['\u2F01'] = '\u4E28';
+ t['\u2F02'] = '\u4E36';
+ t['\u2F03'] = '\u4E3F';
+ t['\u2F04'] = '\u4E59';
+ t['\u2F05'] = '\u4E85';
+ t['\u2F06'] = '\u4E8C';
+ t['\u2F07'] = '\u4EA0';
+ t['\u2F08'] = '\u4EBA';
+ t['\u2F09'] = '\u513F';
+ t['\u2F0A'] = '\u5165';
+ t['\u2F0B'] = '\u516B';
+ t['\u2F0C'] = '\u5182';
+ t['\u2F0D'] = '\u5196';
+ t['\u2F0E'] = '\u51AB';
+ t['\u2F0F'] = '\u51E0';
+ t['\u2F10'] = '\u51F5';
+ t['\u2F11'] = '\u5200';
+ t['\u2F12'] = '\u529B';
+ t['\u2F13'] = '\u52F9';
+ t['\u2F14'] = '\u5315';
+ t['\u2F15'] = '\u531A';
+ t['\u2F16'] = '\u5338';
+ t['\u2F17'] = '\u5341';
+ t['\u2F18'] = '\u535C';
+ t['\u2F19'] = '\u5369';
+ t['\u2F1A'] = '\u5382';
+ t['\u2F1B'] = '\u53B6';
+ t['\u2F1C'] = '\u53C8';
+ t['\u2F1D'] = '\u53E3';
+ t['\u2F1E'] = '\u56D7';
+ t['\u2F1F'] = '\u571F';
+ t['\u2F20'] = '\u58EB';
+ t['\u2F21'] = '\u5902';
+ t['\u2F22'] = '\u590A';
+ t['\u2F23'] = '\u5915';
+ t['\u2F24'] = '\u5927';
+ t['\u2F25'] = '\u5973';
+ t['\u2F26'] = '\u5B50';
+ t['\u2F27'] = '\u5B80';
+ t['\u2F28'] = '\u5BF8';
+ t['\u2F29'] = '\u5C0F';
+ t['\u2F2A'] = '\u5C22';
+ t['\u2F2B'] = '\u5C38';
+ t['\u2F2C'] = '\u5C6E';
+ t['\u2F2D'] = '\u5C71';
+ t['\u2F2E'] = '\u5DDB';
+ t['\u2F2F'] = '\u5DE5';
+ t['\u2F30'] = '\u5DF1';
+ t['\u2F31'] = '\u5DFE';
+ t['\u2F32'] = '\u5E72';
+ t['\u2F33'] = '\u5E7A';
+ t['\u2F34'] = '\u5E7F';
+ t['\u2F35'] = '\u5EF4';
+ t['\u2F36'] = '\u5EFE';
+ t['\u2F37'] = '\u5F0B';
+ t['\u2F38'] = '\u5F13';
+ t['\u2F39'] = '\u5F50';
+ t['\u2F3A'] = '\u5F61';
+ t['\u2F3B'] = '\u5F73';
+ t['\u2F3C'] = '\u5FC3';
+ t['\u2F3D'] = '\u6208';
+ t['\u2F3E'] = '\u6236';
+ t['\u2F3F'] = '\u624B';
+ t['\u2F40'] = '\u652F';
+ t['\u2F41'] = '\u6534';
+ t['\u2F42'] = '\u6587';
+ t['\u2F43'] = '\u6597';
+ t['\u2F44'] = '\u65A4';
+ t['\u2F45'] = '\u65B9';
+ t['\u2F46'] = '\u65E0';
+ t['\u2F47'] = '\u65E5';
+ t['\u2F48'] = '\u66F0';
+ t['\u2F49'] = '\u6708';
+ t['\u2F4A'] = '\u6728';
+ t['\u2F4B'] = '\u6B20';
+ t['\u2F4C'] = '\u6B62';
+ t['\u2F4D'] = '\u6B79';
+ t['\u2F4E'] = '\u6BB3';
+ t['\u2F4F'] = '\u6BCB';
+ t['\u2F50'] = '\u6BD4';
+ t['\u2F51'] = '\u6BDB';
+ t['\u2F52'] = '\u6C0F';
+ t['\u2F53'] = '\u6C14';
+ t['\u2F54'] = '\u6C34';
+ t['\u2F55'] = '\u706B';
+ t['\u2F56'] = '\u722A';
+ t['\u2F57'] = '\u7236';
+ t['\u2F58'] = '\u723B';
+ t['\u2F59'] = '\u723F';
+ t['\u2F5A'] = '\u7247';
+ t['\u2F5B'] = '\u7259';
+ t['\u2F5C'] = '\u725B';
+ t['\u2F5D'] = '\u72AC';
+ t['\u2F5E'] = '\u7384';
+ t['\u2F5F'] = '\u7389';
+ t['\u2F60'] = '\u74DC';
+ t['\u2F61'] = '\u74E6';
+ t['\u2F62'] = '\u7518';
+ t['\u2F63'] = '\u751F';
+ t['\u2F64'] = '\u7528';
+ t['\u2F65'] = '\u7530';
+ t['\u2F66'] = '\u758B';
+ t['\u2F67'] = '\u7592';
+ t['\u2F68'] = '\u7676';
+ t['\u2F69'] = '\u767D';
+ t['\u2F6A'] = '\u76AE';
+ t['\u2F6B'] = '\u76BF';
+ t['\u2F6C'] = '\u76EE';
+ t['\u2F6D'] = '\u77DB';
+ t['\u2F6E'] = '\u77E2';
+ t['\u2F6F'] = '\u77F3';
+ t['\u2F70'] = '\u793A';
+ t['\u2F71'] = '\u79B8';
+ t['\u2F72'] = '\u79BE';
+ t['\u2F73'] = '\u7A74';
+ t['\u2F74'] = '\u7ACB';
+ t['\u2F75'] = '\u7AF9';
+ t['\u2F76'] = '\u7C73';
+ t['\u2F77'] = '\u7CF8';
+ t['\u2F78'] = '\u7F36';
+ t['\u2F79'] = '\u7F51';
+ t['\u2F7A'] = '\u7F8A';
+ t['\u2F7B'] = '\u7FBD';
+ t['\u2F7C'] = '\u8001';
+ t['\u2F7D'] = '\u800C';
+ t['\u2F7E'] = '\u8012';
+ t['\u2F7F'] = '\u8033';
+ t['\u2F80'] = '\u807F';
+ t['\u2F81'] = '\u8089';
+ t['\u2F82'] = '\u81E3';
+ t['\u2F83'] = '\u81EA';
+ t['\u2F84'] = '\u81F3';
+ t['\u2F85'] = '\u81FC';
+ t['\u2F86'] = '\u820C';
+ t['\u2F87'] = '\u821B';
+ t['\u2F88'] = '\u821F';
+ t['\u2F89'] = '\u826E';
+ t['\u2F8A'] = '\u8272';
+ t['\u2F8B'] = '\u8278';
+ t['\u2F8C'] = '\u864D';
+ t['\u2F8D'] = '\u866B';
+ t['\u2F8E'] = '\u8840';
+ t['\u2F8F'] = '\u884C';
+ t['\u2F90'] = '\u8863';
+ t['\u2F91'] = '\u897E';
+ t['\u2F92'] = '\u898B';
+ t['\u2F93'] = '\u89D2';
+ t['\u2F94'] = '\u8A00';
+ t['\u2F95'] = '\u8C37';
+ t['\u2F96'] = '\u8C46';
+ t['\u2F97'] = '\u8C55';
+ t['\u2F98'] = '\u8C78';
+ t['\u2F99'] = '\u8C9D';
+ t['\u2F9A'] = '\u8D64';
+ t['\u2F9B'] = '\u8D70';
+ t['\u2F9C'] = '\u8DB3';
+ t['\u2F9D'] = '\u8EAB';
+ t['\u2F9E'] = '\u8ECA';
+ t['\u2F9F'] = '\u8F9B';
+ t['\u2FA0'] = '\u8FB0';
+ t['\u2FA1'] = '\u8FB5';
+ t['\u2FA2'] = '\u9091';
+ t['\u2FA3'] = '\u9149';
+ t['\u2FA4'] = '\u91C6';
+ t['\u2FA5'] = '\u91CC';
+ t['\u2FA6'] = '\u91D1';
+ t['\u2FA7'] = '\u9577';
+ t['\u2FA8'] = '\u9580';
+ t['\u2FA9'] = '\u961C';
+ t['\u2FAA'] = '\u96B6';
+ t['\u2FAB'] = '\u96B9';
+ t['\u2FAC'] = '\u96E8';
+ t['\u2FAD'] = '\u9751';
+ t['\u2FAE'] = '\u975E';
+ t['\u2FAF'] = '\u9762';
+ t['\u2FB0'] = '\u9769';
+ t['\u2FB1'] = '\u97CB';
+ t['\u2FB2'] = '\u97ED';
+ t['\u2FB3'] = '\u97F3';
+ t['\u2FB4'] = '\u9801';
+ t['\u2FB5'] = '\u98A8';
+ t['\u2FB6'] = '\u98DB';
+ t['\u2FB7'] = '\u98DF';
+ t['\u2FB8'] = '\u9996';
+ t['\u2FB9'] = '\u9999';
+ t['\u2FBA'] = '\u99AC';
+ t['\u2FBB'] = '\u9AA8';
+ t['\u2FBC'] = '\u9AD8';
+ t['\u2FBD'] = '\u9ADF';
+ t['\u2FBE'] = '\u9B25';
+ t['\u2FBF'] = '\u9B2F';
+ t['\u2FC0'] = '\u9B32';
+ t['\u2FC1'] = '\u9B3C';
+ t['\u2FC2'] = '\u9B5A';
+ t['\u2FC3'] = '\u9CE5';
+ t['\u2FC4'] = '\u9E75';
+ t['\u2FC5'] = '\u9E7F';
+ t['\u2FC6'] = '\u9EA5';
+ t['\u2FC7'] = '\u9EBB';
+ t['\u2FC8'] = '\u9EC3';
+ t['\u2FC9'] = '\u9ECD';
+ t['\u2FCA'] = '\u9ED1';
+ t['\u2FCB'] = '\u9EF9';
+ t['\u2FCC'] = '\u9EFD';
+ t['\u2FCD'] = '\u9F0E';
+ t['\u2FCE'] = '\u9F13';
+ t['\u2FCF'] = '\u9F20';
+ t['\u2FD0'] = '\u9F3B';
+ t['\u2FD1'] = '\u9F4A';
+ t['\u2FD2'] = '\u9F52';
+ t['\u2FD3'] = '\u9F8D';
+ t['\u2FD4'] = '\u9F9C';
+ t['\u2FD5'] = '\u9FA0';
+ t['\u3036'] = '\u3012';
+ t['\u3038'] = '\u5341';
+ t['\u3039'] = '\u5344';
+ t['\u303A'] = '\u5345';
+ t['\u309B'] = '\u0020\u3099';
+ t['\u309C'] = '\u0020\u309A';
+ t['\u3131'] = '\u1100';
+ t['\u3132'] = '\u1101';
+ t['\u3133'] = '\u11AA';
+ t['\u3134'] = '\u1102';
+ t['\u3135'] = '\u11AC';
+ t['\u3136'] = '\u11AD';
+ t['\u3137'] = '\u1103';
+ t['\u3138'] = '\u1104';
+ t['\u3139'] = '\u1105';
+ t['\u313A'] = '\u11B0';
+ t['\u313B'] = '\u11B1';
+ t['\u313C'] = '\u11B2';
+ t['\u313D'] = '\u11B3';
+ t['\u313E'] = '\u11B4';
+ t['\u313F'] = '\u11B5';
+ t['\u3140'] = '\u111A';
+ t['\u3141'] = '\u1106';
+ t['\u3142'] = '\u1107';
+ t['\u3143'] = '\u1108';
+ t['\u3144'] = '\u1121';
+ t['\u3145'] = '\u1109';
+ t['\u3146'] = '\u110A';
+ t['\u3147'] = '\u110B';
+ t['\u3148'] = '\u110C';
+ t['\u3149'] = '\u110D';
+ t['\u314A'] = '\u110E';
+ t['\u314B'] = '\u110F';
+ t['\u314C'] = '\u1110';
+ t['\u314D'] = '\u1111';
+ t['\u314E'] = '\u1112';
+ t['\u314F'] = '\u1161';
+ t['\u3150'] = '\u1162';
+ t['\u3151'] = '\u1163';
+ t['\u3152'] = '\u1164';
+ t['\u3153'] = '\u1165';
+ t['\u3154'] = '\u1166';
+ t['\u3155'] = '\u1167';
+ t['\u3156'] = '\u1168';
+ t['\u3157'] = '\u1169';
+ t['\u3158'] = '\u116A';
+ t['\u3159'] = '\u116B';
+ t['\u315A'] = '\u116C';
+ t['\u315B'] = '\u116D';
+ t['\u315C'] = '\u116E';
+ t['\u315D'] = '\u116F';
+ t['\u315E'] = '\u1170';
+ t['\u315F'] = '\u1171';
+ t['\u3160'] = '\u1172';
+ t['\u3161'] = '\u1173';
+ t['\u3162'] = '\u1174';
+ t['\u3163'] = '\u1175';
+ t['\u3164'] = '\u1160';
+ t['\u3165'] = '\u1114';
+ t['\u3166'] = '\u1115';
+ t['\u3167'] = '\u11C7';
+ t['\u3168'] = '\u11C8';
+ t['\u3169'] = '\u11CC';
+ t['\u316A'] = '\u11CE';
+ t['\u316B'] = '\u11D3';
+ t['\u316C'] = '\u11D7';
+ t['\u316D'] = '\u11D9';
+ t['\u316E'] = '\u111C';
+ t['\u316F'] = '\u11DD';
+ t['\u3170'] = '\u11DF';
+ t['\u3171'] = '\u111D';
+ t['\u3172'] = '\u111E';
+ t['\u3173'] = '\u1120';
+ t['\u3174'] = '\u1122';
+ t['\u3175'] = '\u1123';
+ t['\u3176'] = '\u1127';
+ t['\u3177'] = '\u1129';
+ t['\u3178'] = '\u112B';
+ t['\u3179'] = '\u112C';
+ t['\u317A'] = '\u112D';
+ t['\u317B'] = '\u112E';
+ t['\u317C'] = '\u112F';
+ t['\u317D'] = '\u1132';
+ t['\u317E'] = '\u1136';
+ t['\u317F'] = '\u1140';
+ t['\u3180'] = '\u1147';
+ t['\u3181'] = '\u114C';
+ t['\u3182'] = '\u11F1';
+ t['\u3183'] = '\u11F2';
+ t['\u3184'] = '\u1157';
+ t['\u3185'] = '\u1158';
+ t['\u3186'] = '\u1159';
+ t['\u3187'] = '\u1184';
+ t['\u3188'] = '\u1185';
+ t['\u3189'] = '\u1188';
+ t['\u318A'] = '\u1191';
+ t['\u318B'] = '\u1192';
+ t['\u318C'] = '\u1194';
+ t['\u318D'] = '\u119E';
+ t['\u318E'] = '\u11A1';
+ t['\u3200'] = '\u0028\u1100\u0029';
+ t['\u3201'] = '\u0028\u1102\u0029';
+ t['\u3202'] = '\u0028\u1103\u0029';
+ t['\u3203'] = '\u0028\u1105\u0029';
+ t['\u3204'] = '\u0028\u1106\u0029';
+ t['\u3205'] = '\u0028\u1107\u0029';
+ t['\u3206'] = '\u0028\u1109\u0029';
+ t['\u3207'] = '\u0028\u110B\u0029';
+ t['\u3208'] = '\u0028\u110C\u0029';
+ t['\u3209'] = '\u0028\u110E\u0029';
+ t['\u320A'] = '\u0028\u110F\u0029';
+ t['\u320B'] = '\u0028\u1110\u0029';
+ t['\u320C'] = '\u0028\u1111\u0029';
+ t['\u320D'] = '\u0028\u1112\u0029';
+ t['\u320E'] = '\u0028\u1100\u1161\u0029';
+ t['\u320F'] = '\u0028\u1102\u1161\u0029';
+ t['\u3210'] = '\u0028\u1103\u1161\u0029';
+ t['\u3211'] = '\u0028\u1105\u1161\u0029';
+ t['\u3212'] = '\u0028\u1106\u1161\u0029';
+ t['\u3213'] = '\u0028\u1107\u1161\u0029';
+ t['\u3214'] = '\u0028\u1109\u1161\u0029';
+ t['\u3215'] = '\u0028\u110B\u1161\u0029';
+ t['\u3216'] = '\u0028\u110C\u1161\u0029';
+ t['\u3217'] = '\u0028\u110E\u1161\u0029';
+ t['\u3218'] = '\u0028\u110F\u1161\u0029';
+ t['\u3219'] = '\u0028\u1110\u1161\u0029';
+ t['\u321A'] = '\u0028\u1111\u1161\u0029';
+ t['\u321B'] = '\u0028\u1112\u1161\u0029';
+ t['\u321C'] = '\u0028\u110C\u116E\u0029';
+ t['\u321D'] = '\u0028\u110B\u1169\u110C\u1165\u11AB\u0029';
+ t['\u321E'] = '\u0028\u110B\u1169\u1112\u116E\u0029';
+ t['\u3220'] = '\u0028\u4E00\u0029';
+ t['\u3221'] = '\u0028\u4E8C\u0029';
+ t['\u3222'] = '\u0028\u4E09\u0029';
+ t['\u3223'] = '\u0028\u56DB\u0029';
+ t['\u3224'] = '\u0028\u4E94\u0029';
+ t['\u3225'] = '\u0028\u516D\u0029';
+ t['\u3226'] = '\u0028\u4E03\u0029';
+ t['\u3227'] = '\u0028\u516B\u0029';
+ t['\u3228'] = '\u0028\u4E5D\u0029';
+ t['\u3229'] = '\u0028\u5341\u0029';
+ t['\u322A'] = '\u0028\u6708\u0029';
+ t['\u322B'] = '\u0028\u706B\u0029';
+ t['\u322C'] = '\u0028\u6C34\u0029';
+ t['\u322D'] = '\u0028\u6728\u0029';
+ t['\u322E'] = '\u0028\u91D1\u0029';
+ t['\u322F'] = '\u0028\u571F\u0029';
+ t['\u3230'] = '\u0028\u65E5\u0029';
+ t['\u3231'] = '\u0028\u682A\u0029';
+ t['\u3232'] = '\u0028\u6709\u0029';
+ t['\u3233'] = '\u0028\u793E\u0029';
+ t['\u3234'] = '\u0028\u540D\u0029';
+ t['\u3235'] = '\u0028\u7279\u0029';
+ t['\u3236'] = '\u0028\u8CA1\u0029';
+ t['\u3237'] = '\u0028\u795D\u0029';
+ t['\u3238'] = '\u0028\u52B4\u0029';
+ t['\u3239'] = '\u0028\u4EE3\u0029';
+ t['\u323A'] = '\u0028\u547C\u0029';
+ t['\u323B'] = '\u0028\u5B66\u0029';
+ t['\u323C'] = '\u0028\u76E3\u0029';
+ t['\u323D'] = '\u0028\u4F01\u0029';
+ t['\u323E'] = '\u0028\u8CC7\u0029';
+ t['\u323F'] = '\u0028\u5354\u0029';
+ t['\u3240'] = '\u0028\u796D\u0029';
+ t['\u3241'] = '\u0028\u4F11\u0029';
+ t['\u3242'] = '\u0028\u81EA\u0029';
+ t['\u3243'] = '\u0028\u81F3\u0029';
+ t['\u32C0'] = '\u0031\u6708';
+ t['\u32C1'] = '\u0032\u6708';
+ t['\u32C2'] = '\u0033\u6708';
+ t['\u32C3'] = '\u0034\u6708';
+ t['\u32C4'] = '\u0035\u6708';
+ t['\u32C5'] = '\u0036\u6708';
+ t['\u32C6'] = '\u0037\u6708';
+ t['\u32C7'] = '\u0038\u6708';
+ t['\u32C8'] = '\u0039\u6708';
+ t['\u32C9'] = '\u0031\u0030\u6708';
+ t['\u32CA'] = '\u0031\u0031\u6708';
+ t['\u32CB'] = '\u0031\u0032\u6708';
+ t['\u3358'] = '\u0030\u70B9';
+ t['\u3359'] = '\u0031\u70B9';
+ t['\u335A'] = '\u0032\u70B9';
+ t['\u335B'] = '\u0033\u70B9';
+ t['\u335C'] = '\u0034\u70B9';
+ t['\u335D'] = '\u0035\u70B9';
+ t['\u335E'] = '\u0036\u70B9';
+ t['\u335F'] = '\u0037\u70B9';
+ t['\u3360'] = '\u0038\u70B9';
+ t['\u3361'] = '\u0039\u70B9';
+ t['\u3362'] = '\u0031\u0030\u70B9';
+ t['\u3363'] = '\u0031\u0031\u70B9';
+ t['\u3364'] = '\u0031\u0032\u70B9';
+ t['\u3365'] = '\u0031\u0033\u70B9';
+ t['\u3366'] = '\u0031\u0034\u70B9';
+ t['\u3367'] = '\u0031\u0035\u70B9';
+ t['\u3368'] = '\u0031\u0036\u70B9';
+ t['\u3369'] = '\u0031\u0037\u70B9';
+ t['\u336A'] = '\u0031\u0038\u70B9';
+ t['\u336B'] = '\u0031\u0039\u70B9';
+ t['\u336C'] = '\u0032\u0030\u70B9';
+ t['\u336D'] = '\u0032\u0031\u70B9';
+ t['\u336E'] = '\u0032\u0032\u70B9';
+ t['\u336F'] = '\u0032\u0033\u70B9';
+ t['\u3370'] = '\u0032\u0034\u70B9';
+ t['\u33E0'] = '\u0031\u65E5';
+ t['\u33E1'] = '\u0032\u65E5';
+ t['\u33E2'] = '\u0033\u65E5';
+ t['\u33E3'] = '\u0034\u65E5';
+ t['\u33E4'] = '\u0035\u65E5';
+ t['\u33E5'] = '\u0036\u65E5';
+ t['\u33E6'] = '\u0037\u65E5';
+ t['\u33E7'] = '\u0038\u65E5';
+ t['\u33E8'] = '\u0039\u65E5';
+ t['\u33E9'] = '\u0031\u0030\u65E5';
+ t['\u33EA'] = '\u0031\u0031\u65E5';
+ t['\u33EB'] = '\u0031\u0032\u65E5';
+ t['\u33EC'] = '\u0031\u0033\u65E5';
+ t['\u33ED'] = '\u0031\u0034\u65E5';
+ t['\u33EE'] = '\u0031\u0035\u65E5';
+ t['\u33EF'] = '\u0031\u0036\u65E5';
+ t['\u33F0'] = '\u0031\u0037\u65E5';
+ t['\u33F1'] = '\u0031\u0038\u65E5';
+ t['\u33F2'] = '\u0031\u0039\u65E5';
+ t['\u33F3'] = '\u0032\u0030\u65E5';
+ t['\u33F4'] = '\u0032\u0031\u65E5';
+ t['\u33F5'] = '\u0032\u0032\u65E5';
+ t['\u33F6'] = '\u0032\u0033\u65E5';
+ t['\u33F7'] = '\u0032\u0034\u65E5';
+ t['\u33F8'] = '\u0032\u0035\u65E5';
+ t['\u33F9'] = '\u0032\u0036\u65E5';
+ t['\u33FA'] = '\u0032\u0037\u65E5';
+ t['\u33FB'] = '\u0032\u0038\u65E5';
+ t['\u33FC'] = '\u0032\u0039\u65E5';
+ t['\u33FD'] = '\u0033\u0030\u65E5';
+ t['\u33FE'] = '\u0033\u0031\u65E5';
+ t['\uFB00'] = '\u0066\u0066';
+ t['\uFB01'] = '\u0066\u0069';
+ t['\uFB02'] = '\u0066\u006C';
+ t['\uFB03'] = '\u0066\u0066\u0069';
+ t['\uFB04'] = '\u0066\u0066\u006C';
+ t['\uFB05'] = '\u017F\u0074';
+ t['\uFB06'] = '\u0073\u0074';
+ t['\uFB13'] = '\u0574\u0576';
+ t['\uFB14'] = '\u0574\u0565';
+ t['\uFB15'] = '\u0574\u056B';
+ t['\uFB16'] = '\u057E\u0576';
+ t['\uFB17'] = '\u0574\u056D';
+ t['\uFB4F'] = '\u05D0\u05DC';
+ t['\uFB50'] = '\u0671';
+ t['\uFB51'] = '\u0671';
+ t['\uFB52'] = '\u067B';
+ t['\uFB53'] = '\u067B';
+ t['\uFB54'] = '\u067B';
+ t['\uFB55'] = '\u067B';
+ t['\uFB56'] = '\u067E';
+ t['\uFB57'] = '\u067E';
+ t['\uFB58'] = '\u067E';
+ t['\uFB59'] = '\u067E';
+ t['\uFB5A'] = '\u0680';
+ t['\uFB5B'] = '\u0680';
+ t['\uFB5C'] = '\u0680';
+ t['\uFB5D'] = '\u0680';
+ t['\uFB5E'] = '\u067A';
+ t['\uFB5F'] = '\u067A';
+ t['\uFB60'] = '\u067A';
+ t['\uFB61'] = '\u067A';
+ t['\uFB62'] = '\u067F';
+ t['\uFB63'] = '\u067F';
+ t['\uFB64'] = '\u067F';
+ t['\uFB65'] = '\u067F';
+ t['\uFB66'] = '\u0679';
+ t['\uFB67'] = '\u0679';
+ t['\uFB68'] = '\u0679';
+ t['\uFB69'] = '\u0679';
+ t['\uFB6A'] = '\u06A4';
+ t['\uFB6B'] = '\u06A4';
+ t['\uFB6C'] = '\u06A4';
+ t['\uFB6D'] = '\u06A4';
+ t['\uFB6E'] = '\u06A6';
+ t['\uFB6F'] = '\u06A6';
+ t['\uFB70'] = '\u06A6';
+ t['\uFB71'] = '\u06A6';
+ t['\uFB72'] = '\u0684';
+ t['\uFB73'] = '\u0684';
+ t['\uFB74'] = '\u0684';
+ t['\uFB75'] = '\u0684';
+ t['\uFB76'] = '\u0683';
+ t['\uFB77'] = '\u0683';
+ t['\uFB78'] = '\u0683';
+ t['\uFB79'] = '\u0683';
+ t['\uFB7A'] = '\u0686';
+ t['\uFB7B'] = '\u0686';
+ t['\uFB7C'] = '\u0686';
+ t['\uFB7D'] = '\u0686';
+ t['\uFB7E'] = '\u0687';
+ t['\uFB7F'] = '\u0687';
+ t['\uFB80'] = '\u0687';
+ t['\uFB81'] = '\u0687';
+ t['\uFB82'] = '\u068D';
+ t['\uFB83'] = '\u068D';
+ t['\uFB84'] = '\u068C';
+ t['\uFB85'] = '\u068C';
+ t['\uFB86'] = '\u068E';
+ t['\uFB87'] = '\u068E';
+ t['\uFB88'] = '\u0688';
+ t['\uFB89'] = '\u0688';
+ t['\uFB8A'] = '\u0698';
+ t['\uFB8B'] = '\u0698';
+ t['\uFB8C'] = '\u0691';
+ t['\uFB8D'] = '\u0691';
+ t['\uFB8E'] = '\u06A9';
+ t['\uFB8F'] = '\u06A9';
+ t['\uFB90'] = '\u06A9';
+ t['\uFB91'] = '\u06A9';
+ t['\uFB92'] = '\u06AF';
+ t['\uFB93'] = '\u06AF';
+ t['\uFB94'] = '\u06AF';
+ t['\uFB95'] = '\u06AF';
+ t['\uFB96'] = '\u06B3';
+ t['\uFB97'] = '\u06B3';
+ t['\uFB98'] = '\u06B3';
+ t['\uFB99'] = '\u06B3';
+ t['\uFB9A'] = '\u06B1';
+ t['\uFB9B'] = '\u06B1';
+ t['\uFB9C'] = '\u06B1';
+ t['\uFB9D'] = '\u06B1';
+ t['\uFB9E'] = '\u06BA';
+ t['\uFB9F'] = '\u06BA';
+ t['\uFBA0'] = '\u06BB';
+ t['\uFBA1'] = '\u06BB';
+ t['\uFBA2'] = '\u06BB';
+ t['\uFBA3'] = '\u06BB';
+ t['\uFBA4'] = '\u06C0';
+ t['\uFBA5'] = '\u06C0';
+ t['\uFBA6'] = '\u06C1';
+ t['\uFBA7'] = '\u06C1';
+ t['\uFBA8'] = '\u06C1';
+ t['\uFBA9'] = '\u06C1';
+ t['\uFBAA'] = '\u06BE';
+ t['\uFBAB'] = '\u06BE';
+ t['\uFBAC'] = '\u06BE';
+ t['\uFBAD'] = '\u06BE';
+ t['\uFBAE'] = '\u06D2';
+ t['\uFBAF'] = '\u06D2';
+ t['\uFBB0'] = '\u06D3';
+ t['\uFBB1'] = '\u06D3';
+ t['\uFBD3'] = '\u06AD';
+ t['\uFBD4'] = '\u06AD';
+ t['\uFBD5'] = '\u06AD';
+ t['\uFBD6'] = '\u06AD';
+ t['\uFBD7'] = '\u06C7';
+ t['\uFBD8'] = '\u06C7';
+ t['\uFBD9'] = '\u06C6';
+ t['\uFBDA'] = '\u06C6';
+ t['\uFBDB'] = '\u06C8';
+ t['\uFBDC'] = '\u06C8';
+ t['\uFBDD'] = '\u0677';
+ t['\uFBDE'] = '\u06CB';
+ t['\uFBDF'] = '\u06CB';
+ t['\uFBE0'] = '\u06C5';
+ t['\uFBE1'] = '\u06C5';
+ t['\uFBE2'] = '\u06C9';
+ t['\uFBE3'] = '\u06C9';
+ t['\uFBE4'] = '\u06D0';
+ t['\uFBE5'] = '\u06D0';
+ t['\uFBE6'] = '\u06D0';
+ t['\uFBE7'] = '\u06D0';
+ t['\uFBE8'] = '\u0649';
+ t['\uFBE9'] = '\u0649';
+ t['\uFBEA'] = '\u0626\u0627';
+ t['\uFBEB'] = '\u0626\u0627';
+ t['\uFBEC'] = '\u0626\u06D5';
+ t['\uFBED'] = '\u0626\u06D5';
+ t['\uFBEE'] = '\u0626\u0648';
+ t['\uFBEF'] = '\u0626\u0648';
+ t['\uFBF0'] = '\u0626\u06C7';
+ t['\uFBF1'] = '\u0626\u06C7';
+ t['\uFBF2'] = '\u0626\u06C6';
+ t['\uFBF3'] = '\u0626\u06C6';
+ t['\uFBF4'] = '\u0626\u06C8';
+ t['\uFBF5'] = '\u0626\u06C8';
+ t['\uFBF6'] = '\u0626\u06D0';
+ t['\uFBF7'] = '\u0626\u06D0';
+ t['\uFBF8'] = '\u0626\u06D0';
+ t['\uFBF9'] = '\u0626\u0649';
+ t['\uFBFA'] = '\u0626\u0649';
+ t['\uFBFB'] = '\u0626\u0649';
+ t['\uFBFC'] = '\u06CC';
+ t['\uFBFD'] = '\u06CC';
+ t['\uFBFE'] = '\u06CC';
+ t['\uFBFF'] = '\u06CC';
+ t['\uFC00'] = '\u0626\u062C';
+ t['\uFC01'] = '\u0626\u062D';
+ t['\uFC02'] = '\u0626\u0645';
+ t['\uFC03'] = '\u0626\u0649';
+ t['\uFC04'] = '\u0626\u064A';
+ t['\uFC05'] = '\u0628\u062C';
+ t['\uFC06'] = '\u0628\u062D';
+ t['\uFC07'] = '\u0628\u062E';
+ t['\uFC08'] = '\u0628\u0645';
+ t['\uFC09'] = '\u0628\u0649';
+ t['\uFC0A'] = '\u0628\u064A';
+ t['\uFC0B'] = '\u062A\u062C';
+ t['\uFC0C'] = '\u062A\u062D';
+ t['\uFC0D'] = '\u062A\u062E';
+ t['\uFC0E'] = '\u062A\u0645';
+ t['\uFC0F'] = '\u062A\u0649';
+ t['\uFC10'] = '\u062A\u064A';
+ t['\uFC11'] = '\u062B\u062C';
+ t['\uFC12'] = '\u062B\u0645';
+ t['\uFC13'] = '\u062B\u0649';
+ t['\uFC14'] = '\u062B\u064A';
+ t['\uFC15'] = '\u062C\u062D';
+ t['\uFC16'] = '\u062C\u0645';
+ t['\uFC17'] = '\u062D\u062C';
+ t['\uFC18'] = '\u062D\u0645';
+ t['\uFC19'] = '\u062E\u062C';
+ t['\uFC1A'] = '\u062E\u062D';
+ t['\uFC1B'] = '\u062E\u0645';
+ t['\uFC1C'] = '\u0633\u062C';
+ t['\uFC1D'] = '\u0633\u062D';
+ t['\uFC1E'] = '\u0633\u062E';
+ t['\uFC1F'] = '\u0633\u0645';
+ t['\uFC20'] = '\u0635\u062D';
+ t['\uFC21'] = '\u0635\u0645';
+ t['\uFC22'] = '\u0636\u062C';
+ t['\uFC23'] = '\u0636\u062D';
+ t['\uFC24'] = '\u0636\u062E';
+ t['\uFC25'] = '\u0636\u0645';
+ t['\uFC26'] = '\u0637\u062D';
+ t['\uFC27'] = '\u0637\u0645';
+ t['\uFC28'] = '\u0638\u0645';
+ t['\uFC29'] = '\u0639\u062C';
+ t['\uFC2A'] = '\u0639\u0645';
+ t['\uFC2B'] = '\u063A\u062C';
+ t['\uFC2C'] = '\u063A\u0645';
+ t['\uFC2D'] = '\u0641\u062C';
+ t['\uFC2E'] = '\u0641\u062D';
+ t['\uFC2F'] = '\u0641\u062E';
+ t['\uFC30'] = '\u0641\u0645';
+ t['\uFC31'] = '\u0641\u0649';
+ t['\uFC32'] = '\u0641\u064A';
+ t['\uFC33'] = '\u0642\u062D';
+ t['\uFC34'] = '\u0642\u0645';
+ t['\uFC35'] = '\u0642\u0649';
+ t['\uFC36'] = '\u0642\u064A';
+ t['\uFC37'] = '\u0643\u0627';
+ t['\uFC38'] = '\u0643\u062C';
+ t['\uFC39'] = '\u0643\u062D';
+ t['\uFC3A'] = '\u0643\u062E';
+ t['\uFC3B'] = '\u0643\u0644';
+ t['\uFC3C'] = '\u0643\u0645';
+ t['\uFC3D'] = '\u0643\u0649';
+ t['\uFC3E'] = '\u0643\u064A';
+ t['\uFC3F'] = '\u0644\u062C';
+ t['\uFC40'] = '\u0644\u062D';
+ t['\uFC41'] = '\u0644\u062E';
+ t['\uFC42'] = '\u0644\u0645';
+ t['\uFC43'] = '\u0644\u0649';
+ t['\uFC44'] = '\u0644\u064A';
+ t['\uFC45'] = '\u0645\u062C';
+ t['\uFC46'] = '\u0645\u062D';
+ t['\uFC47'] = '\u0645\u062E';
+ t['\uFC48'] = '\u0645\u0645';
+ t['\uFC49'] = '\u0645\u0649';
+ t['\uFC4A'] = '\u0645\u064A';
+ t['\uFC4B'] = '\u0646\u062C';
+ t['\uFC4C'] = '\u0646\u062D';
+ t['\uFC4D'] = '\u0646\u062E';
+ t['\uFC4E'] = '\u0646\u0645';
+ t['\uFC4F'] = '\u0646\u0649';
+ t['\uFC50'] = '\u0646\u064A';
+ t['\uFC51'] = '\u0647\u062C';
+ t['\uFC52'] = '\u0647\u0645';
+ t['\uFC53'] = '\u0647\u0649';
+ t['\uFC54'] = '\u0647\u064A';
+ t['\uFC55'] = '\u064A\u062C';
+ t['\uFC56'] = '\u064A\u062D';
+ t['\uFC57'] = '\u064A\u062E';
+ t['\uFC58'] = '\u064A\u0645';
+ t['\uFC59'] = '\u064A\u0649';
+ t['\uFC5A'] = '\u064A\u064A';
+ t['\uFC5B'] = '\u0630\u0670';
+ t['\uFC5C'] = '\u0631\u0670';
+ t['\uFC5D'] = '\u0649\u0670';
+ t['\uFC5E'] = '\u0020\u064C\u0651';
+ t['\uFC5F'] = '\u0020\u064D\u0651';
+ t['\uFC60'] = '\u0020\u064E\u0651';
+ t['\uFC61'] = '\u0020\u064F\u0651';
+ t['\uFC62'] = '\u0020\u0650\u0651';
+ t['\uFC63'] = '\u0020\u0651\u0670';
+ t['\uFC64'] = '\u0626\u0631';
+ t['\uFC65'] = '\u0626\u0632';
+ t['\uFC66'] = '\u0626\u0645';
+ t['\uFC67'] = '\u0626\u0646';
+ t['\uFC68'] = '\u0626\u0649';
+ t['\uFC69'] = '\u0626\u064A';
+ t['\uFC6A'] = '\u0628\u0631';
+ t['\uFC6B'] = '\u0628\u0632';
+ t['\uFC6C'] = '\u0628\u0645';
+ t['\uFC6D'] = '\u0628\u0646';
+ t['\uFC6E'] = '\u0628\u0649';
+ t['\uFC6F'] = '\u0628\u064A';
+ t['\uFC70'] = '\u062A\u0631';
+ t['\uFC71'] = '\u062A\u0632';
+ t['\uFC72'] = '\u062A\u0645';
+ t['\uFC73'] = '\u062A\u0646';
+ t['\uFC74'] = '\u062A\u0649';
+ t['\uFC75'] = '\u062A\u064A';
+ t['\uFC76'] = '\u062B\u0631';
+ t['\uFC77'] = '\u062B\u0632';
+ t['\uFC78'] = '\u062B\u0645';
+ t['\uFC79'] = '\u062B\u0646';
+ t['\uFC7A'] = '\u062B\u0649';
+ t['\uFC7B'] = '\u062B\u064A';
+ t['\uFC7C'] = '\u0641\u0649';
+ t['\uFC7D'] = '\u0641\u064A';
+ t['\uFC7E'] = '\u0642\u0649';
+ t['\uFC7F'] = '\u0642\u064A';
+ t['\uFC80'] = '\u0643\u0627';
+ t['\uFC81'] = '\u0643\u0644';
+ t['\uFC82'] = '\u0643\u0645';
+ t['\uFC83'] = '\u0643\u0649';
+ t['\uFC84'] = '\u0643\u064A';
+ t['\uFC85'] = '\u0644\u0645';
+ t['\uFC86'] = '\u0644\u0649';
+ t['\uFC87'] = '\u0644\u064A';
+ t['\uFC88'] = '\u0645\u0627';
+ t['\uFC89'] = '\u0645\u0645';
+ t['\uFC8A'] = '\u0646\u0631';
+ t['\uFC8B'] = '\u0646\u0632';
+ t['\uFC8C'] = '\u0646\u0645';
+ t['\uFC8D'] = '\u0646\u0646';
+ t['\uFC8E'] = '\u0646\u0649';
+ t['\uFC8F'] = '\u0646\u064A';
+ t['\uFC90'] = '\u0649\u0670';
+ t['\uFC91'] = '\u064A\u0631';
+ t['\uFC92'] = '\u064A\u0632';
+ t['\uFC93'] = '\u064A\u0645';
+ t['\uFC94'] = '\u064A\u0646';
+ t['\uFC95'] = '\u064A\u0649';
+ t['\uFC96'] = '\u064A\u064A';
+ t['\uFC97'] = '\u0626\u062C';
+ t['\uFC98'] = '\u0626\u062D';
+ t['\uFC99'] = '\u0626\u062E';
+ t['\uFC9A'] = '\u0626\u0645';
+ t['\uFC9B'] = '\u0626\u0647';
+ t['\uFC9C'] = '\u0628\u062C';
+ t['\uFC9D'] = '\u0628\u062D';
+ t['\uFC9E'] = '\u0628\u062E';
+ t['\uFC9F'] = '\u0628\u0645';
+ t['\uFCA0'] = '\u0628\u0647';
+ t['\uFCA1'] = '\u062A\u062C';
+ t['\uFCA2'] = '\u062A\u062D';
+ t['\uFCA3'] = '\u062A\u062E';
+ t['\uFCA4'] = '\u062A\u0645';
+ t['\uFCA5'] = '\u062A\u0647';
+ t['\uFCA6'] = '\u062B\u0645';
+ t['\uFCA7'] = '\u062C\u062D';
+ t['\uFCA8'] = '\u062C\u0645';
+ t['\uFCA9'] = '\u062D\u062C';
+ t['\uFCAA'] = '\u062D\u0645';
+ t['\uFCAB'] = '\u062E\u062C';
+ t['\uFCAC'] = '\u062E\u0645';
+ t['\uFCAD'] = '\u0633\u062C';
+ t['\uFCAE'] = '\u0633\u062D';
+ t['\uFCAF'] = '\u0633\u062E';
+ t['\uFCB0'] = '\u0633\u0645';
+ t['\uFCB1'] = '\u0635\u062D';
+ t['\uFCB2'] = '\u0635\u062E';
+ t['\uFCB3'] = '\u0635\u0645';
+ t['\uFCB4'] = '\u0636\u062C';
+ t['\uFCB5'] = '\u0636\u062D';
+ t['\uFCB6'] = '\u0636\u062E';
+ t['\uFCB7'] = '\u0636\u0645';
+ t['\uFCB8'] = '\u0637\u062D';
+ t['\uFCB9'] = '\u0638\u0645';
+ t['\uFCBA'] = '\u0639\u062C';
+ t['\uFCBB'] = '\u0639\u0645';
+ t['\uFCBC'] = '\u063A\u062C';
+ t['\uFCBD'] = '\u063A\u0645';
+ t['\uFCBE'] = '\u0641\u062C';
+ t['\uFCBF'] = '\u0641\u062D';
+ t['\uFCC0'] = '\u0641\u062E';
+ t['\uFCC1'] = '\u0641\u0645';
+ t['\uFCC2'] = '\u0642\u062D';
+ t['\uFCC3'] = '\u0642\u0645';
+ t['\uFCC4'] = '\u0643\u062C';
+ t['\uFCC5'] = '\u0643\u062D';
+ t['\uFCC6'] = '\u0643\u062E';
+ t['\uFCC7'] = '\u0643\u0644';
+ t['\uFCC8'] = '\u0643\u0645';
+ t['\uFCC9'] = '\u0644\u062C';
+ t['\uFCCA'] = '\u0644\u062D';
+ t['\uFCCB'] = '\u0644\u062E';
+ t['\uFCCC'] = '\u0644\u0645';
+ t['\uFCCD'] = '\u0644\u0647';
+ t['\uFCCE'] = '\u0645\u062C';
+ t['\uFCCF'] = '\u0645\u062D';
+ t['\uFCD0'] = '\u0645\u062E';
+ t['\uFCD1'] = '\u0645\u0645';
+ t['\uFCD2'] = '\u0646\u062C';
+ t['\uFCD3'] = '\u0646\u062D';
+ t['\uFCD4'] = '\u0646\u062E';
+ t['\uFCD5'] = '\u0646\u0645';
+ t['\uFCD6'] = '\u0646\u0647';
+ t['\uFCD7'] = '\u0647\u062C';
+ t['\uFCD8'] = '\u0647\u0645';
+ t['\uFCD9'] = '\u0647\u0670';
+ t['\uFCDA'] = '\u064A\u062C';
+ t['\uFCDB'] = '\u064A\u062D';
+ t['\uFCDC'] = '\u064A\u062E';
+ t['\uFCDD'] = '\u064A\u0645';
+ t['\uFCDE'] = '\u064A\u0647';
+ t['\uFCDF'] = '\u0626\u0645';
+ t['\uFCE0'] = '\u0626\u0647';
+ t['\uFCE1'] = '\u0628\u0645';
+ t['\uFCE2'] = '\u0628\u0647';
+ t['\uFCE3'] = '\u062A\u0645';
+ t['\uFCE4'] = '\u062A\u0647';
+ t['\uFCE5'] = '\u062B\u0645';
+ t['\uFCE6'] = '\u062B\u0647';
+ t['\uFCE7'] = '\u0633\u0645';
+ t['\uFCE8'] = '\u0633\u0647';
+ t['\uFCE9'] = '\u0634\u0645';
+ t['\uFCEA'] = '\u0634\u0647';
+ t['\uFCEB'] = '\u0643\u0644';
+ t['\uFCEC'] = '\u0643\u0645';
+ t['\uFCED'] = '\u0644\u0645';
+ t['\uFCEE'] = '\u0646\u0645';
+ t['\uFCEF'] = '\u0646\u0647';
+ t['\uFCF0'] = '\u064A\u0645';
+ t['\uFCF1'] = '\u064A\u0647';
+ t['\uFCF2'] = '\u0640\u064E\u0651';
+ t['\uFCF3'] = '\u0640\u064F\u0651';
+ t['\uFCF4'] = '\u0640\u0650\u0651';
+ t['\uFCF5'] = '\u0637\u0649';
+ t['\uFCF6'] = '\u0637\u064A';
+ t['\uFCF7'] = '\u0639\u0649';
+ t['\uFCF8'] = '\u0639\u064A';
+ t['\uFCF9'] = '\u063A\u0649';
+ t['\uFCFA'] = '\u063A\u064A';
+ t['\uFCFB'] = '\u0633\u0649';
+ t['\uFCFC'] = '\u0633\u064A';
+ t['\uFCFD'] = '\u0634\u0649';
+ t['\uFCFE'] = '\u0634\u064A';
+ t['\uFCFF'] = '\u062D\u0649';
+ t['\uFD00'] = '\u062D\u064A';
+ t['\uFD01'] = '\u062C\u0649';
+ t['\uFD02'] = '\u062C\u064A';
+ t['\uFD03'] = '\u062E\u0649';
+ t['\uFD04'] = '\u062E\u064A';
+ t['\uFD05'] = '\u0635\u0649';
+ t['\uFD06'] = '\u0635\u064A';
+ t['\uFD07'] = '\u0636\u0649';
+ t['\uFD08'] = '\u0636\u064A';
+ t['\uFD09'] = '\u0634\u062C';
+ t['\uFD0A'] = '\u0634\u062D';
+ t['\uFD0B'] = '\u0634\u062E';
+ t['\uFD0C'] = '\u0634\u0645';
+ t['\uFD0D'] = '\u0634\u0631';
+ t['\uFD0E'] = '\u0633\u0631';
+ t['\uFD0F'] = '\u0635\u0631';
+ t['\uFD10'] = '\u0636\u0631';
+ t['\uFD11'] = '\u0637\u0649';
+ t['\uFD12'] = '\u0637\u064A';
+ t['\uFD13'] = '\u0639\u0649';
+ t['\uFD14'] = '\u0639\u064A';
+ t['\uFD15'] = '\u063A\u0649';
+ t['\uFD16'] = '\u063A\u064A';
+ t['\uFD17'] = '\u0633\u0649';
+ t['\uFD18'] = '\u0633\u064A';
+ t['\uFD19'] = '\u0634\u0649';
+ t['\uFD1A'] = '\u0634\u064A';
+ t['\uFD1B'] = '\u062D\u0649';
+ t['\uFD1C'] = '\u062D\u064A';
+ t['\uFD1D'] = '\u062C\u0649';
+ t['\uFD1E'] = '\u062C\u064A';
+ t['\uFD1F'] = '\u062E\u0649';
+ t['\uFD20'] = '\u062E\u064A';
+ t['\uFD21'] = '\u0635\u0649';
+ t['\uFD22'] = '\u0635\u064A';
+ t['\uFD23'] = '\u0636\u0649';
+ t['\uFD24'] = '\u0636\u064A';
+ t['\uFD25'] = '\u0634\u062C';
+ t['\uFD26'] = '\u0634\u062D';
+ t['\uFD27'] = '\u0634\u062E';
+ t['\uFD28'] = '\u0634\u0645';
+ t['\uFD29'] = '\u0634\u0631';
+ t['\uFD2A'] = '\u0633\u0631';
+ t['\uFD2B'] = '\u0635\u0631';
+ t['\uFD2C'] = '\u0636\u0631';
+ t['\uFD2D'] = '\u0634\u062C';
+ t['\uFD2E'] = '\u0634\u062D';
+ t['\uFD2F'] = '\u0634\u062E';
+ t['\uFD30'] = '\u0634\u0645';
+ t['\uFD31'] = '\u0633\u0647';
+ t['\uFD32'] = '\u0634\u0647';
+ t['\uFD33'] = '\u0637\u0645';
+ t['\uFD34'] = '\u0633\u062C';
+ t['\uFD35'] = '\u0633\u062D';
+ t['\uFD36'] = '\u0633\u062E';
+ t['\uFD37'] = '\u0634\u062C';
+ t['\uFD38'] = '\u0634\u062D';
+ t['\uFD39'] = '\u0634\u062E';
+ t['\uFD3A'] = '\u0637\u0645';
+ t['\uFD3B'] = '\u0638\u0645';
+ t['\uFD3C'] = '\u0627\u064B';
+ t['\uFD3D'] = '\u0627\u064B';
+ t['\uFD50'] = '\u062A\u062C\u0645';
+ t['\uFD51'] = '\u062A\u062D\u062C';
+ t['\uFD52'] = '\u062A\u062D\u062C';
+ t['\uFD53'] = '\u062A\u062D\u0645';
+ t['\uFD54'] = '\u062A\u062E\u0645';
+ t['\uFD55'] = '\u062A\u0645\u062C';
+ t['\uFD56'] = '\u062A\u0645\u062D';
+ t['\uFD57'] = '\u062A\u0645\u062E';
+ t['\uFD58'] = '\u062C\u0645\u062D';
+ t['\uFD59'] = '\u062C\u0645\u062D';
+ t['\uFD5A'] = '\u062D\u0645\u064A';
+ t['\uFD5B'] = '\u062D\u0645\u0649';
+ t['\uFD5C'] = '\u0633\u062D\u062C';
+ t['\uFD5D'] = '\u0633\u062C\u062D';
+ t['\uFD5E'] = '\u0633\u062C\u0649';
+ t['\uFD5F'] = '\u0633\u0645\u062D';
+ t['\uFD60'] = '\u0633\u0645\u062D';
+ t['\uFD61'] = '\u0633\u0645\u062C';
+ t['\uFD62'] = '\u0633\u0645\u0645';
+ t['\uFD63'] = '\u0633\u0645\u0645';
+ t['\uFD64'] = '\u0635\u062D\u062D';
+ t['\uFD65'] = '\u0635\u062D\u062D';
+ t['\uFD66'] = '\u0635\u0645\u0645';
+ t['\uFD67'] = '\u0634\u062D\u0645';
+ t['\uFD68'] = '\u0634\u062D\u0645';
+ t['\uFD69'] = '\u0634\u062C\u064A';
+ t['\uFD6A'] = '\u0634\u0645\u062E';
+ t['\uFD6B'] = '\u0634\u0645\u062E';
+ t['\uFD6C'] = '\u0634\u0645\u0645';
+ t['\uFD6D'] = '\u0634\u0645\u0645';
+ t['\uFD6E'] = '\u0636\u062D\u0649';
+ t['\uFD6F'] = '\u0636\u062E\u0645';
+ t['\uFD70'] = '\u0636\u062E\u0645';
+ t['\uFD71'] = '\u0637\u0645\u062D';
+ t['\uFD72'] = '\u0637\u0645\u062D';
+ t['\uFD73'] = '\u0637\u0645\u0645';
+ t['\uFD74'] = '\u0637\u0645\u064A';
+ t['\uFD75'] = '\u0639\u062C\u0645';
+ t['\uFD76'] = '\u0639\u0645\u0645';
+ t['\uFD77'] = '\u0639\u0645\u0645';
+ t['\uFD78'] = '\u0639\u0645\u0649';
+ t['\uFD79'] = '\u063A\u0645\u0645';
+ t['\uFD7A'] = '\u063A\u0645\u064A';
+ t['\uFD7B'] = '\u063A\u0645\u0649';
+ t['\uFD7C'] = '\u0641\u062E\u0645';
+ t['\uFD7D'] = '\u0641\u062E\u0645';
+ t['\uFD7E'] = '\u0642\u0645\u062D';
+ t['\uFD7F'] = '\u0642\u0645\u0645';
+ t['\uFD80'] = '\u0644\u062D\u0645';
+ t['\uFD81'] = '\u0644\u062D\u064A';
+ t['\uFD82'] = '\u0644\u062D\u0649';
+ t['\uFD83'] = '\u0644\u062C\u062C';
+ t['\uFD84'] = '\u0644\u062C\u062C';
+ t['\uFD85'] = '\u0644\u062E\u0645';
+ t['\uFD86'] = '\u0644\u062E\u0645';
+ t['\uFD87'] = '\u0644\u0645\u062D';
+ t['\uFD88'] = '\u0644\u0645\u062D';
+ t['\uFD89'] = '\u0645\u062D\u062C';
+ t['\uFD8A'] = '\u0645\u062D\u0645';
+ t['\uFD8B'] = '\u0645\u062D\u064A';
+ t['\uFD8C'] = '\u0645\u062C\u062D';
+ t['\uFD8D'] = '\u0645\u062C\u0645';
+ t['\uFD8E'] = '\u0645\u062E\u062C';
+ t['\uFD8F'] = '\u0645\u062E\u0645';
+ t['\uFD92'] = '\u0645\u062C\u062E';
+ t['\uFD93'] = '\u0647\u0645\u062C';
+ t['\uFD94'] = '\u0647\u0645\u0645';
+ t['\uFD95'] = '\u0646\u062D\u0645';
+ t['\uFD96'] = '\u0646\u062D\u0649';
+ t['\uFD97'] = '\u0646\u062C\u0645';
+ t['\uFD98'] = '\u0646\u062C\u0645';
+ t['\uFD99'] = '\u0646\u062C\u0649';
+ t['\uFD9A'] = '\u0646\u0645\u064A';
+ t['\uFD9B'] = '\u0646\u0645\u0649';
+ t['\uFD9C'] = '\u064A\u0645\u0645';
+ t['\uFD9D'] = '\u064A\u0645\u0645';
+ t['\uFD9E'] = '\u0628\u062E\u064A';
+ t['\uFD9F'] = '\u062A\u062C\u064A';
+ t['\uFDA0'] = '\u062A\u062C\u0649';
+ t['\uFDA1'] = '\u062A\u062E\u064A';
+ t['\uFDA2'] = '\u062A\u062E\u0649';
+ t['\uFDA3'] = '\u062A\u0645\u064A';
+ t['\uFDA4'] = '\u062A\u0645\u0649';
+ t['\uFDA5'] = '\u062C\u0645\u064A';
+ t['\uFDA6'] = '\u062C\u062D\u0649';
+ t['\uFDA7'] = '\u062C\u0645\u0649';
+ t['\uFDA8'] = '\u0633\u062E\u0649';
+ t['\uFDA9'] = '\u0635\u062D\u064A';
+ t['\uFDAA'] = '\u0634\u062D\u064A';
+ t['\uFDAB'] = '\u0636\u062D\u064A';
+ t['\uFDAC'] = '\u0644\u062C\u064A';
+ t['\uFDAD'] = '\u0644\u0645\u064A';
+ t['\uFDAE'] = '\u064A\u062D\u064A';
+ t['\uFDAF'] = '\u064A\u062C\u064A';
+ t['\uFDB0'] = '\u064A\u0645\u064A';
+ t['\uFDB1'] = '\u0645\u0645\u064A';
+ t['\uFDB2'] = '\u0642\u0645\u064A';
+ t['\uFDB3'] = '\u0646\u062D\u064A';
+ t['\uFDB4'] = '\u0642\u0645\u062D';
+ t['\uFDB5'] = '\u0644\u062D\u0645';
+ t['\uFDB6'] = '\u0639\u0645\u064A';
+ t['\uFDB7'] = '\u0643\u0645\u064A';
+ t['\uFDB8'] = '\u0646\u062C\u062D';
+ t['\uFDB9'] = '\u0645\u062E\u064A';
+ t['\uFDBA'] = '\u0644\u062C\u0645';
+ t['\uFDBB'] = '\u0643\u0645\u0645';
+ t['\uFDBC'] = '\u0644\u062C\u0645';
+ t['\uFDBD'] = '\u0646\u062C\u062D';
+ t['\uFDBE'] = '\u062C\u062D\u064A';
+ t['\uFDBF'] = '\u062D\u062C\u064A';
+ t['\uFDC0'] = '\u0645\u062C\u064A';
+ t['\uFDC1'] = '\u0641\u0645\u064A';
+ t['\uFDC2'] = '\u0628\u062D\u064A';
+ t['\uFDC3'] = '\u0643\u0645\u0645';
+ t['\uFDC4'] = '\u0639\u062C\u0645';
+ t['\uFDC5'] = '\u0635\u0645\u0645';
+ t['\uFDC6'] = '\u0633\u062E\u064A';
+ t['\uFDC7'] = '\u0646\u062C\u064A';
+ t['\uFE49'] = '\u203E';
+ t['\uFE4A'] = '\u203E';
+ t['\uFE4B'] = '\u203E';
+ t['\uFE4C'] = '\u203E';
+ t['\uFE4D'] = '\u005F';
+ t['\uFE4E'] = '\u005F';
+ t['\uFE4F'] = '\u005F';
+ t['\uFE80'] = '\u0621';
+ t['\uFE81'] = '\u0622';
+ t['\uFE82'] = '\u0622';
+ t['\uFE83'] = '\u0623';
+ t['\uFE84'] = '\u0623';
+ t['\uFE85'] = '\u0624';
+ t['\uFE86'] = '\u0624';
+ t['\uFE87'] = '\u0625';
+ t['\uFE88'] = '\u0625';
+ t['\uFE89'] = '\u0626';
+ t['\uFE8A'] = '\u0626';
+ t['\uFE8B'] = '\u0626';
+ t['\uFE8C'] = '\u0626';
+ t['\uFE8D'] = '\u0627';
+ t['\uFE8E'] = '\u0627';
+ t['\uFE8F'] = '\u0628';
+ t['\uFE90'] = '\u0628';
+ t['\uFE91'] = '\u0628';
+ t['\uFE92'] = '\u0628';
+ t['\uFE93'] = '\u0629';
+ t['\uFE94'] = '\u0629';
+ t['\uFE95'] = '\u062A';
+ t['\uFE96'] = '\u062A';
+ t['\uFE97'] = '\u062A';
+ t['\uFE98'] = '\u062A';
+ t['\uFE99'] = '\u062B';
+ t['\uFE9A'] = '\u062B';
+ t['\uFE9B'] = '\u062B';
+ t['\uFE9C'] = '\u062B';
+ t['\uFE9D'] = '\u062C';
+ t['\uFE9E'] = '\u062C';
+ t['\uFE9F'] = '\u062C';
+ t['\uFEA0'] = '\u062C';
+ t['\uFEA1'] = '\u062D';
+ t['\uFEA2'] = '\u062D';
+ t['\uFEA3'] = '\u062D';
+ t['\uFEA4'] = '\u062D';
+ t['\uFEA5'] = '\u062E';
+ t['\uFEA6'] = '\u062E';
+ t['\uFEA7'] = '\u062E';
+ t['\uFEA8'] = '\u062E';
+ t['\uFEA9'] = '\u062F';
+ t['\uFEAA'] = '\u062F';
+ t['\uFEAB'] = '\u0630';
+ t['\uFEAC'] = '\u0630';
+ t['\uFEAD'] = '\u0631';
+ t['\uFEAE'] = '\u0631';
+ t['\uFEAF'] = '\u0632';
+ t['\uFEB0'] = '\u0632';
+ t['\uFEB1'] = '\u0633';
+ t['\uFEB2'] = '\u0633';
+ t['\uFEB3'] = '\u0633';
+ t['\uFEB4'] = '\u0633';
+ t['\uFEB5'] = '\u0634';
+ t['\uFEB6'] = '\u0634';
+ t['\uFEB7'] = '\u0634';
+ t['\uFEB8'] = '\u0634';
+ t['\uFEB9'] = '\u0635';
+ t['\uFEBA'] = '\u0635';
+ t['\uFEBB'] = '\u0635';
+ t['\uFEBC'] = '\u0635';
+ t['\uFEBD'] = '\u0636';
+ t['\uFEBE'] = '\u0636';
+ t['\uFEBF'] = '\u0636';
+ t['\uFEC0'] = '\u0636';
+ t['\uFEC1'] = '\u0637';
+ t['\uFEC2'] = '\u0637';
+ t['\uFEC3'] = '\u0637';
+ t['\uFEC4'] = '\u0637';
+ t['\uFEC5'] = '\u0638';
+ t['\uFEC6'] = '\u0638';
+ t['\uFEC7'] = '\u0638';
+ t['\uFEC8'] = '\u0638';
+ t['\uFEC9'] = '\u0639';
+ t['\uFECA'] = '\u0639';
+ t['\uFECB'] = '\u0639';
+ t['\uFECC'] = '\u0639';
+ t['\uFECD'] = '\u063A';
+ t['\uFECE'] = '\u063A';
+ t['\uFECF'] = '\u063A';
+ t['\uFED0'] = '\u063A';
+ t['\uFED1'] = '\u0641';
+ t['\uFED2'] = '\u0641';
+ t['\uFED3'] = '\u0641';
+ t['\uFED4'] = '\u0641';
+ t['\uFED5'] = '\u0642';
+ t['\uFED6'] = '\u0642';
+ t['\uFED7'] = '\u0642';
+ t['\uFED8'] = '\u0642';
+ t['\uFED9'] = '\u0643';
+ t['\uFEDA'] = '\u0643';
+ t['\uFEDB'] = '\u0643';
+ t['\uFEDC'] = '\u0643';
+ t['\uFEDD'] = '\u0644';
+ t['\uFEDE'] = '\u0644';
+ t['\uFEDF'] = '\u0644';
+ t['\uFEE0'] = '\u0644';
+ t['\uFEE1'] = '\u0645';
+ t['\uFEE2'] = '\u0645';
+ t['\uFEE3'] = '\u0645';
+ t['\uFEE4'] = '\u0645';
+ t['\uFEE5'] = '\u0646';
+ t['\uFEE6'] = '\u0646';
+ t['\uFEE7'] = '\u0646';
+ t['\uFEE8'] = '\u0646';
+ t['\uFEE9'] = '\u0647';
+ t['\uFEEA'] = '\u0647';
+ t['\uFEEB'] = '\u0647';
+ t['\uFEEC'] = '\u0647';
+ t['\uFEED'] = '\u0648';
+ t['\uFEEE'] = '\u0648';
+ t['\uFEEF'] = '\u0649';
+ t['\uFEF0'] = '\u0649';
+ t['\uFEF1'] = '\u064A';
+ t['\uFEF2'] = '\u064A';
+ t['\uFEF3'] = '\u064A';
+ t['\uFEF4'] = '\u064A';
+ t['\uFEF5'] = '\u0644\u0622';
+ t['\uFEF6'] = '\u0644\u0622';
+ t['\uFEF7'] = '\u0644\u0623';
+ t['\uFEF8'] = '\u0644\u0623';
+ t['\uFEF9'] = '\u0644\u0625';
+ t['\uFEFA'] = '\u0644\u0625';
+ t['\uFEFB'] = '\u0644\u0627';
+ t['\uFEFC'] = '\u0644\u0627';
+});
+function reverseIfRtl(chars) {
+ var charsLength = chars.length;
+ if (charsLength <= 1 || !isRTLRangeFor(chars.charCodeAt(0))) {
+  return chars;
+ }
+ var s = '';
+ for (var ii = charsLength - 1; ii >= 0; ii--) {
+  s += chars[ii];
+ }
+ return s;
+}
+exports.mapSpecialUnicodeValues = mapSpecialUnicodeValues;
+exports.reverseIfRtl = reverseIfRtl;
+exports.getUnicodeRangeFor = getUnicodeRangeFor;
+exports.getNormalizedUnicodes = getNormalizedUnicodes;
+exports.getUnicodeForGlyph = getUnicodeForGlyph;
+
+/***/ }),
+/* 181 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.FontRendererFactory = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _cff_parser = __w_pdfjs_require__(175);
+
+var _glyphlist = __w_pdfjs_require__(178);
+
+var _encodings = __w_pdfjs_require__(177);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _possibleConstructorReturn(self, call) { if (call && (_typeof(call) === "object" || typeof call === "function")) { return call; } return _assertThisInitialized(self); }
+
+function _assertThisInitialized(self) { if (self === void 0) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return self; }
+
+function _getPrototypeOf(o) { _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf : function _getPrototypeOf(o) { return o.__proto__ || Object.getPrototypeOf(o); }; return _getPrototypeOf(o); }
+
+function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function"); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, writable: true, configurable: true } }); if (superClass) _setPrototypeOf(subClass, superClass); }
+
+function _setPrototypeOf(o, p) { _setPrototypeOf = Object.setPrototypeOf || function _setPrototypeOf(o, p) { o.__proto__ = p; return o; }; return _setPrototypeOf(o, p); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var FontRendererFactory = function FontRendererFactoryClosure() {
+  function getLong(data, offset) {
+    return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
+  }
+
+  function getUshort(data, offset) {
+    return data[offset] << 8 | data[offset + 1];
+  }
+
+  function parseCmap(data, start, end) {
+    var offset = getUshort(data, start + 2) === 1 ? getLong(data, start + 8) : getLong(data, start + 16);
+    var format = getUshort(data, start + offset);
+    var ranges, p, i;
+
+    if (format === 4) {
+      getUshort(data, start + offset + 2);
+      var segCount = getUshort(data, start + offset + 6) >> 1;
+      p = start + offset + 14;
+      ranges = [];
+
+      for (i = 0; i < segCount; i++, p += 2) {
+        ranges[i] = {
+          end: getUshort(data, p)
+        };
+      }
+
+      p += 2;
+
+      for (i = 0; i < segCount; i++, p += 2) {
+        ranges[i].start = getUshort(data, p);
+      }
+
+      for (i = 0; i < segCount; i++, p += 2) {
+        ranges[i].idDelta = getUshort(data, p);
+      }
+
+      for (i = 0; i < segCount; i++, p += 2) {
+        var idOffset = getUshort(data, p);
+
+        if (idOffset === 0) {
+          continue;
+        }
+
+        ranges[i].ids = [];
+
+        for (var j = 0, jj = ranges[i].end - ranges[i].start + 1; j < jj; j++) {
+          ranges[i].ids[j] = getUshort(data, p + idOffset);
+          idOffset += 2;
+        }
+      }
+
+      return ranges;
+    } else if (format === 12) {
+      getLong(data, start + offset + 4);
+      var groups = getLong(data, start + offset + 12);
+      p = start + offset + 16;
+      ranges = [];
+
+      for (i = 0; i < groups; i++) {
+        ranges.push({
+          start: getLong(data, p),
+          end: getLong(data, p + 4),
+          idDelta: getLong(data, p + 8) - getLong(data, p)
+        });
+        p += 12;
+      }
+
+      return ranges;
+    }
+
+    throw new _util.FormatError("unsupported cmap: ".concat(format));
+  }
+
+  function parseCff(data, start, end, seacAnalysisEnabled) {
+    var properties = {};
+    var parser = new _cff_parser.CFFParser(new _stream.Stream(data, start, end - start), properties, seacAnalysisEnabled);
+    var cff = parser.parse();
+    return {
+      glyphs: cff.charStrings.objects,
+      subrs: cff.topDict.privateDict && cff.topDict.privateDict.subrsIndex && cff.topDict.privateDict.subrsIndex.objects,
+      gsubrs: cff.globalSubrIndex && cff.globalSubrIndex.objects,
+      isCFFCIDFont: cff.isCIDFont,
+      fdSelect: cff.fdSelect,
+      fdArray: cff.fdArray
+    };
+  }
+
+  function parseGlyfTable(glyf, loca, isGlyphLocationsLong) {
+    var itemSize, itemDecode;
+
+    if (isGlyphLocationsLong) {
+      itemSize = 4;
+
+      itemDecode = function fontItemDecodeLong(data, offset) {
+        return data[offset] << 24 | data[offset + 1] << 16 | data[offset + 2] << 8 | data[offset + 3];
+      };
+    } else {
+      itemSize = 2;
+
+      itemDecode = function fontItemDecode(data, offset) {
+        return data[offset] << 9 | data[offset + 1] << 1;
+      };
+    }
+
+    var glyphs = [];
+    var startOffset = itemDecode(loca, 0);
+
+    for (var j = itemSize; j < loca.length; j += itemSize) {
+      var endOffset = itemDecode(loca, j);
+      glyphs.push(glyf.subarray(startOffset, endOffset));
+      startOffset = endOffset;
+    }
+
+    return glyphs;
+  }
+
+  function lookupCmap(ranges, unicode) {
+    var code = unicode.codePointAt(0),
+        gid = 0;
+    var l = 0,
+        r = ranges.length - 1;
+
+    while (l < r) {
+      var c = l + r + 1 >> 1;
+
+      if (code < ranges[c].start) {
+        r = c - 1;
+      } else {
+        l = c;
+      }
+    }
+
+    if (ranges[l].start <= code && code <= ranges[l].end) {
+      gid = ranges[l].idDelta + (ranges[l].ids ? ranges[l].ids[code - ranges[l].start] : code) & 0xFFFF;
+    }
+
+    return {
+      charCode: code,
+      glyphId: gid
+    };
+  }
+
+  function compileGlyf(code, cmds, font) {
+    function moveTo(x, y) {
+      cmds.push({
+        cmd: 'moveTo',
+        args: [x, y]
+      });
+    }
+
+    function lineTo(x, y) {
+      cmds.push({
+        cmd: 'lineTo',
+        args: [x, y]
+      });
+    }
+
+    function quadraticCurveTo(xa, ya, x, y) {
+      cmds.push({
+        cmd: 'quadraticCurveTo',
+        args: [xa, ya, x, y]
+      });
+    }
+
+    var i = 0;
+    var numberOfContours = (code[i] << 24 | code[i + 1] << 16) >> 16;
+    var flags;
+    var x = 0,
+        y = 0;
+    i += 10;
+
+    if (numberOfContours < 0) {
+      do {
+        flags = code[i] << 8 | code[i + 1];
+        var glyphIndex = code[i + 2] << 8 | code[i + 3];
+        i += 4;
+        var arg1, arg2;
+
+        if (flags & 0x01) {
+          arg1 = (code[i] << 24 | code[i + 1] << 16) >> 16;
+          arg2 = (code[i + 2] << 24 | code[i + 3] << 16) >> 16;
+          i += 4;
+        } else {
+          arg1 = code[i++];
+          arg2 = code[i++];
+        }
+
+        if (flags & 0x02) {
+          x = arg1;
+          y = arg2;
+        } else {
+          x = 0;
+          y = 0;
+        }
+
+        var scaleX = 1,
+            scaleY = 1,
+            scale01 = 0,
+            scale10 = 0;
+
+        if (flags & 0x08) {
+          scaleX = scaleY = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
+          i += 2;
+        } else if (flags & 0x40) {
+          scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
+          scaleY = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
+          i += 4;
+        } else if (flags & 0x80) {
+          scaleX = (code[i] << 24 | code[i + 1] << 16) / 1073741824;
+          scale01 = (code[i + 2] << 24 | code[i + 3] << 16) / 1073741824;
+          scale10 = (code[i + 4] << 24 | code[i + 5] << 16) / 1073741824;
+          scaleY = (code[i + 6] << 24 | code[i + 7] << 16) / 1073741824;
+          i += 8;
+        }
+
+        var subglyph = font.glyphs[glyphIndex];
+
+        if (subglyph) {
+          cmds.push({
+            cmd: 'save'
+          });
+          cmds.push({
+            cmd: 'transform',
+            args: [scaleX, scale01, scale10, scaleY, x, y]
+          });
+          compileGlyf(subglyph, cmds, font);
+          cmds.push({
+            cmd: 'restore'
+          });
+        }
+      } while (flags & 0x20);
+    } else {
+      var endPtsOfContours = [];
+      var j, jj;
+
+      for (j = 0; j < numberOfContours; j++) {
+        endPtsOfContours.push(code[i] << 8 | code[i + 1]);
+        i += 2;
+      }
+
+      var instructionLength = code[i] << 8 | code[i + 1];
+      i += 2 + instructionLength;
+      var numberOfPoints = endPtsOfContours[endPtsOfContours.length - 1] + 1;
+      var points = [];
+
+      while (points.length < numberOfPoints) {
+        flags = code[i++];
+        var repeat = 1;
+
+        if (flags & 0x08) {
+          repeat += code[i++];
+        }
+
+        while (repeat-- > 0) {
+          points.push({
+            flags: flags
+          });
+        }
+      }
+
+      for (j = 0; j < numberOfPoints; j++) {
+        switch (points[j].flags & 0x12) {
+          case 0x00:
+            x += (code[i] << 24 | code[i + 1] << 16) >> 16;
+            i += 2;
+            break;
+
+          case 0x02:
+            x -= code[i++];
+            break;
+
+          case 0x12:
+            x += code[i++];
+            break;
+        }
+
+        points[j].x = x;
+      }
+
+      for (j = 0; j < numberOfPoints; j++) {
+        switch (points[j].flags & 0x24) {
+          case 0x00:
+            y += (code[i] << 24 | code[i + 1] << 16) >> 16;
+            i += 2;
+            break;
+
+          case 0x04:
+            y -= code[i++];
+            break;
+
+          case 0x24:
+            y += code[i++];
+            break;
+        }
+
+        points[j].y = y;
+      }
+
+      var startPoint = 0;
+
+      for (i = 0; i < numberOfContours; i++) {
+        var endPoint = endPtsOfContours[i];
+        var contour = points.slice(startPoint, endPoint + 1);
+
+        if (contour[0].flags & 1) {
+          contour.push(contour[0]);
+        } else if (contour[contour.length - 1].flags & 1) {
+          contour.unshift(contour[contour.length - 1]);
+        } else {
+          var p = {
+            flags: 1,
+            x: (contour[0].x + contour[contour.length - 1].x) / 2,
+            y: (contour[0].y + contour[contour.length - 1].y) / 2
+          };
+          contour.unshift(p);
+          contour.push(p);
+        }
+
+        moveTo(contour[0].x, contour[0].y);
+
+        for (j = 1, jj = contour.length; j < jj; j++) {
+          if (contour[j].flags & 1) {
+            lineTo(contour[j].x, contour[j].y);
+          } else if (contour[j + 1].flags & 1) {
+            quadraticCurveTo(contour[j].x, contour[j].y, contour[j + 1].x, contour[j + 1].y);
+            j++;
+          } else {
+            quadraticCurveTo(contour[j].x, contour[j].y, (contour[j].x + contour[j + 1].x) / 2, (contour[j].y + contour[j + 1].y) / 2);
+          }
+        }
+
+        startPoint = endPoint + 1;
+      }
+    }
+  }
+
+  function compileCharString(code, cmds, font, glyphId) {
+    var stack = [];
+    var x = 0,
+        y = 0;
+    var stems = 0;
+
+    function moveTo(x, y) {
+      cmds.push({
+        cmd: 'moveTo',
+        args: [x, y]
+      });
+    }
+
+    function lineTo(x, y) {
+      cmds.push({
+        cmd: 'lineTo',
+        args: [x, y]
+      });
+    }
+
+    function bezierCurveTo(x1, y1, x2, y2, x, y) {
+      cmds.push({
+        cmd: 'bezierCurveTo',
+        args: [x1, y1, x2, y2, x, y]
+      });
+    }
+
+    function parse(code) {
+      var i = 0;
+
+      while (i < code.length) {
+        var stackClean = false;
+        var v = code[i++];
+        var xa, xb, ya, yb, y1, y2, y3, n, subrCode;
+
+        switch (v) {
+          case 1:
+            stems += stack.length >> 1;
+            stackClean = true;
+            break;
+
+          case 3:
+            stems += stack.length >> 1;
+            stackClean = true;
+            break;
+
+          case 4:
+            y += stack.pop();
+            moveTo(x, y);
+            stackClean = true;
+            break;
+
+          case 5:
+            while (stack.length > 0) {
+              x += stack.shift();
+              y += stack.shift();
+              lineTo(x, y);
+            }
+
+            break;
+
+          case 6:
+            while (stack.length > 0) {
+              x += stack.shift();
+              lineTo(x, y);
+
+              if (stack.length === 0) {
+                break;
+              }
+
+              y += stack.shift();
+              lineTo(x, y);
+            }
+
+            break;
+
+          case 7:
+            while (stack.length > 0) {
+              y += stack.shift();
+              lineTo(x, y);
+
+              if (stack.length === 0) {
+                break;
+              }
+
+              x += stack.shift();
+              lineTo(x, y);
+            }
+
+            break;
+
+          case 8:
+            while (stack.length > 0) {
+              xa = x + stack.shift();
+              ya = y + stack.shift();
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb + stack.shift();
+              y = yb + stack.shift();
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            break;
+
+          case 10:
+            n = stack.pop();
+            subrCode = null;
+
+            if (font.isCFFCIDFont) {
+              var fdIndex = font.fdSelect.getFDIndex(glyphId);
+
+              if (fdIndex >= 0 && fdIndex < font.fdArray.length) {
+                var fontDict = font.fdArray[fdIndex],
+                    subrs = void 0;
+
+                if (fontDict.privateDict && fontDict.privateDict.subrsIndex) {
+                  subrs = fontDict.privateDict.subrsIndex.objects;
+                }
+
+                if (subrs) {
+                  var numSubrs = subrs.length;
+                  n += numSubrs < 1240 ? 107 : numSubrs < 33900 ? 1131 : 32768;
+                  subrCode = subrs[n];
+                }
+              } else {
+                (0, _util.warn)('Invalid fd index for glyph index.');
+              }
+            } else {
+              subrCode = font.subrs[n + font.subrsBias];
+            }
+
+            if (subrCode) {
+              parse(subrCode);
+            }
+
+            break;
+
+          case 11:
+            return;
+
+          case 12:
+            v = code[i++];
+
+            switch (v) {
+              case 34:
+                xa = x + stack.shift();
+                xb = xa + stack.shift();
+                y1 = y + stack.shift();
+                x = xb + stack.shift();
+                bezierCurveTo(xa, y, xb, y1, x, y1);
+                xa = x + stack.shift();
+                xb = xa + stack.shift();
+                x = xb + stack.shift();
+                bezierCurveTo(xa, y1, xb, y, x, y);
+                break;
+
+              case 35:
+                xa = x + stack.shift();
+                ya = y + stack.shift();
+                xb = xa + stack.shift();
+                yb = ya + stack.shift();
+                x = xb + stack.shift();
+                y = yb + stack.shift();
+                bezierCurveTo(xa, ya, xb, yb, x, y);
+                xa = x + stack.shift();
+                ya = y + stack.shift();
+                xb = xa + stack.shift();
+                yb = ya + stack.shift();
+                x = xb + stack.shift();
+                y = yb + stack.shift();
+                bezierCurveTo(xa, ya, xb, yb, x, y);
+                stack.pop();
+                break;
+
+              case 36:
+                xa = x + stack.shift();
+                y1 = y + stack.shift();
+                xb = xa + stack.shift();
+                y2 = y1 + stack.shift();
+                x = xb + stack.shift();
+                bezierCurveTo(xa, y1, xb, y2, x, y2);
+                xa = x + stack.shift();
+                xb = xa + stack.shift();
+                y3 = y2 + stack.shift();
+                x = xb + stack.shift();
+                bezierCurveTo(xa, y2, xb, y3, x, y);
+                break;
+
+              case 37:
+                var x0 = x,
+                    y0 = y;
+                xa = x + stack.shift();
+                ya = y + stack.shift();
+                xb = xa + stack.shift();
+                yb = ya + stack.shift();
+                x = xb + stack.shift();
+                y = yb + stack.shift();
+                bezierCurveTo(xa, ya, xb, yb, x, y);
+                xa = x + stack.shift();
+                ya = y + stack.shift();
+                xb = xa + stack.shift();
+                yb = ya + stack.shift();
+                x = xb;
+                y = yb;
+
+                if (Math.abs(x - x0) > Math.abs(y - y0)) {
+                  x += stack.shift();
+                } else {
+                  y += stack.shift();
+                }
+
+                bezierCurveTo(xa, ya, xb, yb, x, y);
+                break;
+
+              default:
+                throw new _util.FormatError("unknown operator: 12 ".concat(v));
+            }
+
+            break;
+
+          case 14:
+            if (stack.length >= 4) {
+              var achar = stack.pop();
+              var bchar = stack.pop();
+              y = stack.pop();
+              x = stack.pop();
+              cmds.push({
+                cmd: 'save'
+              });
+              cmds.push({
+                cmd: 'translate',
+                args: [x, y]
+              });
+              var cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[achar]]));
+              compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
+              cmds.push({
+                cmd: 'restore'
+              });
+              cmap = lookupCmap(font.cmap, String.fromCharCode(font.glyphNameMap[_encodings.StandardEncoding[bchar]]));
+              compileCharString(font.glyphs[cmap.glyphId], cmds, font, cmap.glyphId);
+            }
+
+            return;
+
+          case 18:
+            stems += stack.length >> 1;
+            stackClean = true;
+            break;
+
+          case 19:
+            stems += stack.length >> 1;
+            i += stems + 7 >> 3;
+            stackClean = true;
+            break;
+
+          case 20:
+            stems += stack.length >> 1;
+            i += stems + 7 >> 3;
+            stackClean = true;
+            break;
+
+          case 21:
+            y += stack.pop();
+            x += stack.pop();
+            moveTo(x, y);
+            stackClean = true;
+            break;
+
+          case 22:
+            x += stack.pop();
+            moveTo(x, y);
+            stackClean = true;
+            break;
+
+          case 23:
+            stems += stack.length >> 1;
+            stackClean = true;
+            break;
+
+          case 24:
+            while (stack.length > 2) {
+              xa = x + stack.shift();
+              ya = y + stack.shift();
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb + stack.shift();
+              y = yb + stack.shift();
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            x += stack.shift();
+            y += stack.shift();
+            lineTo(x, y);
+            break;
+
+          case 25:
+            while (stack.length > 6) {
+              x += stack.shift();
+              y += stack.shift();
+              lineTo(x, y);
+            }
+
+            xa = x + stack.shift();
+            ya = y + stack.shift();
+            xb = xa + stack.shift();
+            yb = ya + stack.shift();
+            x = xb + stack.shift();
+            y = yb + stack.shift();
+            bezierCurveTo(xa, ya, xb, yb, x, y);
+            break;
+
+          case 26:
+            if (stack.length % 2) {
+              x += stack.shift();
+            }
+
+            while (stack.length > 0) {
+              xa = x;
+              ya = y + stack.shift();
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb;
+              y = yb + stack.shift();
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            break;
+
+          case 27:
+            if (stack.length % 2) {
+              y += stack.shift();
+            }
+
+            while (stack.length > 0) {
+              xa = x + stack.shift();
+              ya = y;
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb + stack.shift();
+              y = yb;
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            break;
+
+          case 28:
+            stack.push((code[i] << 24 | code[i + 1] << 16) >> 16);
+            i += 2;
+            break;
+
+          case 29:
+            n = stack.pop() + font.gsubrsBias;
+            subrCode = font.gsubrs[n];
+
+            if (subrCode) {
+              parse(subrCode);
+            }
+
+            break;
+
+          case 30:
+            while (stack.length > 0) {
+              xa = x;
+              ya = y + stack.shift();
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb + stack.shift();
+              y = yb + (stack.length === 1 ? stack.shift() : 0);
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+
+              if (stack.length === 0) {
+                break;
+              }
+
+              xa = x + stack.shift();
+              ya = y;
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              y = yb + stack.shift();
+              x = xb + (stack.length === 1 ? stack.shift() : 0);
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            break;
+
+          case 31:
+            while (stack.length > 0) {
+              xa = x + stack.shift();
+              ya = y;
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              y = yb + stack.shift();
+              x = xb + (stack.length === 1 ? stack.shift() : 0);
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+
+              if (stack.length === 0) {
+                break;
+              }
+
+              xa = x;
+              ya = y + stack.shift();
+              xb = xa + stack.shift();
+              yb = ya + stack.shift();
+              x = xb + stack.shift();
+              y = yb + (stack.length === 1 ? stack.shift() : 0);
+              bezierCurveTo(xa, ya, xb, yb, x, y);
+            }
+
+            break;
+
+          default:
+            if (v < 32) {
+              throw new _util.FormatError("unknown operator: ".concat(v));
+            }
+
+            if (v < 247) {
+              stack.push(v - 139);
+            } else if (v < 251) {
+              stack.push((v - 247) * 256 + code[i++] + 108);
+            } else if (v < 255) {
+              stack.push(-(v - 251) * 256 - code[i++] - 108);
+            } else {
+              stack.push((code[i] << 24 | code[i + 1] << 16 | code[i + 2] << 8 | code[i + 3]) / 65536);
+              i += 4;
+            }
+
+            break;
+        }
+
+        if (stackClean) {
+          stack.length = 0;
+        }
+      }
+    }
+
+    parse(code);
+  }
+
+  var NOOP = [];
+
+  var CompiledFont =
+  /*#__PURE__*/
+  function () {
+    function CompiledFont(fontMatrix) {
+      _classCallCheck(this, CompiledFont);
+
+      if (this.constructor === CompiledFont) {
+        (0, _util.unreachable)('Cannot initialize CompiledFont.');
+      }
+
+      this.fontMatrix = fontMatrix;
+      this.compiledGlyphs = Object.create(null);
+      this.compiledCharCodeToGlyphId = Object.create(null);
+    }
+
+    _createClass(CompiledFont, [{
+      key: "getPathJs",
+      value: function getPathJs(unicode) {
+        var cmap = lookupCmap(this.cmap, unicode);
+        var fn = this.compiledGlyphs[cmap.glyphId];
+
+        if (!fn) {
+          fn = this.compileGlyph(this.glyphs[cmap.glyphId], cmap.glyphId);
+          this.compiledGlyphs[cmap.glyphId] = fn;
+        }
+
+        if (this.compiledCharCodeToGlyphId[cmap.charCode] === undefined) {
+          this.compiledCharCodeToGlyphId[cmap.charCode] = cmap.glyphId;
+        }
+
+        return fn;
+      }
+    }, {
+      key: "compileGlyph",
+      value: function compileGlyph(code, glyphId) {
+        if (!code || code.length === 0 || code[0] === 14) {
+          return NOOP;
+        }
+
+        var fontMatrix = this.fontMatrix;
+
+        if (this.isCFFCIDFont) {
+          var fdIndex = this.fdSelect.getFDIndex(glyphId);
+
+          if (fdIndex >= 0 && fdIndex < this.fdArray.length) {
+            var fontDict = this.fdArray[fdIndex];
+            fontMatrix = fontDict.getByName('FontMatrix') || _util.FONT_IDENTITY_MATRIX;
+          } else {
+            (0, _util.warn)('Invalid fd index for glyph index.');
+          }
+        }
+
+        var cmds = [];
+        cmds.push({
+          cmd: 'save'
+        });
+        cmds.push({
+          cmd: 'transform',
+          args: fontMatrix.slice()
+        });
+        cmds.push({
+          cmd: 'scale',
+          args: ['size', '-size']
+        });
+        this.compileGlyphImpl(code, cmds, glyphId);
+        cmds.push({
+          cmd: 'restore'
+        });
+        return cmds;
+      }
+    }, {
+      key: "compileGlyphImpl",
+      value: function compileGlyphImpl() {
+        (0, _util.unreachable)('Children classes should implement this.');
+      }
+    }, {
+      key: "hasBuiltPath",
+      value: function hasBuiltPath(unicode) {
+        var cmap = lookupCmap(this.cmap, unicode);
+        return this.compiledGlyphs[cmap.glyphId] !== undefined && this.compiledCharCodeToGlyphId[cmap.charCode] !== undefined;
+      }
+    }]);
+
+    return CompiledFont;
+  }();
+
+  var TrueTypeCompiled =
+  /*#__PURE__*/
+  function (_CompiledFont) {
+    _inherits(TrueTypeCompiled, _CompiledFont);
+
+    function TrueTypeCompiled(glyphs, cmap, fontMatrix) {
+      var _this;
+
+      _classCallCheck(this, TrueTypeCompiled);
+
+      _this = _possibleConstructorReturn(this, _getPrototypeOf(TrueTypeCompiled).call(this, fontMatrix || [0.000488, 0, 0, 0.000488, 0, 0]));
+      _this.glyphs = glyphs;
+      _this.cmap = cmap;
+      return _this;
+    }
+
+    _createClass(TrueTypeCompiled, [{
+      key: "compileGlyphImpl",
+      value: function compileGlyphImpl(code, cmds) {
+        compileGlyf(code, cmds, this);
+      }
+    }]);
+
+    return TrueTypeCompiled;
+  }(CompiledFont);
+
+  var Type2Compiled =
+  /*#__PURE__*/
+  function (_CompiledFont2) {
+    _inherits(Type2Compiled, _CompiledFont2);
+
+    function Type2Compiled(cffInfo, cmap, fontMatrix, glyphNameMap) {
+      var _this2;
+
+      _classCallCheck(this, Type2Compiled);
+
+      _this2 = _possibleConstructorReturn(this, _getPrototypeOf(Type2Compiled).call(this, fontMatrix || [0.001, 0, 0, 0.001, 0, 0]));
+      _this2.glyphs = cffInfo.glyphs;
+      _this2.gsubrs = cffInfo.gsubrs || [];
+      _this2.subrs = cffInfo.subrs || [];
+      _this2.cmap = cmap;
+      _this2.glyphNameMap = glyphNameMap || (0, _glyphlist.getGlyphsUnicode)();
+      _this2.gsubrsBias = _this2.gsubrs.length < 1240 ? 107 : _this2.gsubrs.length < 33900 ? 1131 : 32768;
+      _this2.subrsBias = _this2.subrs.length < 1240 ? 107 : _this2.subrs.length < 33900 ? 1131 : 32768;
+      _this2.isCFFCIDFont = cffInfo.isCFFCIDFont;
+      _this2.fdSelect = cffInfo.fdSelect;
+      _this2.fdArray = cffInfo.fdArray;
+      return _this2;
+    }
+
+    _createClass(Type2Compiled, [{
+      key: "compileGlyphImpl",
+      value: function compileGlyphImpl(code, cmds, glyphId) {
+        compileCharString(code, cmds, this, glyphId);
+      }
+    }]);
+
+    return Type2Compiled;
+  }(CompiledFont);
+
+  return {
+    create: function FontRendererFactory_create(font, seacAnalysisEnabled) {
+      var data = new Uint8Array(font.data);
+      var cmap, glyf, loca, cff, indexToLocFormat, unitsPerEm;
+      var numTables = getUshort(data, 4);
+
+      for (var i = 0, p = 12; i < numTables; i++, p += 16) {
+        var tag = (0, _util.bytesToString)(data.subarray(p, p + 4));
+        var offset = getLong(data, p + 8);
+        var length = getLong(data, p + 12);
+
+        switch (tag) {
+          case 'cmap':
+            cmap = parseCmap(data, offset, offset + length);
+            break;
+
+          case 'glyf':
+            glyf = data.subarray(offset, offset + length);
+            break;
+
+          case 'loca':
+            loca = data.subarray(offset, offset + length);
+            break;
+
+          case 'head':
+            unitsPerEm = getUshort(data, offset + 18);
+            indexToLocFormat = getUshort(data, offset + 50);
+            break;
+
+          case 'CFF ':
+            cff = parseCff(data, offset, offset + length, seacAnalysisEnabled);
+            break;
+        }
+      }
+
+      if (glyf) {
+        var fontMatrix = !unitsPerEm ? font.fontMatrix : [1 / unitsPerEm, 0, 0, 1 / unitsPerEm, 0, 0];
+        return new TrueTypeCompiled(parseGlyfTable(glyf, loca, indexToLocFormat), cmap, fontMatrix);
+      }
+
+      return new Type2Compiled(cff, cmap, font.fontMatrix, font.glyphNameMap);
+    }
+  };
+}();
+
+exports.FontRendererFactory = FontRendererFactory;
+
+/***/ }),
+/* 182 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.Type1Parser = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _encodings = __w_pdfjs_require__(177);
+
+var _stream = __w_pdfjs_require__(158);
+
+var HINTING_ENABLED = false;
+
+var Type1CharString = function Type1CharStringClosure() {
+  var COMMAND_MAP = {
+    'hstem': [1],
+    'vstem': [3],
+    'vmoveto': [4],
+    'rlineto': [5],
+    'hlineto': [6],
+    'vlineto': [7],
+    'rrcurveto': [8],
+    'callsubr': [10],
+    'flex': [12, 35],
+    'drop': [12, 18],
+    'endchar': [14],
+    'rmoveto': [21],
+    'hmoveto': [22],
+    'vhcurveto': [30],
+    'hvcurveto': [31]
+  };
+
+  function Type1CharString() {
+    this.width = 0;
+    this.lsb = 0;
+    this.flexing = false;
+    this.output = [];
+    this.stack = [];
+  }
+
+  Type1CharString.prototype = {
+    convert: function Type1CharString_convert(encoded, subrs, seacAnalysisEnabled) {
+      var count = encoded.length;
+      var error = false;
+      var wx, sbx, subrNumber;
+
+      for (var i = 0; i < count; i++) {
+        var value = encoded[i];
+
+        if (value < 32) {
+          if (value === 12) {
+            value = (value << 8) + encoded[++i];
+          }
+
+          switch (value) {
+            case 1:
+              if (!HINTING_ENABLED) {
+                this.stack = [];
+                break;
+              }
+
+              error = this.executeCommand(2, COMMAND_MAP.hstem);
+              break;
+
+            case 3:
+              if (!HINTING_ENABLED) {
+                this.stack = [];
+                break;
+              }
+
+              error = this.executeCommand(2, COMMAND_MAP.vstem);
+              break;
+
+            case 4:
+              if (this.flexing) {
+                if (this.stack.length < 1) {
+                  error = true;
+                  break;
+                }
+
+                var dy = this.stack.pop();
+                this.stack.push(0, dy);
+                break;
+              }
+
+              error = this.executeCommand(1, COMMAND_MAP.vmoveto);
+              break;
+
+            case 5:
+              error = this.executeCommand(2, COMMAND_MAP.rlineto);
+              break;
+
+            case 6:
+              error = this.executeCommand(1, COMMAND_MAP.hlineto);
+              break;
+
+            case 7:
+              error = this.executeCommand(1, COMMAND_MAP.vlineto);
+              break;
+
+            case 8:
+              error = this.executeCommand(6, COMMAND_MAP.rrcurveto);
+              break;
+
+            case 9:
+              this.stack = [];
+              break;
+
+            case 10:
+              if (this.stack.length < 1) {
+                error = true;
+                break;
+              }
+
+              subrNumber = this.stack.pop();
+
+              if (!subrs[subrNumber]) {
+                error = true;
+                break;
+              }
+
+              error = this.convert(subrs[subrNumber], subrs, seacAnalysisEnabled);
+              break;
+
+            case 11:
+              return error;
+
+            case 13:
+              if (this.stack.length < 2) {
+                error = true;
+                break;
+              }
+
+              wx = this.stack.pop();
+              sbx = this.stack.pop();
+              this.lsb = sbx;
+              this.width = wx;
+              this.stack.push(wx, sbx);
+              error = this.executeCommand(2, COMMAND_MAP.hmoveto);
+              break;
+
+            case 14:
+              this.output.push(COMMAND_MAP.endchar[0]);
+              break;
+
+            case 21:
+              if (this.flexing) {
+                break;
+              }
+
+              error = this.executeCommand(2, COMMAND_MAP.rmoveto);
+              break;
+
+            case 22:
+              if (this.flexing) {
+                this.stack.push(0);
+                break;
+              }
+
+              error = this.executeCommand(1, COMMAND_MAP.hmoveto);
+              break;
+
+            case 30:
+              error = this.executeCommand(4, COMMAND_MAP.vhcurveto);
+              break;
+
+            case 31:
+              error = this.executeCommand(4, COMMAND_MAP.hvcurveto);
+              break;
+
+            case (12 << 8) + 0:
+              this.stack = [];
+              break;
+
+            case (12 << 8) + 1:
+              if (!HINTING_ENABLED) {
+                this.stack = [];
+                break;
+              }
+
+              error = this.executeCommand(2, COMMAND_MAP.vstem);
+              break;
+
+            case (12 << 8) + 2:
+              if (!HINTING_ENABLED) {
+                this.stack = [];
+                break;
+              }
+
+              error = this.executeCommand(2, COMMAND_MAP.hstem);
+              break;
+
+            case (12 << 8) + 6:
+              if (seacAnalysisEnabled) {
+                this.seac = this.stack.splice(-4, 4);
+                error = this.executeCommand(0, COMMAND_MAP.endchar);
+              } else {
+                error = this.executeCommand(4, COMMAND_MAP.endchar);
+              }
+
+              break;
+
+            case (12 << 8) + 7:
+              if (this.stack.length < 4) {
+                error = true;
+                break;
+              }
+
+              this.stack.pop();
+              wx = this.stack.pop();
+              var sby = this.stack.pop();
+              sbx = this.stack.pop();
+              this.lsb = sbx;
+              this.width = wx;
+              this.stack.push(wx, sbx, sby);
+              error = this.executeCommand(3, COMMAND_MAP.rmoveto);
+              break;
+
+            case (12 << 8) + 12:
+              if (this.stack.length < 2) {
+                error = true;
+                break;
+              }
+
+              var num2 = this.stack.pop();
+              var num1 = this.stack.pop();
+              this.stack.push(num1 / num2);
+              break;
+
+            case (12 << 8) + 16:
+              if (this.stack.length < 2) {
+                error = true;
+                break;
+              }
+
+              subrNumber = this.stack.pop();
+              var numArgs = this.stack.pop();
+
+              if (subrNumber === 0 && numArgs === 3) {
+                var flexArgs = this.stack.splice(this.stack.length - 17, 17);
+                this.stack.push(flexArgs[2] + flexArgs[0], flexArgs[3] + flexArgs[1], flexArgs[4], flexArgs[5], flexArgs[6], flexArgs[7], flexArgs[8], flexArgs[9], flexArgs[10], flexArgs[11], flexArgs[12], flexArgs[13], flexArgs[14]);
+                error = this.executeCommand(13, COMMAND_MAP.flex, true);
+                this.flexing = false;
+                this.stack.push(flexArgs[15], flexArgs[16]);
+              } else if (subrNumber === 1 && numArgs === 0) {
+                this.flexing = true;
+              }
+
+              break;
+
+            case (12 << 8) + 17:
+              break;
+
+            case (12 << 8) + 33:
+              this.stack = [];
+              break;
+
+            default:
+              (0, _util.warn)('Unknown type 1 charstring command of "' + value + '"');
+              break;
+          }
+
+          if (error) {
+            break;
+          }
+
+          continue;
+        } else if (value <= 246) {
+          value = value - 139;
+        } else if (value <= 250) {
+          value = (value - 247) * 256 + encoded[++i] + 108;
+        } else if (value <= 254) {
+          value = -((value - 251) * 256) - encoded[++i] - 108;
+        } else {
+          value = (encoded[++i] & 0xff) << 24 | (encoded[++i] & 0xff) << 16 | (encoded[++i] & 0xff) << 8 | (encoded[++i] & 0xff) << 0;
+        }
+
+        this.stack.push(value);
+      }
+
+      return error;
+    },
+    executeCommand: function executeCommand(howManyArgs, command, keepStack) {
+      var stackLength = this.stack.length;
+
+      if (howManyArgs > stackLength) {
+        return true;
+      }
+
+      var start = stackLength - howManyArgs;
+
+      for (var i = start; i < stackLength; i++) {
+        var value = this.stack[i];
+
+        if (Number.isInteger(value)) {
+          this.output.push(28, value >> 8 & 0xff, value & 0xff);
+        } else {
+          value = 65536 * value | 0;
+          this.output.push(255, value >> 24 & 0xFF, value >> 16 & 0xFF, value >> 8 & 0xFF, value & 0xFF);
+        }
+      }
+
+      this.output.push.apply(this.output, command);
+
+      if (keepStack) {
+        this.stack.splice(start, howManyArgs);
+      } else {
+        this.stack.length = 0;
+      }
+
+      return false;
+    }
+  };
+  return Type1CharString;
+}();
+
+var Type1Parser = function Type1ParserClosure() {
+  var EEXEC_ENCRYPT_KEY = 55665;
+  var CHAR_STRS_ENCRYPT_KEY = 4330;
+
+  function isHexDigit(code) {
+    return code >= 48 && code <= 57 || code >= 65 && code <= 70 || code >= 97 && code <= 102;
+  }
+
+  function decrypt(data, key, discardNumber) {
+    if (discardNumber >= data.length) {
+      return new Uint8Array(0);
+    }
+
+    var r = key | 0,
+        c1 = 52845,
+        c2 = 22719,
+        i,
+        j;
+
+    for (i = 0; i < discardNumber; i++) {
+      r = (data[i] + r) * c1 + c2 & (1 << 16) - 1;
+    }
+
+    var count = data.length - discardNumber;
+    var decrypted = new Uint8Array(count);
+
+    for (i = discardNumber, j = 0; j < count; i++, j++) {
+      var value = data[i];
+      decrypted[j] = value ^ r >> 8;
+      r = (value + r) * c1 + c2 & (1 << 16) - 1;
+    }
+
+    return decrypted;
+  }
+
+  function decryptAscii(data, key, discardNumber) {
+    var r = key | 0,
+        c1 = 52845,
+        c2 = 22719;
+    var count = data.length,
+        maybeLength = count >>> 1;
+    var decrypted = new Uint8Array(maybeLength);
+    var i, j;
+
+    for (i = 0, j = 0; i < count; i++) {
+      var digit1 = data[i];
+
+      if (!isHexDigit(digit1)) {
+        continue;
+      }
+
+      i++;
+      var digit2;
+
+      while (i < count && !isHexDigit(digit2 = data[i])) {
+        i++;
+      }
+
+      if (i < count) {
+        var value = parseInt(String.fromCharCode(digit1, digit2), 16);
+        decrypted[j++] = value ^ r >> 8;
+        r = (value + r) * c1 + c2 & (1 << 16) - 1;
+      }
+    }
+
+    return Array.prototype.slice.call(decrypted, discardNumber, j);
+  }
+
+  function isSpecial(c) {
+    return c === 0x2F || c === 0x5B || c === 0x5D || c === 0x7B || c === 0x7D || c === 0x28 || c === 0x29;
+  }
+
+  function Type1Parser(stream, encrypted, seacAnalysisEnabled) {
+    if (encrypted) {
+      var data = stream.getBytes();
+      var isBinary = !(isHexDigit(data[0]) && isHexDigit(data[1]) && isHexDigit(data[2]) && isHexDigit(data[3]));
+      stream = new _stream.Stream(isBinary ? decrypt(data, EEXEC_ENCRYPT_KEY, 4) : decryptAscii(data, EEXEC_ENCRYPT_KEY, 4));
+    }
+
+    this.seacAnalysisEnabled = !!seacAnalysisEnabled;
+    this.stream = stream;
+    this.nextChar();
+  }
+
+  Type1Parser.prototype = {
+    readNumberArray: function Type1Parser_readNumberArray() {
+      this.getToken();
+      var array = [];
+
+      while (true) {
+        var token = this.getToken();
+
+        if (token === null || token === ']' || token === '}') {
+          break;
+        }
+
+        array.push(parseFloat(token || 0));
+      }
+
+      return array;
+    },
+    readNumber: function Type1Parser_readNumber() {
+      var token = this.getToken();
+      return parseFloat(token || 0);
+    },
+    readInt: function Type1Parser_readInt() {
+      var token = this.getToken();
+      return parseInt(token || 0, 10) | 0;
+    },
+    readBoolean: function Type1Parser_readBoolean() {
+      var token = this.getToken();
+      return token === 'true' ? 1 : 0;
+    },
+    nextChar: function Type1_nextChar() {
+      return this.currentChar = this.stream.getByte();
+    },
+    getToken: function Type1Parser_getToken() {
+      var comment = false;
+      var ch = this.currentChar;
+
+      while (true) {
+        if (ch === -1) {
+          return null;
+        }
+
+        if (comment) {
+          if (ch === 0x0A || ch === 0x0D) {
+            comment = false;
+          }
+        } else if (ch === 0x25) {
+          comment = true;
+        } else if (!(0, _util.isSpace)(ch)) {
+          break;
+        }
+
+        ch = this.nextChar();
+      }
+
+      if (isSpecial(ch)) {
+        this.nextChar();
+        return String.fromCharCode(ch);
+      }
+
+      var token = '';
+
+      do {
+        token += String.fromCharCode(ch);
+        ch = this.nextChar();
+      } while (ch >= 0 && !(0, _util.isSpace)(ch) && !isSpecial(ch));
+
+      return token;
+    },
+    readCharStrings: function Type1Parser_readCharStrings(bytes, lenIV) {
+      if (lenIV === -1) {
+        return bytes;
+      }
+
+      return decrypt(bytes, CHAR_STRS_ENCRYPT_KEY, lenIV);
+    },
+    extractFontProgram: function Type1Parser_extractFontProgram() {
+      var stream = this.stream;
+      var subrs = [],
+          charstrings = [];
+      var privateData = Object.create(null);
+      privateData['lenIV'] = 4;
+      var program = {
+        subrs: [],
+        charstrings: [],
+        properties: {
+          'privateData': privateData
+        }
+      };
+      var token, length, data, lenIV, encoded;
+
+      while ((token = this.getToken()) !== null) {
+        if (token !== '/') {
+          continue;
+        }
+
+        token = this.getToken();
+
+        switch (token) {
+          case 'CharStrings':
+            this.getToken();
+            this.getToken();
+            this.getToken();
+            this.getToken();
+
+            while (true) {
+              token = this.getToken();
+
+              if (token === null || token === 'end') {
+                break;
+              }
+
+              if (token !== '/') {
+                continue;
+              }
+
+              var glyph = this.getToken();
+              length = this.readInt();
+              this.getToken();
+              data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
+              lenIV = program.properties.privateData['lenIV'];
+              encoded = this.readCharStrings(data, lenIV);
+              this.nextChar();
+              token = this.getToken();
+
+              if (token === 'noaccess') {
+                this.getToken();
+              }
+
+              charstrings.push({
+                glyph: glyph,
+                encoded: encoded
+              });
+            }
+
+            break;
+
+          case 'Subrs':
+            this.readInt();
+            this.getToken();
+
+            while (this.getToken() === 'dup') {
+              var index = this.readInt();
+              length = this.readInt();
+              this.getToken();
+              data = length > 0 ? stream.getBytes(length) : new Uint8Array(0);
+              lenIV = program.properties.privateData['lenIV'];
+              encoded = this.readCharStrings(data, lenIV);
+              this.nextChar();
+              token = this.getToken();
+
+              if (token === 'noaccess') {
+                this.getToken();
+              }
+
+              subrs[index] = encoded;
+            }
+
+            break;
+
+          case 'BlueValues':
+          case 'OtherBlues':
+          case 'FamilyBlues':
+          case 'FamilyOtherBlues':
+            var blueArray = this.readNumberArray();
+
+            if (blueArray.length > 0 && blueArray.length % 2 === 0 && HINTING_ENABLED) {
+              program.properties.privateData[token] = blueArray;
+            }
+
+            break;
+
+          case 'StemSnapH':
+          case 'StemSnapV':
+            program.properties.privateData[token] = this.readNumberArray();
+            break;
+
+          case 'StdHW':
+          case 'StdVW':
+            program.properties.privateData[token] = this.readNumberArray()[0];
+            break;
+
+          case 'BlueShift':
+          case 'lenIV':
+          case 'BlueFuzz':
+          case 'BlueScale':
+          case 'LanguageGroup':
+          case 'ExpansionFactor':
+            program.properties.privateData[token] = this.readNumber();
+            break;
+
+          case 'ForceBold':
+            program.properties.privateData[token] = this.readBoolean();
+            break;
+        }
+      }
+
+      for (var i = 0; i < charstrings.length; i++) {
+        glyph = charstrings[i].glyph;
+        encoded = charstrings[i].encoded;
+        var charString = new Type1CharString();
+        var error = charString.convert(encoded, subrs, this.seacAnalysisEnabled);
+        var output = charString.output;
+
+        if (error) {
+          output = [14];
+        }
+
+        program.charstrings.push({
+          glyphName: glyph,
+          charstring: output,
+          width: charString.width,
+          lsb: charString.lsb,
+          seac: charString.seac
+        });
+      }
+
+      return program;
+    },
+    extractFontHeader: function Type1Parser_extractFontHeader(properties) {
+      var token;
+
+      while ((token = this.getToken()) !== null) {
+        if (token !== '/') {
+          continue;
+        }
+
+        token = this.getToken();
+
+        switch (token) {
+          case 'FontMatrix':
+            var matrix = this.readNumberArray();
+            properties.fontMatrix = matrix;
+            break;
+
+          case 'Encoding':
+            var encodingArg = this.getToken();
+            var encoding;
+
+            if (!/^\d+$/.test(encodingArg)) {
+              encoding = (0, _encodings.getEncoding)(encodingArg);
+            } else {
+              encoding = [];
+              var size = parseInt(encodingArg, 10) | 0;
+              this.getToken();
+
+              for (var j = 0; j < size; j++) {
+                token = this.getToken();
+
+                while (token !== 'dup' && token !== 'def') {
+                  token = this.getToken();
+
+                  if (token === null) {
+                    return;
+                  }
+                }
+
+                if (token === 'def') {
+                  break;
+                }
+
+                var index = this.readInt();
+                this.getToken();
+                var glyph = this.getToken();
+                encoding[index] = glyph;
+                this.getToken();
+              }
+            }
+
+            properties.builtInEncoding = encoding;
+            break;
+
+          case 'FontBBox':
+            var fontBBox = this.readNumberArray();
+            properties.ascent = Math.max(fontBBox[3], fontBBox[1]);
+            properties.descent = Math.min(fontBBox[1], fontBBox[3]);
+            properties.ascentScaled = true;
+            break;
+        }
+      }
+    }
+  };
+  return Type1Parser;
+}();
+
+exports.Type1Parser = Type1Parser;
+
+/***/ }),
+/* 183 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getTilingPatternIR = getTilingPatternIR;
+exports.Pattern = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _colorspace = __w_pdfjs_require__(169);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var ShadingType = {
+  FUNCTION_BASED: 1,
+  AXIAL: 2,
+  RADIAL: 3,
+  FREE_FORM_MESH: 4,
+  LATTICE_FORM_MESH: 5,
+  COONS_PATCH_MESH: 6,
+  TENSOR_PATCH_MESH: 7
+};
+
+var Pattern = function PatternClosure() {
+  function Pattern() {
+    (0, _util.unreachable)('should not call Pattern constructor');
+  }
+
+  Pattern.prototype = {
+    getPattern: function Pattern_getPattern(ctx) {
+      (0, _util.unreachable)("Should not call Pattern.getStyle: ".concat(ctx));
+    }
+  };
+
+  Pattern.parseShading = function (shading, matrix, xref, res, handler, pdfFunctionFactory) {
+    var dict = (0, _primitives.isStream)(shading) ? shading.dict : shading;
+    var type = dict.get('ShadingType');
+
+    try {
+      switch (type) {
+        case ShadingType.AXIAL:
+        case ShadingType.RADIAL:
+          return new Shadings.RadialAxial(dict, matrix, xref, res, pdfFunctionFactory);
+
+        case ShadingType.FREE_FORM_MESH:
+        case ShadingType.LATTICE_FORM_MESH:
+        case ShadingType.COONS_PATCH_MESH:
+        case ShadingType.TENSOR_PATCH_MESH:
+          return new Shadings.Mesh(shading, matrix, xref, res, pdfFunctionFactory);
+
+        default:
+          throw new _util.FormatError('Unsupported ShadingType: ' + type);
+      }
+    } catch (ex) {
+      if (ex instanceof _core_utils.MissingDataException) {
+        throw ex;
+      }
+
+      handler.send('UnsupportedFeature', {
+        featureId: _util.UNSUPPORTED_FEATURES.shadingPattern
+      });
+      (0, _util.warn)(ex);
+      return new Shadings.Dummy();
+    }
+  };
+
+  return Pattern;
+}();
+
+exports.Pattern = Pattern;
+var Shadings = {};
+Shadings.SMALL_NUMBER = 1e-6;
+
+Shadings.RadialAxial = function RadialAxialClosure() {
+  function RadialAxial(dict, matrix, xref, res, pdfFunctionFactory) {
+    this.matrix = matrix;
+    this.coordsArr = dict.getArray('Coords');
+    this.shadingType = dict.get('ShadingType');
+    this.type = 'Pattern';
+    var cs = dict.get('ColorSpace', 'CS');
+    cs = _colorspace.ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
+    this.cs = cs;
+    var t0 = 0.0,
+        t1 = 1.0;
+
+    if (dict.has('Domain')) {
+      var domainArr = dict.getArray('Domain');
+      t0 = domainArr[0];
+      t1 = domainArr[1];
+    }
+
+    var extendStart = false,
+        extendEnd = false;
+
+    if (dict.has('Extend')) {
+      var extendArr = dict.getArray('Extend');
+      extendStart = extendArr[0];
+      extendEnd = extendArr[1];
+    }
+
+    if (this.shadingType === ShadingType.RADIAL && (!extendStart || !extendEnd)) {
+      var x1 = this.coordsArr[0];
+      var y1 = this.coordsArr[1];
+      var r1 = this.coordsArr[2];
+      var x2 = this.coordsArr[3];
+      var y2 = this.coordsArr[4];
+      var r2 = this.coordsArr[5];
+      var distance = Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
+
+      if (r1 <= r2 + distance && r2 <= r1 + distance) {
+        (0, _util.warn)('Unsupported radial gradient.');
+      }
+    }
+
+    this.extendStart = extendStart;
+    this.extendEnd = extendEnd;
+    var fnObj = dict.get('Function');
+    var fn = pdfFunctionFactory.createFromArray(fnObj);
+    var diff = t1 - t0;
+    var step = diff / 10;
+    var colorStops = this.colorStops = [];
+
+    if (t0 >= t1 || step <= 0) {
+      (0, _util.info)('Bad shading domain.');
+      return;
+    }
+
+    var color = new Float32Array(cs.numComps),
+        ratio = new Float32Array(1);
+    var rgbColor;
+
+    for (var i = t0; i <= t1; i += step) {
+      ratio[0] = i;
+      fn(ratio, 0, color, 0);
+      rgbColor = cs.getRgb(color, 0);
+
+      var cssColor = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
+
+      colorStops.push([(i - t0) / diff, cssColor]);
+    }
+
+    var background = 'transparent';
+
+    if (dict.has('Background')) {
+      rgbColor = cs.getRgb(dict.get('Background'), 0);
+      background = _util.Util.makeCssRgb(rgbColor[0], rgbColor[1], rgbColor[2]);
+    }
+
+    if (!extendStart) {
+      colorStops.unshift([0, background]);
+      colorStops[1][0] += Shadings.SMALL_NUMBER;
+    }
+
+    if (!extendEnd) {
+      colorStops[colorStops.length - 1][0] -= Shadings.SMALL_NUMBER;
+      colorStops.push([1, background]);
+    }
+
+    this.colorStops = colorStops;
+  }
+
+  RadialAxial.prototype = {
+    getIR: function RadialAxial_getIR() {
+      var coordsArr = this.coordsArr;
+      var shadingType = this.shadingType;
+      var type, p0, p1, r0, r1;
+
+      if (shadingType === ShadingType.AXIAL) {
+        p0 = [coordsArr[0], coordsArr[1]];
+        p1 = [coordsArr[2], coordsArr[3]];
+        r0 = null;
+        r1 = null;
+        type = 'axial';
+      } else if (shadingType === ShadingType.RADIAL) {
+        p0 = [coordsArr[0], coordsArr[1]];
+        p1 = [coordsArr[3], coordsArr[4]];
+        r0 = coordsArr[2];
+        r1 = coordsArr[5];
+        type = 'radial';
+      } else {
+        (0, _util.unreachable)("getPattern type unknown: ".concat(shadingType));
+      }
+
+      var matrix = this.matrix;
+
+      if (matrix) {
+        p0 = _util.Util.applyTransform(p0, matrix);
+        p1 = _util.Util.applyTransform(p1, matrix);
+
+        if (shadingType === ShadingType.RADIAL) {
+          var scale = _util.Util.singularValueDecompose2dScale(matrix);
+
+          r0 *= scale[0];
+          r1 *= scale[1];
+        }
+      }
+
+      return ['RadialAxial', type, this.colorStops, p0, p1, r0, r1];
+    }
+  };
+  return RadialAxial;
+}();
+
+Shadings.Mesh = function MeshClosure() {
+  function MeshStreamReader(stream, context) {
+    this.stream = stream;
+    this.context = context;
+    this.buffer = 0;
+    this.bufferLength = 0;
+    var numComps = context.numComps;
+    this.tmpCompsBuf = new Float32Array(numComps);
+    var csNumComps = context.colorSpace.numComps;
+    this.tmpCsCompsBuf = context.colorFn ? new Float32Array(csNumComps) : this.tmpCompsBuf;
+  }
+
+  MeshStreamReader.prototype = {
+    get hasData() {
+      if (this.stream.end) {
+        return this.stream.pos < this.stream.end;
+      }
+
+      if (this.bufferLength > 0) {
+        return true;
+      }
+
+      var nextByte = this.stream.getByte();
+
+      if (nextByte < 0) {
+        return false;
+      }
+
+      this.buffer = nextByte;
+      this.bufferLength = 8;
+      return true;
+    },
+
+    readBits: function MeshStreamReader_readBits(n) {
+      var buffer = this.buffer;
+      var bufferLength = this.bufferLength;
+
+      if (n === 32) {
+        if (bufferLength === 0) {
+          return (this.stream.getByte() << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte()) >>> 0;
+        }
+
+        buffer = buffer << 24 | this.stream.getByte() << 16 | this.stream.getByte() << 8 | this.stream.getByte();
+        var nextByte = this.stream.getByte();
+        this.buffer = nextByte & (1 << bufferLength) - 1;
+        return (buffer << 8 - bufferLength | (nextByte & 0xFF) >> bufferLength) >>> 0;
+      }
+
+      if (n === 8 && bufferLength === 0) {
+        return this.stream.getByte();
+      }
+
+      while (bufferLength < n) {
+        buffer = buffer << 8 | this.stream.getByte();
+        bufferLength += 8;
+      }
+
+      bufferLength -= n;
+      this.bufferLength = bufferLength;
+      this.buffer = buffer & (1 << bufferLength) - 1;
+      return buffer >> bufferLength;
+    },
+    align: function MeshStreamReader_align() {
+      this.buffer = 0;
+      this.bufferLength = 0;
+    },
+    readFlag: function MeshStreamReader_readFlag() {
+      return this.readBits(this.context.bitsPerFlag);
+    },
+    readCoordinate: function MeshStreamReader_readCoordinate() {
+      var bitsPerCoordinate = this.context.bitsPerCoordinate;
+      var xi = this.readBits(bitsPerCoordinate);
+      var yi = this.readBits(bitsPerCoordinate);
+      var decode = this.context.decode;
+      var scale = bitsPerCoordinate < 32 ? 1 / ((1 << bitsPerCoordinate) - 1) : 2.3283064365386963e-10;
+      return [xi * scale * (decode[1] - decode[0]) + decode[0], yi * scale * (decode[3] - decode[2]) + decode[2]];
+    },
+    readComponents: function MeshStreamReader_readComponents() {
+      var numComps = this.context.numComps;
+      var bitsPerComponent = this.context.bitsPerComponent;
+      var scale = bitsPerComponent < 32 ? 1 / ((1 << bitsPerComponent) - 1) : 2.3283064365386963e-10;
+      var decode = this.context.decode;
+      var components = this.tmpCompsBuf;
+
+      for (var i = 0, j = 4; i < numComps; i++, j += 2) {
+        var ci = this.readBits(bitsPerComponent);
+        components[i] = ci * scale * (decode[j + 1] - decode[j]) + decode[j];
+      }
+
+      var color = this.tmpCsCompsBuf;
+
+      if (this.context.colorFn) {
+        this.context.colorFn(components, 0, color, 0);
+      }
+
+      return this.context.colorSpace.getRgb(color, 0);
+    }
+  };
+
+  function decodeType4Shading(mesh, reader) {
+    var coords = mesh.coords;
+    var colors = mesh.colors;
+    var operators = [];
+    var ps = [];
+    var verticesLeft = 0;
+
+    while (reader.hasData) {
+      var f = reader.readFlag();
+      var coord = reader.readCoordinate();
+      var color = reader.readComponents();
+
+      if (verticesLeft === 0) {
+        if (!(0 <= f && f <= 2)) {
+          throw new _util.FormatError('Unknown type4 flag');
+        }
+
+        switch (f) {
+          case 0:
+            verticesLeft = 3;
+            break;
+
+          case 1:
+            ps.push(ps[ps.length - 2], ps[ps.length - 1]);
+            verticesLeft = 1;
+            break;
+
+          case 2:
+            ps.push(ps[ps.length - 3], ps[ps.length - 1]);
+            verticesLeft = 1;
+            break;
+        }
+
+        operators.push(f);
+      }
+
+      ps.push(coords.length);
+      coords.push(coord);
+      colors.push(color);
+      verticesLeft--;
+      reader.align();
+    }
+
+    mesh.figures.push({
+      type: 'triangles',
+      coords: new Int32Array(ps),
+      colors: new Int32Array(ps)
+    });
+  }
+
+  function decodeType5Shading(mesh, reader, verticesPerRow) {
+    var coords = mesh.coords;
+    var colors = mesh.colors;
+    var ps = [];
+
+    while (reader.hasData) {
+      var coord = reader.readCoordinate();
+      var color = reader.readComponents();
+      ps.push(coords.length);
+      coords.push(coord);
+      colors.push(color);
+    }
+
+    mesh.figures.push({
+      type: 'lattice',
+      coords: new Int32Array(ps),
+      colors: new Int32Array(ps),
+      verticesPerRow: verticesPerRow
+    });
+  }
+
+  var MIN_SPLIT_PATCH_CHUNKS_AMOUNT = 3;
+  var MAX_SPLIT_PATCH_CHUNKS_AMOUNT = 20;
+  var TRIANGLE_DENSITY = 20;
+
+  var getB = function getBClosure() {
+    function buildB(count) {
+      var lut = [];
+
+      for (var i = 0; i <= count; i++) {
+        var t = i / count,
+            t_ = 1 - t;
+        lut.push(new Float32Array([t_ * t_ * t_, 3 * t * t_ * t_, 3 * t * t * t_, t * t * t]));
+      }
+
+      return lut;
+    }
+
+    var cache = [];
+    return function getB(count) {
+      if (!cache[count]) {
+        cache[count] = buildB(count);
+      }
+
+      return cache[count];
+    };
+  }();
+
+  function buildFigureFromPatch(mesh, index) {
+    var figure = mesh.figures[index];
+    (0, _util.assert)(figure.type === 'patch', 'Unexpected patch mesh figure');
+    var coords = mesh.coords,
+        colors = mesh.colors;
+    var pi = figure.coords;
+    var ci = figure.colors;
+    var figureMinX = Math.min(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+    var figureMinY = Math.min(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+    var figureMaxX = Math.max(coords[pi[0]][0], coords[pi[3]][0], coords[pi[12]][0], coords[pi[15]][0]);
+    var figureMaxY = Math.max(coords[pi[0]][1], coords[pi[3]][1], coords[pi[12]][1], coords[pi[15]][1]);
+    var splitXBy = Math.ceil((figureMaxX - figureMinX) * TRIANGLE_DENSITY / (mesh.bounds[2] - mesh.bounds[0]));
+    splitXBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitXBy));
+    var splitYBy = Math.ceil((figureMaxY - figureMinY) * TRIANGLE_DENSITY / (mesh.bounds[3] - mesh.bounds[1]));
+    splitYBy = Math.max(MIN_SPLIT_PATCH_CHUNKS_AMOUNT, Math.min(MAX_SPLIT_PATCH_CHUNKS_AMOUNT, splitYBy));
+    var verticesPerRow = splitXBy + 1;
+    var figureCoords = new Int32Array((splitYBy + 1) * verticesPerRow);
+    var figureColors = new Int32Array((splitYBy + 1) * verticesPerRow);
+    var k = 0;
+    var cl = new Uint8Array(3),
+        cr = new Uint8Array(3);
+    var c0 = colors[ci[0]],
+        c1 = colors[ci[1]],
+        c2 = colors[ci[2]],
+        c3 = colors[ci[3]];
+    var bRow = getB(splitYBy),
+        bCol = getB(splitXBy);
+
+    for (var row = 0; row <= splitYBy; row++) {
+      cl[0] = (c0[0] * (splitYBy - row) + c2[0] * row) / splitYBy | 0;
+      cl[1] = (c0[1] * (splitYBy - row) + c2[1] * row) / splitYBy | 0;
+      cl[2] = (c0[2] * (splitYBy - row) + c2[2] * row) / splitYBy | 0;
+      cr[0] = (c1[0] * (splitYBy - row) + c3[0] * row) / splitYBy | 0;
+      cr[1] = (c1[1] * (splitYBy - row) + c3[1] * row) / splitYBy | 0;
+      cr[2] = (c1[2] * (splitYBy - row) + c3[2] * row) / splitYBy | 0;
+
+      for (var col = 0; col <= splitXBy; col++, k++) {
+        if ((row === 0 || row === splitYBy) && (col === 0 || col === splitXBy)) {
+          continue;
+        }
+
+        var x = 0,
+            y = 0;
+        var q = 0;
+
+        for (var i = 0; i <= 3; i++) {
+          for (var j = 0; j <= 3; j++, q++) {
+            var m = bRow[row][i] * bCol[col][j];
+            x += coords[pi[q]][0] * m;
+            y += coords[pi[q]][1] * m;
+          }
+        }
+
+        figureCoords[k] = coords.length;
+        coords.push([x, y]);
+        figureColors[k] = colors.length;
+        var newColor = new Uint8Array(3);
+        newColor[0] = (cl[0] * (splitXBy - col) + cr[0] * col) / splitXBy | 0;
+        newColor[1] = (cl[1] * (splitXBy - col) + cr[1] * col) / splitXBy | 0;
+        newColor[2] = (cl[2] * (splitXBy - col) + cr[2] * col) / splitXBy | 0;
+        colors.push(newColor);
+      }
+    }
+
+    figureCoords[0] = pi[0];
+    figureColors[0] = ci[0];
+    figureCoords[splitXBy] = pi[3];
+    figureColors[splitXBy] = ci[1];
+    figureCoords[verticesPerRow * splitYBy] = pi[12];
+    figureColors[verticesPerRow * splitYBy] = ci[2];
+    figureCoords[verticesPerRow * splitYBy + splitXBy] = pi[15];
+    figureColors[verticesPerRow * splitYBy + splitXBy] = ci[3];
+    mesh.figures[index] = {
+      type: 'lattice',
+      coords: figureCoords,
+      colors: figureColors,
+      verticesPerRow: verticesPerRow
+    };
+  }
+
+  function decodeType6Shading(mesh, reader) {
+    var coords = mesh.coords;
+    var colors = mesh.colors;
+    var ps = new Int32Array(16);
+    var cs = new Int32Array(4);
+
+    while (reader.hasData) {
+      var f = reader.readFlag();
+
+      if (!(0 <= f && f <= 3)) {
+        throw new _util.FormatError('Unknown type6 flag');
+      }
+
+      var i, ii;
+      var pi = coords.length;
+
+      for (i = 0, ii = f !== 0 ? 8 : 12; i < ii; i++) {
+        coords.push(reader.readCoordinate());
+      }
+
+      var ci = colors.length;
+
+      for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+        colors.push(reader.readComponents());
+      }
+
+      var tmp1, tmp2, tmp3, tmp4;
+
+      switch (f) {
+        case 0:
+          ps[12] = pi + 3;
+          ps[13] = pi + 4;
+          ps[14] = pi + 5;
+          ps[15] = pi + 6;
+          ps[8] = pi + 2;
+          ps[11] = pi + 7;
+          ps[4] = pi + 1;
+          ps[7] = pi + 8;
+          ps[0] = pi;
+          ps[1] = pi + 11;
+          ps[2] = pi + 10;
+          ps[3] = pi + 9;
+          cs[2] = ci + 1;
+          cs[3] = ci + 2;
+          cs[0] = ci;
+          cs[1] = ci + 3;
+          break;
+
+        case 1:
+          tmp1 = ps[12];
+          tmp2 = ps[13];
+          tmp3 = ps[14];
+          tmp4 = ps[15];
+          ps[12] = tmp4;
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = tmp3;
+          ps[11] = pi + 3;
+          ps[4] = tmp2;
+          ps[7] = pi + 4;
+          ps[0] = tmp1;
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          tmp1 = cs[2];
+          tmp2 = cs[3];
+          cs[2] = tmp2;
+          cs[3] = ci;
+          cs[0] = tmp1;
+          cs[1] = ci + 1;
+          break;
+
+        case 2:
+          tmp1 = ps[15];
+          tmp2 = ps[11];
+          ps[12] = ps[3];
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = ps[7];
+          ps[11] = pi + 3;
+          ps[4] = tmp2;
+          ps[7] = pi + 4;
+          ps[0] = tmp1;
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          tmp1 = cs[3];
+          cs[2] = cs[1];
+          cs[3] = ci;
+          cs[0] = tmp1;
+          cs[1] = ci + 1;
+          break;
+
+        case 3:
+          ps[12] = ps[0];
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = ps[1];
+          ps[11] = pi + 3;
+          ps[4] = ps[2];
+          ps[7] = pi + 4;
+          ps[0] = ps[3];
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          cs[2] = cs[0];
+          cs[3] = ci;
+          cs[0] = cs[1];
+          cs[1] = ci + 1;
+          break;
+      }
+
+      ps[5] = coords.length;
+      coords.push([(-4 * coords[ps[0]][0] - coords[ps[15]][0] + 6 * (coords[ps[4]][0] + coords[ps[1]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[13]][0] + coords[ps[7]][0])) / 9, (-4 * coords[ps[0]][1] - coords[ps[15]][1] + 6 * (coords[ps[4]][1] + coords[ps[1]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[13]][1] + coords[ps[7]][1])) / 9]);
+      ps[6] = coords.length;
+      coords.push([(-4 * coords[ps[3]][0] - coords[ps[12]][0] + 6 * (coords[ps[2]][0] + coords[ps[7]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[4]][0] + coords[ps[14]][0])) / 9, (-4 * coords[ps[3]][1] - coords[ps[12]][1] + 6 * (coords[ps[2]][1] + coords[ps[7]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[4]][1] + coords[ps[14]][1])) / 9]);
+      ps[9] = coords.length;
+      coords.push([(-4 * coords[ps[12]][0] - coords[ps[3]][0] + 6 * (coords[ps[8]][0] + coords[ps[13]][0]) - 2 * (coords[ps[0]][0] + coords[ps[15]][0]) + 3 * (coords[ps[11]][0] + coords[ps[1]][0])) / 9, (-4 * coords[ps[12]][1] - coords[ps[3]][1] + 6 * (coords[ps[8]][1] + coords[ps[13]][1]) - 2 * (coords[ps[0]][1] + coords[ps[15]][1]) + 3 * (coords[ps[11]][1] + coords[ps[1]][1])) / 9]);
+      ps[10] = coords.length;
+      coords.push([(-4 * coords[ps[15]][0] - coords[ps[0]][0] + 6 * (coords[ps[11]][0] + coords[ps[14]][0]) - 2 * (coords[ps[12]][0] + coords[ps[3]][0]) + 3 * (coords[ps[2]][0] + coords[ps[8]][0])) / 9, (-4 * coords[ps[15]][1] - coords[ps[0]][1] + 6 * (coords[ps[11]][1] + coords[ps[14]][1]) - 2 * (coords[ps[12]][1] + coords[ps[3]][1]) + 3 * (coords[ps[2]][1] + coords[ps[8]][1])) / 9]);
+      mesh.figures.push({
+        type: 'patch',
+        coords: new Int32Array(ps),
+        colors: new Int32Array(cs)
+      });
+    }
+  }
+
+  function decodeType7Shading(mesh, reader) {
+    var coords = mesh.coords;
+    var colors = mesh.colors;
+    var ps = new Int32Array(16);
+    var cs = new Int32Array(4);
+
+    while (reader.hasData) {
+      var f = reader.readFlag();
+
+      if (!(0 <= f && f <= 3)) {
+        throw new _util.FormatError('Unknown type7 flag');
+      }
+
+      var i, ii;
+      var pi = coords.length;
+
+      for (i = 0, ii = f !== 0 ? 12 : 16; i < ii; i++) {
+        coords.push(reader.readCoordinate());
+      }
+
+      var ci = colors.length;
+
+      for (i = 0, ii = f !== 0 ? 2 : 4; i < ii; i++) {
+        colors.push(reader.readComponents());
+      }
+
+      var tmp1, tmp2, tmp3, tmp4;
+
+      switch (f) {
+        case 0:
+          ps[12] = pi + 3;
+          ps[13] = pi + 4;
+          ps[14] = pi + 5;
+          ps[15] = pi + 6;
+          ps[8] = pi + 2;
+          ps[9] = pi + 13;
+          ps[10] = pi + 14;
+          ps[11] = pi + 7;
+          ps[4] = pi + 1;
+          ps[5] = pi + 12;
+          ps[6] = pi + 15;
+          ps[7] = pi + 8;
+          ps[0] = pi;
+          ps[1] = pi + 11;
+          ps[2] = pi + 10;
+          ps[3] = pi + 9;
+          cs[2] = ci + 1;
+          cs[3] = ci + 2;
+          cs[0] = ci;
+          cs[1] = ci + 3;
+          break;
+
+        case 1:
+          tmp1 = ps[12];
+          tmp2 = ps[13];
+          tmp3 = ps[14];
+          tmp4 = ps[15];
+          ps[12] = tmp4;
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = tmp3;
+          ps[9] = pi + 9;
+          ps[10] = pi + 10;
+          ps[11] = pi + 3;
+          ps[4] = tmp2;
+          ps[5] = pi + 8;
+          ps[6] = pi + 11;
+          ps[7] = pi + 4;
+          ps[0] = tmp1;
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          tmp1 = cs[2];
+          tmp2 = cs[3];
+          cs[2] = tmp2;
+          cs[3] = ci;
+          cs[0] = tmp1;
+          cs[1] = ci + 1;
+          break;
+
+        case 2:
+          tmp1 = ps[15];
+          tmp2 = ps[11];
+          ps[12] = ps[3];
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = ps[7];
+          ps[9] = pi + 9;
+          ps[10] = pi + 10;
+          ps[11] = pi + 3;
+          ps[4] = tmp2;
+          ps[5] = pi + 8;
+          ps[6] = pi + 11;
+          ps[7] = pi + 4;
+          ps[0] = tmp1;
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          tmp1 = cs[3];
+          cs[2] = cs[1];
+          cs[3] = ci;
+          cs[0] = tmp1;
+          cs[1] = ci + 1;
+          break;
+
+        case 3:
+          ps[12] = ps[0];
+          ps[13] = pi + 0;
+          ps[14] = pi + 1;
+          ps[15] = pi + 2;
+          ps[8] = ps[1];
+          ps[9] = pi + 9;
+          ps[10] = pi + 10;
+          ps[11] = pi + 3;
+          ps[4] = ps[2];
+          ps[5] = pi + 8;
+          ps[6] = pi + 11;
+          ps[7] = pi + 4;
+          ps[0] = ps[3];
+          ps[1] = pi + 7;
+          ps[2] = pi + 6;
+          ps[3] = pi + 5;
+          cs[2] = cs[0];
+          cs[3] = ci;
+          cs[0] = cs[1];
+          cs[1] = ci + 1;
+          break;
+      }
+
+      mesh.figures.push({
+        type: 'patch',
+        coords: new Int32Array(ps),
+        colors: new Int32Array(cs)
+      });
+    }
+  }
+
+  function updateBounds(mesh) {
+    var minX = mesh.coords[0][0],
+        minY = mesh.coords[0][1],
+        maxX = minX,
+        maxY = minY;
+
+    for (var i = 1, ii = mesh.coords.length; i < ii; i++) {
+      var x = mesh.coords[i][0],
+          y = mesh.coords[i][1];
+      minX = minX > x ? x : minX;
+      minY = minY > y ? y : minY;
+      maxX = maxX < x ? x : maxX;
+      maxY = maxY < y ? y : maxY;
+    }
+
+    mesh.bounds = [minX, minY, maxX, maxY];
+  }
+
+  function packData(mesh) {
+    var i, ii, j, jj;
+    var coords = mesh.coords;
+    var coordsPacked = new Float32Array(coords.length * 2);
+
+    for (i = 0, j = 0, ii = coords.length; i < ii; i++) {
+      var xy = coords[i];
+      coordsPacked[j++] = xy[0];
+      coordsPacked[j++] = xy[1];
+    }
+
+    mesh.coords = coordsPacked;
+    var colors = mesh.colors;
+    var colorsPacked = new Uint8Array(colors.length * 3);
+
+    for (i = 0, j = 0, ii = colors.length; i < ii; i++) {
+      var c = colors[i];
+      colorsPacked[j++] = c[0];
+      colorsPacked[j++] = c[1];
+      colorsPacked[j++] = c[2];
+    }
+
+    mesh.colors = colorsPacked;
+    var figures = mesh.figures;
+
+    for (i = 0, ii = figures.length; i < ii; i++) {
+      var figure = figures[i],
+          ps = figure.coords,
+          cs = figure.colors;
+
+      for (j = 0, jj = ps.length; j < jj; j++) {
+        ps[j] *= 2;
+        cs[j] *= 3;
+      }
+    }
+  }
+
+  function Mesh(stream, matrix, xref, res, pdfFunctionFactory) {
+    if (!(0, _primitives.isStream)(stream)) {
+      throw new _util.FormatError('Mesh data is not a stream');
+    }
+
+    var dict = stream.dict;
+    this.matrix = matrix;
+    this.shadingType = dict.get('ShadingType');
+    this.type = 'Pattern';
+    this.bbox = dict.getArray('BBox');
+    var cs = dict.get('ColorSpace', 'CS');
+    cs = _colorspace.ColorSpace.parse(cs, xref, res, pdfFunctionFactory);
+    this.cs = cs;
+    this.background = dict.has('Background') ? cs.getRgb(dict.get('Background'), 0) : null;
+    var fnObj = dict.get('Function');
+    var fn = fnObj ? pdfFunctionFactory.createFromArray(fnObj) : null;
+    this.coords = [];
+    this.colors = [];
+    this.figures = [];
+    var decodeContext = {
+      bitsPerCoordinate: dict.get('BitsPerCoordinate'),
+      bitsPerComponent: dict.get('BitsPerComponent'),
+      bitsPerFlag: dict.get('BitsPerFlag'),
+      decode: dict.getArray('Decode'),
+      colorFn: fn,
+      colorSpace: cs,
+      numComps: fn ? 1 : cs.numComps
+    };
+    var reader = new MeshStreamReader(stream, decodeContext);
+    var patchMesh = false;
+
+    switch (this.shadingType) {
+      case ShadingType.FREE_FORM_MESH:
+        decodeType4Shading(this, reader);
+        break;
+
+      case ShadingType.LATTICE_FORM_MESH:
+        var verticesPerRow = dict.get('VerticesPerRow') | 0;
+
+        if (verticesPerRow < 2) {
+          throw new _util.FormatError('Invalid VerticesPerRow');
+        }
+
+        decodeType5Shading(this, reader, verticesPerRow);
+        break;
+
+      case ShadingType.COONS_PATCH_MESH:
+        decodeType6Shading(this, reader);
+        patchMesh = true;
+        break;
+
+      case ShadingType.TENSOR_PATCH_MESH:
+        decodeType7Shading(this, reader);
+        patchMesh = true;
+        break;
+
+      default:
+        (0, _util.unreachable)('Unsupported mesh type.');
+        break;
+    }
+
+    if (patchMesh) {
+      updateBounds(this);
+
+      for (var i = 0, ii = this.figures.length; i < ii; i++) {
+        buildFigureFromPatch(this, i);
+      }
+    }
+
+    updateBounds(this);
+    packData(this);
+  }
+
+  Mesh.prototype = {
+    getIR: function Mesh_getIR() {
+      return ['Mesh', this.shadingType, this.coords, this.colors, this.figures, this.bounds, this.matrix, this.bbox, this.background];
+    }
+  };
+  return Mesh;
+}();
+
+Shadings.Dummy = function DummyClosure() {
+  function Dummy() {
+    this.type = 'Pattern';
+  }
+
+  Dummy.prototype = {
+    getIR: function Dummy_getIR() {
+      return ['Dummy'];
+    }
+  };
+  return Dummy;
+}();
+
+function getTilingPatternIR(operatorList, dict, args) {
+  var matrix = dict.getArray('Matrix');
+
+  var bbox = _util.Util.normalizeRect(dict.getArray('BBox'));
+
+  var xstep = dict.get('XStep');
+  var ystep = dict.get('YStep');
+  var paintType = dict.get('PaintType');
+  var tilingType = dict.get('TilingType');
+
+  if (bbox[2] - bbox[0] === 0 || bbox[3] - bbox[1] === 0) {
+    throw new _util.FormatError("Invalid getTilingPatternIR /BBox array: [".concat(bbox, "]."));
+  }
+
+  return ['TilingPattern', args, operatorList, matrix, bbox, xstep, ystep, paintType, tilingType];
+}
+
+/***/ }),
+/* 184 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.bidi = bidi;
+
+var _util = __w_pdfjs_require__(5);
+
+var baseTypes = ['BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'S', 'B', 'S', 'WS', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'B', 'B', 'S', 'WS', 'ON', 'ON', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'ON', 'ES', 'CS', 'ES', 'CS', 'CS', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'CS', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'ON', 'ON', 'ON', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'B', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'BN', 'CS', 'ON', 'ET', 'ET', 'ET', 'ET', 'ON', 'ON', 'ON', 'ON', 'L', 'ON', 'ON', 'BN', 'ON', 'ON', 'ET', 'ET', 'EN', 'EN', 'ON', 'L', 'ON', 'ON', 'ON', 'EN', 'L', 'ON', 'ON', 'ON', 'ON', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'ON', 'L', 'L', 'L', 'L', 'L', 'L', 'L', 'L'];
+var arabicTypes = ['AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ON', 'ON', 'AL', 'ET', 'ET', 'AL', 'CS', 'AL', 'ON', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', '', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'AN', 'ET', 'AN', 'AN', 'AL', 'AL', 'AL', 'NSM', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AN', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'NSM', 'NSM', 'ON', 'NSM', 'NSM', 'NSM', 'NSM', 'AL', 'AL', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'EN', 'AL', 'AL', 'AL', 'AL', 'AL', 'AL'];
+
+function isOdd(i) {
+  return (i & 1) !== 0;
+}
+
+function isEven(i) {
+  return (i & 1) === 0;
+}
+
+function findUnequal(arr, start, value) {
+  for (var j = start, jj = arr.length; j < jj; ++j) {
+    if (arr[j] !== value) {
+      return j;
+    }
+  }
+
+  return j;
+}
+
+function setValues(arr, start, end, value) {
+  for (var j = start; j < end; ++j) {
+    arr[j] = value;
+  }
+}
+
+function reverseValues(arr, start, end) {
+  for (var i = start, j = end - 1; i < j; ++i, --j) {
+    var temp = arr[i];
+    arr[i] = arr[j];
+    arr[j] = temp;
+  }
+}
+
+function createBidiText(str, isLTR, vertical) {
+  return {
+    str: str,
+    dir: vertical ? 'ttb' : isLTR ? 'ltr' : 'rtl'
+  };
+}
+
+var chars = [];
+var types = [];
+
+function bidi(str, startLevel, vertical) {
+  var isLTR = true;
+  var strLength = str.length;
+
+  if (strLength === 0 || vertical) {
+    return createBidiText(str, isLTR, vertical);
+  }
+
+  chars.length = strLength;
+  types.length = strLength;
+  var numBidi = 0;
+  var i, ii;
+
+  for (i = 0; i < strLength; ++i) {
+    chars[i] = str.charAt(i);
+    var charCode = str.charCodeAt(i);
+    var charType = 'L';
+
+    if (charCode <= 0x00ff) {
+      charType = baseTypes[charCode];
+    } else if (0x0590 <= charCode && charCode <= 0x05f4) {
+      charType = 'R';
+    } else if (0x0600 <= charCode && charCode <= 0x06ff) {
+      charType = arabicTypes[charCode & 0xff];
+
+      if (!charType) {
+        (0, _util.warn)('Bidi: invalid Unicode character ' + charCode.toString(16));
+      }
+    } else if (0x0700 <= charCode && charCode <= 0x08AC) {
+      charType = 'AL';
+    }
+
+    if (charType === 'R' || charType === 'AL' || charType === 'AN') {
+      numBidi++;
+    }
+
+    types[i] = charType;
+  }
+
+  if (numBidi === 0) {
+    isLTR = true;
+    return createBidiText(str, isLTR);
+  }
+
+  if (startLevel === -1) {
+    if (numBidi / strLength < 0.3) {
+      isLTR = true;
+      startLevel = 0;
+    } else {
+      isLTR = false;
+      startLevel = 1;
+    }
+  }
+
+  var levels = [];
+
+  for (i = 0; i < strLength; ++i) {
+    levels[i] = startLevel;
+  }
+
+  var e = isOdd(startLevel) ? 'R' : 'L';
+  var sor = e;
+  var eor = sor;
+  var lastType = sor;
+
+  for (i = 0; i < strLength; ++i) {
+    if (types[i] === 'NSM') {
+      types[i] = lastType;
+    } else {
+      lastType = types[i];
+    }
+  }
+
+  lastType = sor;
+  var t;
+
+  for (i = 0; i < strLength; ++i) {
+    t = types[i];
+
+    if (t === 'EN') {
+      types[i] = lastType === 'AL' ? 'AN' : 'EN';
+    } else if (t === 'R' || t === 'L' || t === 'AL') {
+      lastType = t;
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    t = types[i];
+
+    if (t === 'AL') {
+      types[i] = 'R';
+    }
+  }
+
+  for (i = 1; i < strLength - 1; ++i) {
+    if (types[i] === 'ES' && types[i - 1] === 'EN' && types[i + 1] === 'EN') {
+      types[i] = 'EN';
+    }
+
+    if (types[i] === 'CS' && (types[i - 1] === 'EN' || types[i - 1] === 'AN') && types[i + 1] === types[i - 1]) {
+      types[i] = types[i - 1];
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    if (types[i] === 'EN') {
+      var j;
+
+      for (j = i - 1; j >= 0; --j) {
+        if (types[j] !== 'ET') {
+          break;
+        }
+
+        types[j] = 'EN';
+      }
+
+      for (j = i + 1; j < strLength; ++j) {
+        if (types[j] !== 'ET') {
+          break;
+        }
+
+        types[j] = 'EN';
+      }
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    t = types[i];
+
+    if (t === 'WS' || t === 'ES' || t === 'ET' || t === 'CS') {
+      types[i] = 'ON';
+    }
+  }
+
+  lastType = sor;
+
+  for (i = 0; i < strLength; ++i) {
+    t = types[i];
+
+    if (t === 'EN') {
+      types[i] = lastType === 'L' ? 'L' : 'EN';
+    } else if (t === 'R' || t === 'L') {
+      lastType = t;
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    if (types[i] === 'ON') {
+      var end = findUnequal(types, i + 1, 'ON');
+      var before = sor;
+
+      if (i > 0) {
+        before = types[i - 1];
+      }
+
+      var after = eor;
+
+      if (end + 1 < strLength) {
+        after = types[end + 1];
+      }
+
+      if (before !== 'L') {
+        before = 'R';
+      }
+
+      if (after !== 'L') {
+        after = 'R';
+      }
+
+      if (before === after) {
+        setValues(types, i, end, before);
+      }
+
+      i = end - 1;
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    if (types[i] === 'ON') {
+      types[i] = e;
+    }
+  }
+
+  for (i = 0; i < strLength; ++i) {
+    t = types[i];
+
+    if (isEven(levels[i])) {
+      if (t === 'R') {
+        levels[i] += 1;
+      } else if (t === 'AN' || t === 'EN') {
+        levels[i] += 2;
+      }
+    } else {
+      if (t === 'L' || t === 'AN' || t === 'EN') {
+        levels[i] += 1;
+      }
+    }
+  }
+
+  var highestLevel = -1;
+  var lowestOddLevel = 99;
+  var level;
+
+  for (i = 0, ii = levels.length; i < ii; ++i) {
+    level = levels[i];
+
+    if (highestLevel < level) {
+      highestLevel = level;
+    }
+
+    if (lowestOddLevel > level && isOdd(level)) {
+      lowestOddLevel = level;
+    }
+  }
+
+  for (level = highestLevel; level >= lowestOddLevel; --level) {
+    var start = -1;
+
+    for (i = 0, ii = levels.length; i < ii; ++i) {
+      if (levels[i] < level) {
+        if (start >= 0) {
+          reverseValues(chars, start, i);
+          start = -1;
+        }
+      } else if (start < 0) {
+        start = i;
+      }
+    }
+
+    if (start >= 0) {
+      reverseValues(chars, start, levels.length);
+    }
+  }
+
+  for (i = 0, ii = chars.length; i < ii; ++i) {
+    var ch = chars[i];
+
+    if (ch === '<' || ch === '>') {
+      chars[i] = '';
+    }
+  }
+
+  return createBidiText(chars.join(''), isLTR);
+}
+
+/***/ }),
+/* 185 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.getMetrics = void 0;
+
+var _core_utils = __w_pdfjs_require__(154);
+
+var getMetrics = (0, _core_utils.getLookupTableFactory)(function (t) {
+  t['Courier'] = 600;
+  t['Courier-Bold'] = 600;
+  t['Courier-BoldOblique'] = 600;
+  t['Courier-Oblique'] = 600;
+  t['Helvetica'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 278;
+    t['exclam'] = 278;
+    t['quotedbl'] = 355;
+    t['numbersign'] = 556;
+    t['dollar'] = 556;
+    t['percent'] = 889;
+    t['ampersand'] = 667;
+    t['quoteright'] = 222;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 389;
+    t['plus'] = 584;
+    t['comma'] = 278;
+    t['hyphen'] = 333;
+    t['period'] = 278;
+    t['slash'] = 278;
+    t['zero'] = 556;
+    t['one'] = 556;
+    t['two'] = 556;
+    t['three'] = 556;
+    t['four'] = 556;
+    t['five'] = 556;
+    t['six'] = 556;
+    t['seven'] = 556;
+    t['eight'] = 556;
+    t['nine'] = 556;
+    t['colon'] = 278;
+    t['semicolon'] = 278;
+    t['less'] = 584;
+    t['equal'] = 584;
+    t['greater'] = 584;
+    t['question'] = 556;
+    t['at'] = 1015;
+    t['A'] = 667;
+    t['B'] = 667;
+    t['C'] = 722;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 611;
+    t['G'] = 778;
+    t['H'] = 722;
+    t['I'] = 278;
+    t['J'] = 500;
+    t['K'] = 667;
+    t['L'] = 556;
+    t['M'] = 833;
+    t['N'] = 722;
+    t['O'] = 778;
+    t['P'] = 667;
+    t['Q'] = 778;
+    t['R'] = 722;
+    t['S'] = 667;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 667;
+    t['W'] = 944;
+    t['X'] = 667;
+    t['Y'] = 667;
+    t['Z'] = 611;
+    t['bracketleft'] = 278;
+    t['backslash'] = 278;
+    t['bracketright'] = 278;
+    t['asciicircum'] = 469;
+    t['underscore'] = 556;
+    t['quoteleft'] = 222;
+    t['a'] = 556;
+    t['b'] = 556;
+    t['c'] = 500;
+    t['d'] = 556;
+    t['e'] = 556;
+    t['f'] = 278;
+    t['g'] = 556;
+    t['h'] = 556;
+    t['i'] = 222;
+    t['j'] = 222;
+    t['k'] = 500;
+    t['l'] = 222;
+    t['m'] = 833;
+    t['n'] = 556;
+    t['o'] = 556;
+    t['p'] = 556;
+    t['q'] = 556;
+    t['r'] = 333;
+    t['s'] = 500;
+    t['t'] = 278;
+    t['u'] = 556;
+    t['v'] = 500;
+    t['w'] = 722;
+    t['x'] = 500;
+    t['y'] = 500;
+    t['z'] = 500;
+    t['braceleft'] = 334;
+    t['bar'] = 260;
+    t['braceright'] = 334;
+    t['asciitilde'] = 584;
+    t['exclamdown'] = 333;
+    t['cent'] = 556;
+    t['sterling'] = 556;
+    t['fraction'] = 167;
+    t['yen'] = 556;
+    t['florin'] = 556;
+    t['section'] = 556;
+    t['currency'] = 556;
+    t['quotesingle'] = 191;
+    t['quotedblleft'] = 333;
+    t['guillemotleft'] = 556;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 500;
+    t['fl'] = 500;
+    t['endash'] = 556;
+    t['dagger'] = 556;
+    t['daggerdbl'] = 556;
+    t['periodcentered'] = 278;
+    t['paragraph'] = 537;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 222;
+    t['quotedblbase'] = 333;
+    t['quotedblright'] = 333;
+    t['guillemotright'] = 556;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 611;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 1000;
+    t['ordfeminine'] = 370;
+    t['Lslash'] = 556;
+    t['Oslash'] = 778;
+    t['OE'] = 1000;
+    t['ordmasculine'] = 365;
+    t['ae'] = 889;
+    t['dotlessi'] = 278;
+    t['lslash'] = 222;
+    t['oslash'] = 611;
+    t['oe'] = 944;
+    t['germandbls'] = 611;
+    t['Idieresis'] = 278;
+    t['eacute'] = 556;
+    t['abreve'] = 556;
+    t['uhungarumlaut'] = 556;
+    t['ecaron'] = 556;
+    t['Ydieresis'] = 667;
+    t['divide'] = 584;
+    t['Yacute'] = 667;
+    t['Acircumflex'] = 667;
+    t['aacute'] = 556;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 500;
+    t['scommaaccent'] = 500;
+    t['ecircumflex'] = 556;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 556;
+    t['Uacute'] = 722;
+    t['uogonek'] = 556;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 737;
+    t['Emacron'] = 667;
+    t['ccaron'] = 500;
+    t['aring'] = 556;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 222;
+    t['agrave'] = 556;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 722;
+    t['atilde'] = 556;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 500;
+    t['scedilla'] = 500;
+    t['iacute'] = 278;
+    t['lozenge'] = 471;
+    t['Rcaron'] = 722;
+    t['Gcommaaccent'] = 778;
+    t['ucircumflex'] = 556;
+    t['acircumflex'] = 556;
+    t['Amacron'] = 667;
+    t['rcaron'] = 333;
+    t['ccedilla'] = 500;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 667;
+    t['Omacron'] = 778;
+    t['Racute'] = 722;
+    t['Sacute'] = 667;
+    t['dcaron'] = 643;
+    t['Umacron'] = 722;
+    t['uring'] = 556;
+    t['threesuperior'] = 333;
+    t['Ograve'] = 778;
+    t['Agrave'] = 667;
+    t['Abreve'] = 667;
+    t['multiply'] = 584;
+    t['uacute'] = 556;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 476;
+    t['ydieresis'] = 500;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 556;
+    t['edieresis'] = 556;
+    t['cacute'] = 500;
+    t['nacute'] = 556;
+    t['umacron'] = 556;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 278;
+    t['plusminus'] = 584;
+    t['brokenbar'] = 260;
+    t['registered'] = 737;
+    t['Gbreve'] = 778;
+    t['Idotaccent'] = 278;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 333;
+    t['omacron'] = 556;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 722;
+    t['lcommaaccent'] = 222;
+    t['tcaron'] = 317;
+    t['eogonek'] = 556;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 667;
+    t['Adieresis'] = 667;
+    t['egrave'] = 556;
+    t['zacute'] = 500;
+    t['iogonek'] = 222;
+    t['Oacute'] = 778;
+    t['oacute'] = 556;
+    t['amacron'] = 556;
+    t['sacute'] = 500;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 778;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 556;
+    t['twosuperior'] = 333;
+    t['Odieresis'] = 778;
+    t['mu'] = 556;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 556;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 556;
+    t['threequarters'] = 834;
+    t['Scedilla'] = 667;
+    t['lcaron'] = 299;
+    t['Kcommaaccent'] = 667;
+    t['Lacute'] = 556;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 556;
+    t['Igrave'] = 278;
+    t['Imacron'] = 278;
+    t['Lcaron'] = 556;
+    t['onehalf'] = 834;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 556;
+    t['ntilde'] = 556;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 556;
+    t['gbreve'] = 556;
+    t['onequarter'] = 834;
+    t['Scaron'] = 667;
+    t['Scommaaccent'] = 667;
+    t['Ohungarumlaut'] = 778;
+    t['degree'] = 400;
+    t['ograve'] = 556;
+    t['Ccaron'] = 722;
+    t['ugrave'] = 556;
+    t['radical'] = 453;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 333;
+    t['Ntilde'] = 722;
+    t['otilde'] = 556;
+    t['Rcommaaccent'] = 722;
+    t['Lcommaaccent'] = 556;
+    t['Atilde'] = 667;
+    t['Aogonek'] = 667;
+    t['Aring'] = 667;
+    t['Otilde'] = 778;
+    t['zdotaccent'] = 500;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 278;
+    t['kcommaaccent'] = 500;
+    t['minus'] = 584;
+    t['Icircumflex'] = 278;
+    t['ncaron'] = 556;
+    t['tcommaaccent'] = 278;
+    t['logicalnot'] = 584;
+    t['odieresis'] = 556;
+    t['udieresis'] = 556;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 556;
+    t['eth'] = 556;
+    t['zcaron'] = 500;
+    t['ncommaaccent'] = 556;
+    t['onesuperior'] = 333;
+    t['imacron'] = 278;
+    t['Euro'] = 556;
+  });
+  t['Helvetica-Bold'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 278;
+    t['exclam'] = 333;
+    t['quotedbl'] = 474;
+    t['numbersign'] = 556;
+    t['dollar'] = 556;
+    t['percent'] = 889;
+    t['ampersand'] = 722;
+    t['quoteright'] = 278;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 389;
+    t['plus'] = 584;
+    t['comma'] = 278;
+    t['hyphen'] = 333;
+    t['period'] = 278;
+    t['slash'] = 278;
+    t['zero'] = 556;
+    t['one'] = 556;
+    t['two'] = 556;
+    t['three'] = 556;
+    t['four'] = 556;
+    t['five'] = 556;
+    t['six'] = 556;
+    t['seven'] = 556;
+    t['eight'] = 556;
+    t['nine'] = 556;
+    t['colon'] = 333;
+    t['semicolon'] = 333;
+    t['less'] = 584;
+    t['equal'] = 584;
+    t['greater'] = 584;
+    t['question'] = 611;
+    t['at'] = 975;
+    t['A'] = 722;
+    t['B'] = 722;
+    t['C'] = 722;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 611;
+    t['G'] = 778;
+    t['H'] = 722;
+    t['I'] = 278;
+    t['J'] = 556;
+    t['K'] = 722;
+    t['L'] = 611;
+    t['M'] = 833;
+    t['N'] = 722;
+    t['O'] = 778;
+    t['P'] = 667;
+    t['Q'] = 778;
+    t['R'] = 722;
+    t['S'] = 667;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 667;
+    t['W'] = 944;
+    t['X'] = 667;
+    t['Y'] = 667;
+    t['Z'] = 611;
+    t['bracketleft'] = 333;
+    t['backslash'] = 278;
+    t['bracketright'] = 333;
+    t['asciicircum'] = 584;
+    t['underscore'] = 556;
+    t['quoteleft'] = 278;
+    t['a'] = 556;
+    t['b'] = 611;
+    t['c'] = 556;
+    t['d'] = 611;
+    t['e'] = 556;
+    t['f'] = 333;
+    t['g'] = 611;
+    t['h'] = 611;
+    t['i'] = 278;
+    t['j'] = 278;
+    t['k'] = 556;
+    t['l'] = 278;
+    t['m'] = 889;
+    t['n'] = 611;
+    t['o'] = 611;
+    t['p'] = 611;
+    t['q'] = 611;
+    t['r'] = 389;
+    t['s'] = 556;
+    t['t'] = 333;
+    t['u'] = 611;
+    t['v'] = 556;
+    t['w'] = 778;
+    t['x'] = 556;
+    t['y'] = 556;
+    t['z'] = 500;
+    t['braceleft'] = 389;
+    t['bar'] = 280;
+    t['braceright'] = 389;
+    t['asciitilde'] = 584;
+    t['exclamdown'] = 333;
+    t['cent'] = 556;
+    t['sterling'] = 556;
+    t['fraction'] = 167;
+    t['yen'] = 556;
+    t['florin'] = 556;
+    t['section'] = 556;
+    t['currency'] = 556;
+    t['quotesingle'] = 238;
+    t['quotedblleft'] = 500;
+    t['guillemotleft'] = 556;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 611;
+    t['fl'] = 611;
+    t['endash'] = 556;
+    t['dagger'] = 556;
+    t['daggerdbl'] = 556;
+    t['periodcentered'] = 278;
+    t['paragraph'] = 556;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 278;
+    t['quotedblbase'] = 500;
+    t['quotedblright'] = 500;
+    t['guillemotright'] = 556;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 611;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 1000;
+    t['ordfeminine'] = 370;
+    t['Lslash'] = 611;
+    t['Oslash'] = 778;
+    t['OE'] = 1000;
+    t['ordmasculine'] = 365;
+    t['ae'] = 889;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 611;
+    t['oe'] = 944;
+    t['germandbls'] = 611;
+    t['Idieresis'] = 278;
+    t['eacute'] = 556;
+    t['abreve'] = 556;
+    t['uhungarumlaut'] = 611;
+    t['ecaron'] = 556;
+    t['Ydieresis'] = 667;
+    t['divide'] = 584;
+    t['Yacute'] = 667;
+    t['Acircumflex'] = 722;
+    t['aacute'] = 556;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 556;
+    t['scommaaccent'] = 556;
+    t['ecircumflex'] = 556;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 556;
+    t['Uacute'] = 722;
+    t['uogonek'] = 611;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 737;
+    t['Emacron'] = 667;
+    t['ccaron'] = 556;
+    t['aring'] = 556;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 278;
+    t['agrave'] = 556;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 722;
+    t['atilde'] = 556;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 556;
+    t['scedilla'] = 556;
+    t['iacute'] = 278;
+    t['lozenge'] = 494;
+    t['Rcaron'] = 722;
+    t['Gcommaaccent'] = 778;
+    t['ucircumflex'] = 611;
+    t['acircumflex'] = 556;
+    t['Amacron'] = 722;
+    t['rcaron'] = 389;
+    t['ccedilla'] = 556;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 667;
+    t['Omacron'] = 778;
+    t['Racute'] = 722;
+    t['Sacute'] = 667;
+    t['dcaron'] = 743;
+    t['Umacron'] = 722;
+    t['uring'] = 611;
+    t['threesuperior'] = 333;
+    t['Ograve'] = 778;
+    t['Agrave'] = 722;
+    t['Abreve'] = 722;
+    t['multiply'] = 584;
+    t['uacute'] = 611;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 494;
+    t['ydieresis'] = 556;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 556;
+    t['edieresis'] = 556;
+    t['cacute'] = 556;
+    t['nacute'] = 611;
+    t['umacron'] = 611;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 278;
+    t['plusminus'] = 584;
+    t['brokenbar'] = 280;
+    t['registered'] = 737;
+    t['Gbreve'] = 778;
+    t['Idotaccent'] = 278;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 389;
+    t['omacron'] = 611;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 722;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 389;
+    t['eogonek'] = 556;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 722;
+    t['Adieresis'] = 722;
+    t['egrave'] = 556;
+    t['zacute'] = 500;
+    t['iogonek'] = 278;
+    t['Oacute'] = 778;
+    t['oacute'] = 611;
+    t['amacron'] = 556;
+    t['sacute'] = 556;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 778;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 611;
+    t['twosuperior'] = 333;
+    t['Odieresis'] = 778;
+    t['mu'] = 611;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 611;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 611;
+    t['threequarters'] = 834;
+    t['Scedilla'] = 667;
+    t['lcaron'] = 400;
+    t['Kcommaaccent'] = 722;
+    t['Lacute'] = 611;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 556;
+    t['Igrave'] = 278;
+    t['Imacron'] = 278;
+    t['Lcaron'] = 611;
+    t['onehalf'] = 834;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 611;
+    t['ntilde'] = 611;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 556;
+    t['gbreve'] = 611;
+    t['onequarter'] = 834;
+    t['Scaron'] = 667;
+    t['Scommaaccent'] = 667;
+    t['Ohungarumlaut'] = 778;
+    t['degree'] = 400;
+    t['ograve'] = 611;
+    t['Ccaron'] = 722;
+    t['ugrave'] = 611;
+    t['radical'] = 549;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 389;
+    t['Ntilde'] = 722;
+    t['otilde'] = 611;
+    t['Rcommaaccent'] = 722;
+    t['Lcommaaccent'] = 611;
+    t['Atilde'] = 722;
+    t['Aogonek'] = 722;
+    t['Aring'] = 722;
+    t['Otilde'] = 778;
+    t['zdotaccent'] = 500;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 278;
+    t['kcommaaccent'] = 556;
+    t['minus'] = 584;
+    t['Icircumflex'] = 278;
+    t['ncaron'] = 611;
+    t['tcommaaccent'] = 333;
+    t['logicalnot'] = 584;
+    t['odieresis'] = 611;
+    t['udieresis'] = 611;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 611;
+    t['eth'] = 611;
+    t['zcaron'] = 500;
+    t['ncommaaccent'] = 611;
+    t['onesuperior'] = 333;
+    t['imacron'] = 278;
+    t['Euro'] = 556;
+  });
+  t['Helvetica-BoldOblique'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 278;
+    t['exclam'] = 333;
+    t['quotedbl'] = 474;
+    t['numbersign'] = 556;
+    t['dollar'] = 556;
+    t['percent'] = 889;
+    t['ampersand'] = 722;
+    t['quoteright'] = 278;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 389;
+    t['plus'] = 584;
+    t['comma'] = 278;
+    t['hyphen'] = 333;
+    t['period'] = 278;
+    t['slash'] = 278;
+    t['zero'] = 556;
+    t['one'] = 556;
+    t['two'] = 556;
+    t['three'] = 556;
+    t['four'] = 556;
+    t['five'] = 556;
+    t['six'] = 556;
+    t['seven'] = 556;
+    t['eight'] = 556;
+    t['nine'] = 556;
+    t['colon'] = 333;
+    t['semicolon'] = 333;
+    t['less'] = 584;
+    t['equal'] = 584;
+    t['greater'] = 584;
+    t['question'] = 611;
+    t['at'] = 975;
+    t['A'] = 722;
+    t['B'] = 722;
+    t['C'] = 722;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 611;
+    t['G'] = 778;
+    t['H'] = 722;
+    t['I'] = 278;
+    t['J'] = 556;
+    t['K'] = 722;
+    t['L'] = 611;
+    t['M'] = 833;
+    t['N'] = 722;
+    t['O'] = 778;
+    t['P'] = 667;
+    t['Q'] = 778;
+    t['R'] = 722;
+    t['S'] = 667;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 667;
+    t['W'] = 944;
+    t['X'] = 667;
+    t['Y'] = 667;
+    t['Z'] = 611;
+    t['bracketleft'] = 333;
+    t['backslash'] = 278;
+    t['bracketright'] = 333;
+    t['asciicircum'] = 584;
+    t['underscore'] = 556;
+    t['quoteleft'] = 278;
+    t['a'] = 556;
+    t['b'] = 611;
+    t['c'] = 556;
+    t['d'] = 611;
+    t['e'] = 556;
+    t['f'] = 333;
+    t['g'] = 611;
+    t['h'] = 611;
+    t['i'] = 278;
+    t['j'] = 278;
+    t['k'] = 556;
+    t['l'] = 278;
+    t['m'] = 889;
+    t['n'] = 611;
+    t['o'] = 611;
+    t['p'] = 611;
+    t['q'] = 611;
+    t['r'] = 389;
+    t['s'] = 556;
+    t['t'] = 333;
+    t['u'] = 611;
+    t['v'] = 556;
+    t['w'] = 778;
+    t['x'] = 556;
+    t['y'] = 556;
+    t['z'] = 500;
+    t['braceleft'] = 389;
+    t['bar'] = 280;
+    t['braceright'] = 389;
+    t['asciitilde'] = 584;
+    t['exclamdown'] = 333;
+    t['cent'] = 556;
+    t['sterling'] = 556;
+    t['fraction'] = 167;
+    t['yen'] = 556;
+    t['florin'] = 556;
+    t['section'] = 556;
+    t['currency'] = 556;
+    t['quotesingle'] = 238;
+    t['quotedblleft'] = 500;
+    t['guillemotleft'] = 556;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 611;
+    t['fl'] = 611;
+    t['endash'] = 556;
+    t['dagger'] = 556;
+    t['daggerdbl'] = 556;
+    t['periodcentered'] = 278;
+    t['paragraph'] = 556;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 278;
+    t['quotedblbase'] = 500;
+    t['quotedblright'] = 500;
+    t['guillemotright'] = 556;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 611;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 1000;
+    t['ordfeminine'] = 370;
+    t['Lslash'] = 611;
+    t['Oslash'] = 778;
+    t['OE'] = 1000;
+    t['ordmasculine'] = 365;
+    t['ae'] = 889;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 611;
+    t['oe'] = 944;
+    t['germandbls'] = 611;
+    t['Idieresis'] = 278;
+    t['eacute'] = 556;
+    t['abreve'] = 556;
+    t['uhungarumlaut'] = 611;
+    t['ecaron'] = 556;
+    t['Ydieresis'] = 667;
+    t['divide'] = 584;
+    t['Yacute'] = 667;
+    t['Acircumflex'] = 722;
+    t['aacute'] = 556;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 556;
+    t['scommaaccent'] = 556;
+    t['ecircumflex'] = 556;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 556;
+    t['Uacute'] = 722;
+    t['uogonek'] = 611;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 737;
+    t['Emacron'] = 667;
+    t['ccaron'] = 556;
+    t['aring'] = 556;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 278;
+    t['agrave'] = 556;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 722;
+    t['atilde'] = 556;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 556;
+    t['scedilla'] = 556;
+    t['iacute'] = 278;
+    t['lozenge'] = 494;
+    t['Rcaron'] = 722;
+    t['Gcommaaccent'] = 778;
+    t['ucircumflex'] = 611;
+    t['acircumflex'] = 556;
+    t['Amacron'] = 722;
+    t['rcaron'] = 389;
+    t['ccedilla'] = 556;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 667;
+    t['Omacron'] = 778;
+    t['Racute'] = 722;
+    t['Sacute'] = 667;
+    t['dcaron'] = 743;
+    t['Umacron'] = 722;
+    t['uring'] = 611;
+    t['threesuperior'] = 333;
+    t['Ograve'] = 778;
+    t['Agrave'] = 722;
+    t['Abreve'] = 722;
+    t['multiply'] = 584;
+    t['uacute'] = 611;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 494;
+    t['ydieresis'] = 556;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 556;
+    t['edieresis'] = 556;
+    t['cacute'] = 556;
+    t['nacute'] = 611;
+    t['umacron'] = 611;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 278;
+    t['plusminus'] = 584;
+    t['brokenbar'] = 280;
+    t['registered'] = 737;
+    t['Gbreve'] = 778;
+    t['Idotaccent'] = 278;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 389;
+    t['omacron'] = 611;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 722;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 389;
+    t['eogonek'] = 556;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 722;
+    t['Adieresis'] = 722;
+    t['egrave'] = 556;
+    t['zacute'] = 500;
+    t['iogonek'] = 278;
+    t['Oacute'] = 778;
+    t['oacute'] = 611;
+    t['amacron'] = 556;
+    t['sacute'] = 556;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 778;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 611;
+    t['twosuperior'] = 333;
+    t['Odieresis'] = 778;
+    t['mu'] = 611;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 611;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 611;
+    t['threequarters'] = 834;
+    t['Scedilla'] = 667;
+    t['lcaron'] = 400;
+    t['Kcommaaccent'] = 722;
+    t['Lacute'] = 611;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 556;
+    t['Igrave'] = 278;
+    t['Imacron'] = 278;
+    t['Lcaron'] = 611;
+    t['onehalf'] = 834;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 611;
+    t['ntilde'] = 611;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 556;
+    t['gbreve'] = 611;
+    t['onequarter'] = 834;
+    t['Scaron'] = 667;
+    t['Scommaaccent'] = 667;
+    t['Ohungarumlaut'] = 778;
+    t['degree'] = 400;
+    t['ograve'] = 611;
+    t['Ccaron'] = 722;
+    t['ugrave'] = 611;
+    t['radical'] = 549;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 389;
+    t['Ntilde'] = 722;
+    t['otilde'] = 611;
+    t['Rcommaaccent'] = 722;
+    t['Lcommaaccent'] = 611;
+    t['Atilde'] = 722;
+    t['Aogonek'] = 722;
+    t['Aring'] = 722;
+    t['Otilde'] = 778;
+    t['zdotaccent'] = 500;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 278;
+    t['kcommaaccent'] = 556;
+    t['minus'] = 584;
+    t['Icircumflex'] = 278;
+    t['ncaron'] = 611;
+    t['tcommaaccent'] = 333;
+    t['logicalnot'] = 584;
+    t['odieresis'] = 611;
+    t['udieresis'] = 611;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 611;
+    t['eth'] = 611;
+    t['zcaron'] = 500;
+    t['ncommaaccent'] = 611;
+    t['onesuperior'] = 333;
+    t['imacron'] = 278;
+    t['Euro'] = 556;
+  });
+  t['Helvetica-Oblique'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 278;
+    t['exclam'] = 278;
+    t['quotedbl'] = 355;
+    t['numbersign'] = 556;
+    t['dollar'] = 556;
+    t['percent'] = 889;
+    t['ampersand'] = 667;
+    t['quoteright'] = 222;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 389;
+    t['plus'] = 584;
+    t['comma'] = 278;
+    t['hyphen'] = 333;
+    t['period'] = 278;
+    t['slash'] = 278;
+    t['zero'] = 556;
+    t['one'] = 556;
+    t['two'] = 556;
+    t['three'] = 556;
+    t['four'] = 556;
+    t['five'] = 556;
+    t['six'] = 556;
+    t['seven'] = 556;
+    t['eight'] = 556;
+    t['nine'] = 556;
+    t['colon'] = 278;
+    t['semicolon'] = 278;
+    t['less'] = 584;
+    t['equal'] = 584;
+    t['greater'] = 584;
+    t['question'] = 556;
+    t['at'] = 1015;
+    t['A'] = 667;
+    t['B'] = 667;
+    t['C'] = 722;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 611;
+    t['G'] = 778;
+    t['H'] = 722;
+    t['I'] = 278;
+    t['J'] = 500;
+    t['K'] = 667;
+    t['L'] = 556;
+    t['M'] = 833;
+    t['N'] = 722;
+    t['O'] = 778;
+    t['P'] = 667;
+    t['Q'] = 778;
+    t['R'] = 722;
+    t['S'] = 667;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 667;
+    t['W'] = 944;
+    t['X'] = 667;
+    t['Y'] = 667;
+    t['Z'] = 611;
+    t['bracketleft'] = 278;
+    t['backslash'] = 278;
+    t['bracketright'] = 278;
+    t['asciicircum'] = 469;
+    t['underscore'] = 556;
+    t['quoteleft'] = 222;
+    t['a'] = 556;
+    t['b'] = 556;
+    t['c'] = 500;
+    t['d'] = 556;
+    t['e'] = 556;
+    t['f'] = 278;
+    t['g'] = 556;
+    t['h'] = 556;
+    t['i'] = 222;
+    t['j'] = 222;
+    t['k'] = 500;
+    t['l'] = 222;
+    t['m'] = 833;
+    t['n'] = 556;
+    t['o'] = 556;
+    t['p'] = 556;
+    t['q'] = 556;
+    t['r'] = 333;
+    t['s'] = 500;
+    t['t'] = 278;
+    t['u'] = 556;
+    t['v'] = 500;
+    t['w'] = 722;
+    t['x'] = 500;
+    t['y'] = 500;
+    t['z'] = 500;
+    t['braceleft'] = 334;
+    t['bar'] = 260;
+    t['braceright'] = 334;
+    t['asciitilde'] = 584;
+    t['exclamdown'] = 333;
+    t['cent'] = 556;
+    t['sterling'] = 556;
+    t['fraction'] = 167;
+    t['yen'] = 556;
+    t['florin'] = 556;
+    t['section'] = 556;
+    t['currency'] = 556;
+    t['quotesingle'] = 191;
+    t['quotedblleft'] = 333;
+    t['guillemotleft'] = 556;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 500;
+    t['fl'] = 500;
+    t['endash'] = 556;
+    t['dagger'] = 556;
+    t['daggerdbl'] = 556;
+    t['periodcentered'] = 278;
+    t['paragraph'] = 537;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 222;
+    t['quotedblbase'] = 333;
+    t['quotedblright'] = 333;
+    t['guillemotright'] = 556;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 611;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 1000;
+    t['ordfeminine'] = 370;
+    t['Lslash'] = 556;
+    t['Oslash'] = 778;
+    t['OE'] = 1000;
+    t['ordmasculine'] = 365;
+    t['ae'] = 889;
+    t['dotlessi'] = 278;
+    t['lslash'] = 222;
+    t['oslash'] = 611;
+    t['oe'] = 944;
+    t['germandbls'] = 611;
+    t['Idieresis'] = 278;
+    t['eacute'] = 556;
+    t['abreve'] = 556;
+    t['uhungarumlaut'] = 556;
+    t['ecaron'] = 556;
+    t['Ydieresis'] = 667;
+    t['divide'] = 584;
+    t['Yacute'] = 667;
+    t['Acircumflex'] = 667;
+    t['aacute'] = 556;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 500;
+    t['scommaaccent'] = 500;
+    t['ecircumflex'] = 556;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 556;
+    t['Uacute'] = 722;
+    t['uogonek'] = 556;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 737;
+    t['Emacron'] = 667;
+    t['ccaron'] = 500;
+    t['aring'] = 556;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 222;
+    t['agrave'] = 556;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 722;
+    t['atilde'] = 556;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 500;
+    t['scedilla'] = 500;
+    t['iacute'] = 278;
+    t['lozenge'] = 471;
+    t['Rcaron'] = 722;
+    t['Gcommaaccent'] = 778;
+    t['ucircumflex'] = 556;
+    t['acircumflex'] = 556;
+    t['Amacron'] = 667;
+    t['rcaron'] = 333;
+    t['ccedilla'] = 500;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 667;
+    t['Omacron'] = 778;
+    t['Racute'] = 722;
+    t['Sacute'] = 667;
+    t['dcaron'] = 643;
+    t['Umacron'] = 722;
+    t['uring'] = 556;
+    t['threesuperior'] = 333;
+    t['Ograve'] = 778;
+    t['Agrave'] = 667;
+    t['Abreve'] = 667;
+    t['multiply'] = 584;
+    t['uacute'] = 556;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 476;
+    t['ydieresis'] = 500;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 556;
+    t['edieresis'] = 556;
+    t['cacute'] = 500;
+    t['nacute'] = 556;
+    t['umacron'] = 556;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 278;
+    t['plusminus'] = 584;
+    t['brokenbar'] = 260;
+    t['registered'] = 737;
+    t['Gbreve'] = 778;
+    t['Idotaccent'] = 278;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 333;
+    t['omacron'] = 556;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 722;
+    t['lcommaaccent'] = 222;
+    t['tcaron'] = 317;
+    t['eogonek'] = 556;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 667;
+    t['Adieresis'] = 667;
+    t['egrave'] = 556;
+    t['zacute'] = 500;
+    t['iogonek'] = 222;
+    t['Oacute'] = 778;
+    t['oacute'] = 556;
+    t['amacron'] = 556;
+    t['sacute'] = 500;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 778;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 556;
+    t['twosuperior'] = 333;
+    t['Odieresis'] = 778;
+    t['mu'] = 556;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 556;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 556;
+    t['threequarters'] = 834;
+    t['Scedilla'] = 667;
+    t['lcaron'] = 299;
+    t['Kcommaaccent'] = 667;
+    t['Lacute'] = 556;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 556;
+    t['Igrave'] = 278;
+    t['Imacron'] = 278;
+    t['Lcaron'] = 556;
+    t['onehalf'] = 834;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 556;
+    t['ntilde'] = 556;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 556;
+    t['gbreve'] = 556;
+    t['onequarter'] = 834;
+    t['Scaron'] = 667;
+    t['Scommaaccent'] = 667;
+    t['Ohungarumlaut'] = 778;
+    t['degree'] = 400;
+    t['ograve'] = 556;
+    t['Ccaron'] = 722;
+    t['ugrave'] = 556;
+    t['radical'] = 453;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 333;
+    t['Ntilde'] = 722;
+    t['otilde'] = 556;
+    t['Rcommaaccent'] = 722;
+    t['Lcommaaccent'] = 556;
+    t['Atilde'] = 667;
+    t['Aogonek'] = 667;
+    t['Aring'] = 667;
+    t['Otilde'] = 778;
+    t['zdotaccent'] = 500;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 278;
+    t['kcommaaccent'] = 500;
+    t['minus'] = 584;
+    t['Icircumflex'] = 278;
+    t['ncaron'] = 556;
+    t['tcommaaccent'] = 278;
+    t['logicalnot'] = 584;
+    t['odieresis'] = 556;
+    t['udieresis'] = 556;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 556;
+    t['eth'] = 556;
+    t['zcaron'] = 500;
+    t['ncommaaccent'] = 556;
+    t['onesuperior'] = 333;
+    t['imacron'] = 278;
+    t['Euro'] = 556;
+  });
+  t['Symbol'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 250;
+    t['exclam'] = 333;
+    t['universal'] = 713;
+    t['numbersign'] = 500;
+    t['existential'] = 549;
+    t['percent'] = 833;
+    t['ampersand'] = 778;
+    t['suchthat'] = 439;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asteriskmath'] = 500;
+    t['plus'] = 549;
+    t['comma'] = 250;
+    t['minus'] = 549;
+    t['period'] = 250;
+    t['slash'] = 278;
+    t['zero'] = 500;
+    t['one'] = 500;
+    t['two'] = 500;
+    t['three'] = 500;
+    t['four'] = 500;
+    t['five'] = 500;
+    t['six'] = 500;
+    t['seven'] = 500;
+    t['eight'] = 500;
+    t['nine'] = 500;
+    t['colon'] = 278;
+    t['semicolon'] = 278;
+    t['less'] = 549;
+    t['equal'] = 549;
+    t['greater'] = 549;
+    t['question'] = 444;
+    t['congruent'] = 549;
+    t['Alpha'] = 722;
+    t['Beta'] = 667;
+    t['Chi'] = 722;
+    t['Delta'] = 612;
+    t['Epsilon'] = 611;
+    t['Phi'] = 763;
+    t['Gamma'] = 603;
+    t['Eta'] = 722;
+    t['Iota'] = 333;
+    t['theta1'] = 631;
+    t['Kappa'] = 722;
+    t['Lambda'] = 686;
+    t['Mu'] = 889;
+    t['Nu'] = 722;
+    t['Omicron'] = 722;
+    t['Pi'] = 768;
+    t['Theta'] = 741;
+    t['Rho'] = 556;
+    t['Sigma'] = 592;
+    t['Tau'] = 611;
+    t['Upsilon'] = 690;
+    t['sigma1'] = 439;
+    t['Omega'] = 768;
+    t['Xi'] = 645;
+    t['Psi'] = 795;
+    t['Zeta'] = 611;
+    t['bracketleft'] = 333;
+    t['therefore'] = 863;
+    t['bracketright'] = 333;
+    t['perpendicular'] = 658;
+    t['underscore'] = 500;
+    t['radicalex'] = 500;
+    t['alpha'] = 631;
+    t['beta'] = 549;
+    t['chi'] = 549;
+    t['delta'] = 494;
+    t['epsilon'] = 439;
+    t['phi'] = 521;
+    t['gamma'] = 411;
+    t['eta'] = 603;
+    t['iota'] = 329;
+    t['phi1'] = 603;
+    t['kappa'] = 549;
+    t['lambda'] = 549;
+    t['mu'] = 576;
+    t['nu'] = 521;
+    t['omicron'] = 549;
+    t['pi'] = 549;
+    t['theta'] = 521;
+    t['rho'] = 549;
+    t['sigma'] = 603;
+    t['tau'] = 439;
+    t['upsilon'] = 576;
+    t['omega1'] = 713;
+    t['omega'] = 686;
+    t['xi'] = 493;
+    t['psi'] = 686;
+    t['zeta'] = 494;
+    t['braceleft'] = 480;
+    t['bar'] = 200;
+    t['braceright'] = 480;
+    t['similar'] = 549;
+    t['Euro'] = 750;
+    t['Upsilon1'] = 620;
+    t['minute'] = 247;
+    t['lessequal'] = 549;
+    t['fraction'] = 167;
+    t['infinity'] = 713;
+    t['florin'] = 500;
+    t['club'] = 753;
+    t['diamond'] = 753;
+    t['heart'] = 753;
+    t['spade'] = 753;
+    t['arrowboth'] = 1042;
+    t['arrowleft'] = 987;
+    t['arrowup'] = 603;
+    t['arrowright'] = 987;
+    t['arrowdown'] = 603;
+    t['degree'] = 400;
+    t['plusminus'] = 549;
+    t['second'] = 411;
+    t['greaterequal'] = 549;
+    t['multiply'] = 549;
+    t['proportional'] = 713;
+    t['partialdiff'] = 494;
+    t['bullet'] = 460;
+    t['divide'] = 549;
+    t['notequal'] = 549;
+    t['equivalence'] = 549;
+    t['approxequal'] = 549;
+    t['ellipsis'] = 1000;
+    t['arrowvertex'] = 603;
+    t['arrowhorizex'] = 1000;
+    t['carriagereturn'] = 658;
+    t['aleph'] = 823;
+    t['Ifraktur'] = 686;
+    t['Rfraktur'] = 795;
+    t['weierstrass'] = 987;
+    t['circlemultiply'] = 768;
+    t['circleplus'] = 768;
+    t['emptyset'] = 823;
+    t['intersection'] = 768;
+    t['union'] = 768;
+    t['propersuperset'] = 713;
+    t['reflexsuperset'] = 713;
+    t['notsubset'] = 713;
+    t['propersubset'] = 713;
+    t['reflexsubset'] = 713;
+    t['element'] = 713;
+    t['notelement'] = 713;
+    t['angle'] = 768;
+    t['gradient'] = 713;
+    t['registerserif'] = 790;
+    t['copyrightserif'] = 790;
+    t['trademarkserif'] = 890;
+    t['product'] = 823;
+    t['radical'] = 549;
+    t['dotmath'] = 250;
+    t['logicalnot'] = 713;
+    t['logicaland'] = 603;
+    t['logicalor'] = 603;
+    t['arrowdblboth'] = 1042;
+    t['arrowdblleft'] = 987;
+    t['arrowdblup'] = 603;
+    t['arrowdblright'] = 987;
+    t['arrowdbldown'] = 603;
+    t['lozenge'] = 494;
+    t['angleleft'] = 329;
+    t['registersans'] = 790;
+    t['copyrightsans'] = 790;
+    t['trademarksans'] = 786;
+    t['summation'] = 713;
+    t['parenlefttp'] = 384;
+    t['parenleftex'] = 384;
+    t['parenleftbt'] = 384;
+    t['bracketlefttp'] = 384;
+    t['bracketleftex'] = 384;
+    t['bracketleftbt'] = 384;
+    t['bracelefttp'] = 494;
+    t['braceleftmid'] = 494;
+    t['braceleftbt'] = 494;
+    t['braceex'] = 494;
+    t['angleright'] = 329;
+    t['integral'] = 274;
+    t['integraltp'] = 686;
+    t['integralex'] = 686;
+    t['integralbt'] = 686;
+    t['parenrighttp'] = 384;
+    t['parenrightex'] = 384;
+    t['parenrightbt'] = 384;
+    t['bracketrighttp'] = 384;
+    t['bracketrightex'] = 384;
+    t['bracketrightbt'] = 384;
+    t['bracerighttp'] = 494;
+    t['bracerightmid'] = 494;
+    t['bracerightbt'] = 494;
+    t['apple'] = 790;
+  });
+  t['Times-Roman'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 250;
+    t['exclam'] = 333;
+    t['quotedbl'] = 408;
+    t['numbersign'] = 500;
+    t['dollar'] = 500;
+    t['percent'] = 833;
+    t['ampersand'] = 778;
+    t['quoteright'] = 333;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 500;
+    t['plus'] = 564;
+    t['comma'] = 250;
+    t['hyphen'] = 333;
+    t['period'] = 250;
+    t['slash'] = 278;
+    t['zero'] = 500;
+    t['one'] = 500;
+    t['two'] = 500;
+    t['three'] = 500;
+    t['four'] = 500;
+    t['five'] = 500;
+    t['six'] = 500;
+    t['seven'] = 500;
+    t['eight'] = 500;
+    t['nine'] = 500;
+    t['colon'] = 278;
+    t['semicolon'] = 278;
+    t['less'] = 564;
+    t['equal'] = 564;
+    t['greater'] = 564;
+    t['question'] = 444;
+    t['at'] = 921;
+    t['A'] = 722;
+    t['B'] = 667;
+    t['C'] = 667;
+    t['D'] = 722;
+    t['E'] = 611;
+    t['F'] = 556;
+    t['G'] = 722;
+    t['H'] = 722;
+    t['I'] = 333;
+    t['J'] = 389;
+    t['K'] = 722;
+    t['L'] = 611;
+    t['M'] = 889;
+    t['N'] = 722;
+    t['O'] = 722;
+    t['P'] = 556;
+    t['Q'] = 722;
+    t['R'] = 667;
+    t['S'] = 556;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 722;
+    t['W'] = 944;
+    t['X'] = 722;
+    t['Y'] = 722;
+    t['Z'] = 611;
+    t['bracketleft'] = 333;
+    t['backslash'] = 278;
+    t['bracketright'] = 333;
+    t['asciicircum'] = 469;
+    t['underscore'] = 500;
+    t['quoteleft'] = 333;
+    t['a'] = 444;
+    t['b'] = 500;
+    t['c'] = 444;
+    t['d'] = 500;
+    t['e'] = 444;
+    t['f'] = 333;
+    t['g'] = 500;
+    t['h'] = 500;
+    t['i'] = 278;
+    t['j'] = 278;
+    t['k'] = 500;
+    t['l'] = 278;
+    t['m'] = 778;
+    t['n'] = 500;
+    t['o'] = 500;
+    t['p'] = 500;
+    t['q'] = 500;
+    t['r'] = 333;
+    t['s'] = 389;
+    t['t'] = 278;
+    t['u'] = 500;
+    t['v'] = 500;
+    t['w'] = 722;
+    t['x'] = 500;
+    t['y'] = 500;
+    t['z'] = 444;
+    t['braceleft'] = 480;
+    t['bar'] = 200;
+    t['braceright'] = 480;
+    t['asciitilde'] = 541;
+    t['exclamdown'] = 333;
+    t['cent'] = 500;
+    t['sterling'] = 500;
+    t['fraction'] = 167;
+    t['yen'] = 500;
+    t['florin'] = 500;
+    t['section'] = 500;
+    t['currency'] = 500;
+    t['quotesingle'] = 180;
+    t['quotedblleft'] = 444;
+    t['guillemotleft'] = 500;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 556;
+    t['fl'] = 556;
+    t['endash'] = 500;
+    t['dagger'] = 500;
+    t['daggerdbl'] = 500;
+    t['periodcentered'] = 250;
+    t['paragraph'] = 453;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 333;
+    t['quotedblbase'] = 444;
+    t['quotedblright'] = 444;
+    t['guillemotright'] = 500;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 444;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 889;
+    t['ordfeminine'] = 276;
+    t['Lslash'] = 611;
+    t['Oslash'] = 722;
+    t['OE'] = 889;
+    t['ordmasculine'] = 310;
+    t['ae'] = 667;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 500;
+    t['oe'] = 722;
+    t['germandbls'] = 500;
+    t['Idieresis'] = 333;
+    t['eacute'] = 444;
+    t['abreve'] = 444;
+    t['uhungarumlaut'] = 500;
+    t['ecaron'] = 444;
+    t['Ydieresis'] = 722;
+    t['divide'] = 564;
+    t['Yacute'] = 722;
+    t['Acircumflex'] = 722;
+    t['aacute'] = 444;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 500;
+    t['scommaaccent'] = 389;
+    t['ecircumflex'] = 444;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 444;
+    t['Uacute'] = 722;
+    t['uogonek'] = 500;
+    t['Edieresis'] = 611;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 760;
+    t['Emacron'] = 611;
+    t['ccaron'] = 444;
+    t['aring'] = 444;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 278;
+    t['agrave'] = 444;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 667;
+    t['atilde'] = 444;
+    t['Edotaccent'] = 611;
+    t['scaron'] = 389;
+    t['scedilla'] = 389;
+    t['iacute'] = 278;
+    t['lozenge'] = 471;
+    t['Rcaron'] = 667;
+    t['Gcommaaccent'] = 722;
+    t['ucircumflex'] = 500;
+    t['acircumflex'] = 444;
+    t['Amacron'] = 722;
+    t['rcaron'] = 333;
+    t['ccedilla'] = 444;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 556;
+    t['Omacron'] = 722;
+    t['Racute'] = 667;
+    t['Sacute'] = 556;
+    t['dcaron'] = 588;
+    t['Umacron'] = 722;
+    t['uring'] = 500;
+    t['threesuperior'] = 300;
+    t['Ograve'] = 722;
+    t['Agrave'] = 722;
+    t['Abreve'] = 722;
+    t['multiply'] = 564;
+    t['uacute'] = 500;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 476;
+    t['ydieresis'] = 500;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 611;
+    t['adieresis'] = 444;
+    t['edieresis'] = 444;
+    t['cacute'] = 444;
+    t['nacute'] = 500;
+    t['umacron'] = 500;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 333;
+    t['plusminus'] = 564;
+    t['brokenbar'] = 200;
+    t['registered'] = 760;
+    t['Gbreve'] = 722;
+    t['Idotaccent'] = 333;
+    t['summation'] = 600;
+    t['Egrave'] = 611;
+    t['racute'] = 333;
+    t['omacron'] = 500;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 667;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 326;
+    t['eogonek'] = 444;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 722;
+    t['Adieresis'] = 722;
+    t['egrave'] = 444;
+    t['zacute'] = 444;
+    t['iogonek'] = 278;
+    t['Oacute'] = 722;
+    t['oacute'] = 500;
+    t['amacron'] = 444;
+    t['sacute'] = 389;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 722;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 500;
+    t['twosuperior'] = 300;
+    t['Odieresis'] = 722;
+    t['mu'] = 500;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 500;
+    t['Eogonek'] = 611;
+    t['dcroat'] = 500;
+    t['threequarters'] = 750;
+    t['Scedilla'] = 556;
+    t['lcaron'] = 344;
+    t['Kcommaaccent'] = 722;
+    t['Lacute'] = 611;
+    t['trademark'] = 980;
+    t['edotaccent'] = 444;
+    t['Igrave'] = 333;
+    t['Imacron'] = 333;
+    t['Lcaron'] = 611;
+    t['onehalf'] = 750;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 500;
+    t['ntilde'] = 500;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 611;
+    t['emacron'] = 444;
+    t['gbreve'] = 500;
+    t['onequarter'] = 750;
+    t['Scaron'] = 556;
+    t['Scommaaccent'] = 556;
+    t['Ohungarumlaut'] = 722;
+    t['degree'] = 400;
+    t['ograve'] = 500;
+    t['Ccaron'] = 667;
+    t['ugrave'] = 500;
+    t['radical'] = 453;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 333;
+    t['Ntilde'] = 722;
+    t['otilde'] = 500;
+    t['Rcommaaccent'] = 667;
+    t['Lcommaaccent'] = 611;
+    t['Atilde'] = 722;
+    t['Aogonek'] = 722;
+    t['Aring'] = 722;
+    t['Otilde'] = 722;
+    t['zdotaccent'] = 444;
+    t['Ecaron'] = 611;
+    t['Iogonek'] = 333;
+    t['kcommaaccent'] = 500;
+    t['minus'] = 564;
+    t['Icircumflex'] = 333;
+    t['ncaron'] = 500;
+    t['tcommaaccent'] = 278;
+    t['logicalnot'] = 564;
+    t['odieresis'] = 500;
+    t['udieresis'] = 500;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 500;
+    t['eth'] = 500;
+    t['zcaron'] = 444;
+    t['ncommaaccent'] = 500;
+    t['onesuperior'] = 300;
+    t['imacron'] = 278;
+    t['Euro'] = 500;
+  });
+  t['Times-Bold'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 250;
+    t['exclam'] = 333;
+    t['quotedbl'] = 555;
+    t['numbersign'] = 500;
+    t['dollar'] = 500;
+    t['percent'] = 1000;
+    t['ampersand'] = 833;
+    t['quoteright'] = 333;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 500;
+    t['plus'] = 570;
+    t['comma'] = 250;
+    t['hyphen'] = 333;
+    t['period'] = 250;
+    t['slash'] = 278;
+    t['zero'] = 500;
+    t['one'] = 500;
+    t['two'] = 500;
+    t['three'] = 500;
+    t['four'] = 500;
+    t['five'] = 500;
+    t['six'] = 500;
+    t['seven'] = 500;
+    t['eight'] = 500;
+    t['nine'] = 500;
+    t['colon'] = 333;
+    t['semicolon'] = 333;
+    t['less'] = 570;
+    t['equal'] = 570;
+    t['greater'] = 570;
+    t['question'] = 500;
+    t['at'] = 930;
+    t['A'] = 722;
+    t['B'] = 667;
+    t['C'] = 722;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 611;
+    t['G'] = 778;
+    t['H'] = 778;
+    t['I'] = 389;
+    t['J'] = 500;
+    t['K'] = 778;
+    t['L'] = 667;
+    t['M'] = 944;
+    t['N'] = 722;
+    t['O'] = 778;
+    t['P'] = 611;
+    t['Q'] = 778;
+    t['R'] = 722;
+    t['S'] = 556;
+    t['T'] = 667;
+    t['U'] = 722;
+    t['V'] = 722;
+    t['W'] = 1000;
+    t['X'] = 722;
+    t['Y'] = 722;
+    t['Z'] = 667;
+    t['bracketleft'] = 333;
+    t['backslash'] = 278;
+    t['bracketright'] = 333;
+    t['asciicircum'] = 581;
+    t['underscore'] = 500;
+    t['quoteleft'] = 333;
+    t['a'] = 500;
+    t['b'] = 556;
+    t['c'] = 444;
+    t['d'] = 556;
+    t['e'] = 444;
+    t['f'] = 333;
+    t['g'] = 500;
+    t['h'] = 556;
+    t['i'] = 278;
+    t['j'] = 333;
+    t['k'] = 556;
+    t['l'] = 278;
+    t['m'] = 833;
+    t['n'] = 556;
+    t['o'] = 500;
+    t['p'] = 556;
+    t['q'] = 556;
+    t['r'] = 444;
+    t['s'] = 389;
+    t['t'] = 333;
+    t['u'] = 556;
+    t['v'] = 500;
+    t['w'] = 722;
+    t['x'] = 500;
+    t['y'] = 500;
+    t['z'] = 444;
+    t['braceleft'] = 394;
+    t['bar'] = 220;
+    t['braceright'] = 394;
+    t['asciitilde'] = 520;
+    t['exclamdown'] = 333;
+    t['cent'] = 500;
+    t['sterling'] = 500;
+    t['fraction'] = 167;
+    t['yen'] = 500;
+    t['florin'] = 500;
+    t['section'] = 500;
+    t['currency'] = 500;
+    t['quotesingle'] = 278;
+    t['quotedblleft'] = 500;
+    t['guillemotleft'] = 500;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 556;
+    t['fl'] = 556;
+    t['endash'] = 500;
+    t['dagger'] = 500;
+    t['daggerdbl'] = 500;
+    t['periodcentered'] = 250;
+    t['paragraph'] = 540;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 333;
+    t['quotedblbase'] = 500;
+    t['quotedblright'] = 500;
+    t['guillemotright'] = 500;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 500;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 1000;
+    t['ordfeminine'] = 300;
+    t['Lslash'] = 667;
+    t['Oslash'] = 778;
+    t['OE'] = 1000;
+    t['ordmasculine'] = 330;
+    t['ae'] = 722;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 500;
+    t['oe'] = 722;
+    t['germandbls'] = 556;
+    t['Idieresis'] = 389;
+    t['eacute'] = 444;
+    t['abreve'] = 500;
+    t['uhungarumlaut'] = 556;
+    t['ecaron'] = 444;
+    t['Ydieresis'] = 722;
+    t['divide'] = 570;
+    t['Yacute'] = 722;
+    t['Acircumflex'] = 722;
+    t['aacute'] = 500;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 500;
+    t['scommaaccent'] = 389;
+    t['ecircumflex'] = 444;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 500;
+    t['Uacute'] = 722;
+    t['uogonek'] = 556;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 747;
+    t['Emacron'] = 667;
+    t['ccaron'] = 444;
+    t['aring'] = 500;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 278;
+    t['agrave'] = 500;
+    t['Tcommaaccent'] = 667;
+    t['Cacute'] = 722;
+    t['atilde'] = 500;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 389;
+    t['scedilla'] = 389;
+    t['iacute'] = 278;
+    t['lozenge'] = 494;
+    t['Rcaron'] = 722;
+    t['Gcommaaccent'] = 778;
+    t['ucircumflex'] = 556;
+    t['acircumflex'] = 500;
+    t['Amacron'] = 722;
+    t['rcaron'] = 444;
+    t['ccedilla'] = 444;
+    t['Zdotaccent'] = 667;
+    t['Thorn'] = 611;
+    t['Omacron'] = 778;
+    t['Racute'] = 722;
+    t['Sacute'] = 556;
+    t['dcaron'] = 672;
+    t['Umacron'] = 722;
+    t['uring'] = 556;
+    t['threesuperior'] = 300;
+    t['Ograve'] = 778;
+    t['Agrave'] = 722;
+    t['Abreve'] = 722;
+    t['multiply'] = 570;
+    t['uacute'] = 556;
+    t['Tcaron'] = 667;
+    t['partialdiff'] = 494;
+    t['ydieresis'] = 500;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 500;
+    t['edieresis'] = 444;
+    t['cacute'] = 444;
+    t['nacute'] = 556;
+    t['umacron'] = 556;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 389;
+    t['plusminus'] = 570;
+    t['brokenbar'] = 220;
+    t['registered'] = 747;
+    t['Gbreve'] = 778;
+    t['Idotaccent'] = 389;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 444;
+    t['omacron'] = 500;
+    t['Zacute'] = 667;
+    t['Zcaron'] = 667;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 722;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 416;
+    t['eogonek'] = 444;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 722;
+    t['Adieresis'] = 722;
+    t['egrave'] = 444;
+    t['zacute'] = 444;
+    t['iogonek'] = 278;
+    t['Oacute'] = 778;
+    t['oacute'] = 500;
+    t['amacron'] = 500;
+    t['sacute'] = 389;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 778;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 556;
+    t['twosuperior'] = 300;
+    t['Odieresis'] = 778;
+    t['mu'] = 556;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 500;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 556;
+    t['threequarters'] = 750;
+    t['Scedilla'] = 556;
+    t['lcaron'] = 394;
+    t['Kcommaaccent'] = 778;
+    t['Lacute'] = 667;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 444;
+    t['Igrave'] = 389;
+    t['Imacron'] = 389;
+    t['Lcaron'] = 667;
+    t['onehalf'] = 750;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 500;
+    t['ntilde'] = 556;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 444;
+    t['gbreve'] = 500;
+    t['onequarter'] = 750;
+    t['Scaron'] = 556;
+    t['Scommaaccent'] = 556;
+    t['Ohungarumlaut'] = 778;
+    t['degree'] = 400;
+    t['ograve'] = 500;
+    t['Ccaron'] = 722;
+    t['ugrave'] = 556;
+    t['radical'] = 549;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 444;
+    t['Ntilde'] = 722;
+    t['otilde'] = 500;
+    t['Rcommaaccent'] = 722;
+    t['Lcommaaccent'] = 667;
+    t['Atilde'] = 722;
+    t['Aogonek'] = 722;
+    t['Aring'] = 722;
+    t['Otilde'] = 778;
+    t['zdotaccent'] = 444;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 389;
+    t['kcommaaccent'] = 556;
+    t['minus'] = 570;
+    t['Icircumflex'] = 389;
+    t['ncaron'] = 556;
+    t['tcommaaccent'] = 333;
+    t['logicalnot'] = 570;
+    t['odieresis'] = 500;
+    t['udieresis'] = 556;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 500;
+    t['eth'] = 500;
+    t['zcaron'] = 444;
+    t['ncommaaccent'] = 556;
+    t['onesuperior'] = 300;
+    t['imacron'] = 278;
+    t['Euro'] = 500;
+  });
+  t['Times-BoldItalic'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 250;
+    t['exclam'] = 389;
+    t['quotedbl'] = 555;
+    t['numbersign'] = 500;
+    t['dollar'] = 500;
+    t['percent'] = 833;
+    t['ampersand'] = 778;
+    t['quoteright'] = 333;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 500;
+    t['plus'] = 570;
+    t['comma'] = 250;
+    t['hyphen'] = 333;
+    t['period'] = 250;
+    t['slash'] = 278;
+    t['zero'] = 500;
+    t['one'] = 500;
+    t['two'] = 500;
+    t['three'] = 500;
+    t['four'] = 500;
+    t['five'] = 500;
+    t['six'] = 500;
+    t['seven'] = 500;
+    t['eight'] = 500;
+    t['nine'] = 500;
+    t['colon'] = 333;
+    t['semicolon'] = 333;
+    t['less'] = 570;
+    t['equal'] = 570;
+    t['greater'] = 570;
+    t['question'] = 500;
+    t['at'] = 832;
+    t['A'] = 667;
+    t['B'] = 667;
+    t['C'] = 667;
+    t['D'] = 722;
+    t['E'] = 667;
+    t['F'] = 667;
+    t['G'] = 722;
+    t['H'] = 778;
+    t['I'] = 389;
+    t['J'] = 500;
+    t['K'] = 667;
+    t['L'] = 611;
+    t['M'] = 889;
+    t['N'] = 722;
+    t['O'] = 722;
+    t['P'] = 611;
+    t['Q'] = 722;
+    t['R'] = 667;
+    t['S'] = 556;
+    t['T'] = 611;
+    t['U'] = 722;
+    t['V'] = 667;
+    t['W'] = 889;
+    t['X'] = 667;
+    t['Y'] = 611;
+    t['Z'] = 611;
+    t['bracketleft'] = 333;
+    t['backslash'] = 278;
+    t['bracketright'] = 333;
+    t['asciicircum'] = 570;
+    t['underscore'] = 500;
+    t['quoteleft'] = 333;
+    t['a'] = 500;
+    t['b'] = 500;
+    t['c'] = 444;
+    t['d'] = 500;
+    t['e'] = 444;
+    t['f'] = 333;
+    t['g'] = 500;
+    t['h'] = 556;
+    t['i'] = 278;
+    t['j'] = 278;
+    t['k'] = 500;
+    t['l'] = 278;
+    t['m'] = 778;
+    t['n'] = 556;
+    t['o'] = 500;
+    t['p'] = 500;
+    t['q'] = 500;
+    t['r'] = 389;
+    t['s'] = 389;
+    t['t'] = 278;
+    t['u'] = 556;
+    t['v'] = 444;
+    t['w'] = 667;
+    t['x'] = 500;
+    t['y'] = 444;
+    t['z'] = 389;
+    t['braceleft'] = 348;
+    t['bar'] = 220;
+    t['braceright'] = 348;
+    t['asciitilde'] = 570;
+    t['exclamdown'] = 389;
+    t['cent'] = 500;
+    t['sterling'] = 500;
+    t['fraction'] = 167;
+    t['yen'] = 500;
+    t['florin'] = 500;
+    t['section'] = 500;
+    t['currency'] = 500;
+    t['quotesingle'] = 278;
+    t['quotedblleft'] = 500;
+    t['guillemotleft'] = 500;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 556;
+    t['fl'] = 556;
+    t['endash'] = 500;
+    t['dagger'] = 500;
+    t['daggerdbl'] = 500;
+    t['periodcentered'] = 250;
+    t['paragraph'] = 500;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 333;
+    t['quotedblbase'] = 500;
+    t['quotedblright'] = 500;
+    t['guillemotright'] = 500;
+    t['ellipsis'] = 1000;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 500;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 1000;
+    t['AE'] = 944;
+    t['ordfeminine'] = 266;
+    t['Lslash'] = 611;
+    t['Oslash'] = 722;
+    t['OE'] = 944;
+    t['ordmasculine'] = 300;
+    t['ae'] = 722;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 500;
+    t['oe'] = 722;
+    t['germandbls'] = 500;
+    t['Idieresis'] = 389;
+    t['eacute'] = 444;
+    t['abreve'] = 500;
+    t['uhungarumlaut'] = 556;
+    t['ecaron'] = 444;
+    t['Ydieresis'] = 611;
+    t['divide'] = 570;
+    t['Yacute'] = 611;
+    t['Acircumflex'] = 667;
+    t['aacute'] = 500;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 444;
+    t['scommaaccent'] = 389;
+    t['ecircumflex'] = 444;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 500;
+    t['Uacute'] = 722;
+    t['uogonek'] = 556;
+    t['Edieresis'] = 667;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 747;
+    t['Emacron'] = 667;
+    t['ccaron'] = 444;
+    t['aring'] = 500;
+    t['Ncommaaccent'] = 722;
+    t['lacute'] = 278;
+    t['agrave'] = 500;
+    t['Tcommaaccent'] = 611;
+    t['Cacute'] = 667;
+    t['atilde'] = 500;
+    t['Edotaccent'] = 667;
+    t['scaron'] = 389;
+    t['scedilla'] = 389;
+    t['iacute'] = 278;
+    t['lozenge'] = 494;
+    t['Rcaron'] = 667;
+    t['Gcommaaccent'] = 722;
+    t['ucircumflex'] = 556;
+    t['acircumflex'] = 500;
+    t['Amacron'] = 667;
+    t['rcaron'] = 389;
+    t['ccedilla'] = 444;
+    t['Zdotaccent'] = 611;
+    t['Thorn'] = 611;
+    t['Omacron'] = 722;
+    t['Racute'] = 667;
+    t['Sacute'] = 556;
+    t['dcaron'] = 608;
+    t['Umacron'] = 722;
+    t['uring'] = 556;
+    t['threesuperior'] = 300;
+    t['Ograve'] = 722;
+    t['Agrave'] = 667;
+    t['Abreve'] = 667;
+    t['multiply'] = 570;
+    t['uacute'] = 556;
+    t['Tcaron'] = 611;
+    t['partialdiff'] = 494;
+    t['ydieresis'] = 444;
+    t['Nacute'] = 722;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 667;
+    t['adieresis'] = 500;
+    t['edieresis'] = 444;
+    t['cacute'] = 444;
+    t['nacute'] = 556;
+    t['umacron'] = 556;
+    t['Ncaron'] = 722;
+    t['Iacute'] = 389;
+    t['plusminus'] = 570;
+    t['brokenbar'] = 220;
+    t['registered'] = 747;
+    t['Gbreve'] = 722;
+    t['Idotaccent'] = 389;
+    t['summation'] = 600;
+    t['Egrave'] = 667;
+    t['racute'] = 389;
+    t['omacron'] = 500;
+    t['Zacute'] = 611;
+    t['Zcaron'] = 611;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 667;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 366;
+    t['eogonek'] = 444;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 667;
+    t['Adieresis'] = 667;
+    t['egrave'] = 444;
+    t['zacute'] = 389;
+    t['iogonek'] = 278;
+    t['Oacute'] = 722;
+    t['oacute'] = 500;
+    t['amacron'] = 500;
+    t['sacute'] = 389;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 722;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 500;
+    t['twosuperior'] = 300;
+    t['Odieresis'] = 722;
+    t['mu'] = 576;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 500;
+    t['Eogonek'] = 667;
+    t['dcroat'] = 500;
+    t['threequarters'] = 750;
+    t['Scedilla'] = 556;
+    t['lcaron'] = 382;
+    t['Kcommaaccent'] = 667;
+    t['Lacute'] = 611;
+    t['trademark'] = 1000;
+    t['edotaccent'] = 444;
+    t['Igrave'] = 389;
+    t['Imacron'] = 389;
+    t['Lcaron'] = 611;
+    t['onehalf'] = 750;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 500;
+    t['ntilde'] = 556;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 667;
+    t['emacron'] = 444;
+    t['gbreve'] = 500;
+    t['onequarter'] = 750;
+    t['Scaron'] = 556;
+    t['Scommaaccent'] = 556;
+    t['Ohungarumlaut'] = 722;
+    t['degree'] = 400;
+    t['ograve'] = 500;
+    t['Ccaron'] = 667;
+    t['ugrave'] = 556;
+    t['radical'] = 549;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 389;
+    t['Ntilde'] = 722;
+    t['otilde'] = 500;
+    t['Rcommaaccent'] = 667;
+    t['Lcommaaccent'] = 611;
+    t['Atilde'] = 667;
+    t['Aogonek'] = 667;
+    t['Aring'] = 667;
+    t['Otilde'] = 722;
+    t['zdotaccent'] = 389;
+    t['Ecaron'] = 667;
+    t['Iogonek'] = 389;
+    t['kcommaaccent'] = 500;
+    t['minus'] = 606;
+    t['Icircumflex'] = 389;
+    t['ncaron'] = 556;
+    t['tcommaaccent'] = 278;
+    t['logicalnot'] = 606;
+    t['odieresis'] = 500;
+    t['udieresis'] = 556;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 500;
+    t['eth'] = 500;
+    t['zcaron'] = 389;
+    t['ncommaaccent'] = 556;
+    t['onesuperior'] = 300;
+    t['imacron'] = 278;
+    t['Euro'] = 500;
+  });
+  t['Times-Italic'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 250;
+    t['exclam'] = 333;
+    t['quotedbl'] = 420;
+    t['numbersign'] = 500;
+    t['dollar'] = 500;
+    t['percent'] = 833;
+    t['ampersand'] = 778;
+    t['quoteright'] = 333;
+    t['parenleft'] = 333;
+    t['parenright'] = 333;
+    t['asterisk'] = 500;
+    t['plus'] = 675;
+    t['comma'] = 250;
+    t['hyphen'] = 333;
+    t['period'] = 250;
+    t['slash'] = 278;
+    t['zero'] = 500;
+    t['one'] = 500;
+    t['two'] = 500;
+    t['three'] = 500;
+    t['four'] = 500;
+    t['five'] = 500;
+    t['six'] = 500;
+    t['seven'] = 500;
+    t['eight'] = 500;
+    t['nine'] = 500;
+    t['colon'] = 333;
+    t['semicolon'] = 333;
+    t['less'] = 675;
+    t['equal'] = 675;
+    t['greater'] = 675;
+    t['question'] = 500;
+    t['at'] = 920;
+    t['A'] = 611;
+    t['B'] = 611;
+    t['C'] = 667;
+    t['D'] = 722;
+    t['E'] = 611;
+    t['F'] = 611;
+    t['G'] = 722;
+    t['H'] = 722;
+    t['I'] = 333;
+    t['J'] = 444;
+    t['K'] = 667;
+    t['L'] = 556;
+    t['M'] = 833;
+    t['N'] = 667;
+    t['O'] = 722;
+    t['P'] = 611;
+    t['Q'] = 722;
+    t['R'] = 611;
+    t['S'] = 500;
+    t['T'] = 556;
+    t['U'] = 722;
+    t['V'] = 611;
+    t['W'] = 833;
+    t['X'] = 611;
+    t['Y'] = 556;
+    t['Z'] = 556;
+    t['bracketleft'] = 389;
+    t['backslash'] = 278;
+    t['bracketright'] = 389;
+    t['asciicircum'] = 422;
+    t['underscore'] = 500;
+    t['quoteleft'] = 333;
+    t['a'] = 500;
+    t['b'] = 500;
+    t['c'] = 444;
+    t['d'] = 500;
+    t['e'] = 444;
+    t['f'] = 278;
+    t['g'] = 500;
+    t['h'] = 500;
+    t['i'] = 278;
+    t['j'] = 278;
+    t['k'] = 444;
+    t['l'] = 278;
+    t['m'] = 722;
+    t['n'] = 500;
+    t['o'] = 500;
+    t['p'] = 500;
+    t['q'] = 500;
+    t['r'] = 389;
+    t['s'] = 389;
+    t['t'] = 278;
+    t['u'] = 500;
+    t['v'] = 444;
+    t['w'] = 667;
+    t['x'] = 444;
+    t['y'] = 444;
+    t['z'] = 389;
+    t['braceleft'] = 400;
+    t['bar'] = 275;
+    t['braceright'] = 400;
+    t['asciitilde'] = 541;
+    t['exclamdown'] = 389;
+    t['cent'] = 500;
+    t['sterling'] = 500;
+    t['fraction'] = 167;
+    t['yen'] = 500;
+    t['florin'] = 500;
+    t['section'] = 500;
+    t['currency'] = 500;
+    t['quotesingle'] = 214;
+    t['quotedblleft'] = 556;
+    t['guillemotleft'] = 500;
+    t['guilsinglleft'] = 333;
+    t['guilsinglright'] = 333;
+    t['fi'] = 500;
+    t['fl'] = 500;
+    t['endash'] = 500;
+    t['dagger'] = 500;
+    t['daggerdbl'] = 500;
+    t['periodcentered'] = 250;
+    t['paragraph'] = 523;
+    t['bullet'] = 350;
+    t['quotesinglbase'] = 333;
+    t['quotedblbase'] = 556;
+    t['quotedblright'] = 556;
+    t['guillemotright'] = 500;
+    t['ellipsis'] = 889;
+    t['perthousand'] = 1000;
+    t['questiondown'] = 500;
+    t['grave'] = 333;
+    t['acute'] = 333;
+    t['circumflex'] = 333;
+    t['tilde'] = 333;
+    t['macron'] = 333;
+    t['breve'] = 333;
+    t['dotaccent'] = 333;
+    t['dieresis'] = 333;
+    t['ring'] = 333;
+    t['cedilla'] = 333;
+    t['hungarumlaut'] = 333;
+    t['ogonek'] = 333;
+    t['caron'] = 333;
+    t['emdash'] = 889;
+    t['AE'] = 889;
+    t['ordfeminine'] = 276;
+    t['Lslash'] = 556;
+    t['Oslash'] = 722;
+    t['OE'] = 944;
+    t['ordmasculine'] = 310;
+    t['ae'] = 667;
+    t['dotlessi'] = 278;
+    t['lslash'] = 278;
+    t['oslash'] = 500;
+    t['oe'] = 667;
+    t['germandbls'] = 500;
+    t['Idieresis'] = 333;
+    t['eacute'] = 444;
+    t['abreve'] = 500;
+    t['uhungarumlaut'] = 500;
+    t['ecaron'] = 444;
+    t['Ydieresis'] = 556;
+    t['divide'] = 675;
+    t['Yacute'] = 556;
+    t['Acircumflex'] = 611;
+    t['aacute'] = 500;
+    t['Ucircumflex'] = 722;
+    t['yacute'] = 444;
+    t['scommaaccent'] = 389;
+    t['ecircumflex'] = 444;
+    t['Uring'] = 722;
+    t['Udieresis'] = 722;
+    t['aogonek'] = 500;
+    t['Uacute'] = 722;
+    t['uogonek'] = 500;
+    t['Edieresis'] = 611;
+    t['Dcroat'] = 722;
+    t['commaaccent'] = 250;
+    t['copyright'] = 760;
+    t['Emacron'] = 611;
+    t['ccaron'] = 444;
+    t['aring'] = 500;
+    t['Ncommaaccent'] = 667;
+    t['lacute'] = 278;
+    t['agrave'] = 500;
+    t['Tcommaaccent'] = 556;
+    t['Cacute'] = 667;
+    t['atilde'] = 500;
+    t['Edotaccent'] = 611;
+    t['scaron'] = 389;
+    t['scedilla'] = 389;
+    t['iacute'] = 278;
+    t['lozenge'] = 471;
+    t['Rcaron'] = 611;
+    t['Gcommaaccent'] = 722;
+    t['ucircumflex'] = 500;
+    t['acircumflex'] = 500;
+    t['Amacron'] = 611;
+    t['rcaron'] = 389;
+    t['ccedilla'] = 444;
+    t['Zdotaccent'] = 556;
+    t['Thorn'] = 611;
+    t['Omacron'] = 722;
+    t['Racute'] = 611;
+    t['Sacute'] = 500;
+    t['dcaron'] = 544;
+    t['Umacron'] = 722;
+    t['uring'] = 500;
+    t['threesuperior'] = 300;
+    t['Ograve'] = 722;
+    t['Agrave'] = 611;
+    t['Abreve'] = 611;
+    t['multiply'] = 675;
+    t['uacute'] = 500;
+    t['Tcaron'] = 556;
+    t['partialdiff'] = 476;
+    t['ydieresis'] = 444;
+    t['Nacute'] = 667;
+    t['icircumflex'] = 278;
+    t['Ecircumflex'] = 611;
+    t['adieresis'] = 500;
+    t['edieresis'] = 444;
+    t['cacute'] = 444;
+    t['nacute'] = 500;
+    t['umacron'] = 500;
+    t['Ncaron'] = 667;
+    t['Iacute'] = 333;
+    t['plusminus'] = 675;
+    t['brokenbar'] = 275;
+    t['registered'] = 760;
+    t['Gbreve'] = 722;
+    t['Idotaccent'] = 333;
+    t['summation'] = 600;
+    t['Egrave'] = 611;
+    t['racute'] = 389;
+    t['omacron'] = 500;
+    t['Zacute'] = 556;
+    t['Zcaron'] = 556;
+    t['greaterequal'] = 549;
+    t['Eth'] = 722;
+    t['Ccedilla'] = 667;
+    t['lcommaaccent'] = 278;
+    t['tcaron'] = 300;
+    t['eogonek'] = 444;
+    t['Uogonek'] = 722;
+    t['Aacute'] = 611;
+    t['Adieresis'] = 611;
+    t['egrave'] = 444;
+    t['zacute'] = 389;
+    t['iogonek'] = 278;
+    t['Oacute'] = 722;
+    t['oacute'] = 500;
+    t['amacron'] = 500;
+    t['sacute'] = 389;
+    t['idieresis'] = 278;
+    t['Ocircumflex'] = 722;
+    t['Ugrave'] = 722;
+    t['Delta'] = 612;
+    t['thorn'] = 500;
+    t['twosuperior'] = 300;
+    t['Odieresis'] = 722;
+    t['mu'] = 500;
+    t['igrave'] = 278;
+    t['ohungarumlaut'] = 500;
+    t['Eogonek'] = 611;
+    t['dcroat'] = 500;
+    t['threequarters'] = 750;
+    t['Scedilla'] = 500;
+    t['lcaron'] = 300;
+    t['Kcommaaccent'] = 667;
+    t['Lacute'] = 556;
+    t['trademark'] = 980;
+    t['edotaccent'] = 444;
+    t['Igrave'] = 333;
+    t['Imacron'] = 333;
+    t['Lcaron'] = 611;
+    t['onehalf'] = 750;
+    t['lessequal'] = 549;
+    t['ocircumflex'] = 500;
+    t['ntilde'] = 500;
+    t['Uhungarumlaut'] = 722;
+    t['Eacute'] = 611;
+    t['emacron'] = 444;
+    t['gbreve'] = 500;
+    t['onequarter'] = 750;
+    t['Scaron'] = 500;
+    t['Scommaaccent'] = 500;
+    t['Ohungarumlaut'] = 722;
+    t['degree'] = 400;
+    t['ograve'] = 500;
+    t['Ccaron'] = 667;
+    t['ugrave'] = 500;
+    t['radical'] = 453;
+    t['Dcaron'] = 722;
+    t['rcommaaccent'] = 389;
+    t['Ntilde'] = 667;
+    t['otilde'] = 500;
+    t['Rcommaaccent'] = 611;
+    t['Lcommaaccent'] = 556;
+    t['Atilde'] = 611;
+    t['Aogonek'] = 611;
+    t['Aring'] = 611;
+    t['Otilde'] = 722;
+    t['zdotaccent'] = 389;
+    t['Ecaron'] = 611;
+    t['Iogonek'] = 333;
+    t['kcommaaccent'] = 444;
+    t['minus'] = 675;
+    t['Icircumflex'] = 333;
+    t['ncaron'] = 500;
+    t['tcommaaccent'] = 278;
+    t['logicalnot'] = 675;
+    t['odieresis'] = 500;
+    t['udieresis'] = 500;
+    t['notequal'] = 549;
+    t['gcommaaccent'] = 500;
+    t['eth'] = 500;
+    t['zcaron'] = 389;
+    t['ncommaaccent'] = 500;
+    t['onesuperior'] = 300;
+    t['imacron'] = 278;
+    t['Euro'] = 500;
+  });
+  t['ZapfDingbats'] = (0, _core_utils.getLookupTableFactory)(function (t) {
+    t['space'] = 278;
+    t['a1'] = 974;
+    t['a2'] = 961;
+    t['a202'] = 974;
+    t['a3'] = 980;
+    t['a4'] = 719;
+    t['a5'] = 789;
+    t['a119'] = 790;
+    t['a118'] = 791;
+    t['a117'] = 690;
+    t['a11'] = 960;
+    t['a12'] = 939;
+    t['a13'] = 549;
+    t['a14'] = 855;
+    t['a15'] = 911;
+    t['a16'] = 933;
+    t['a105'] = 911;
+    t['a17'] = 945;
+    t['a18'] = 974;
+    t['a19'] = 755;
+    t['a20'] = 846;
+    t['a21'] = 762;
+    t['a22'] = 761;
+    t['a23'] = 571;
+    t['a24'] = 677;
+    t['a25'] = 763;
+    t['a26'] = 760;
+    t['a27'] = 759;
+    t['a28'] = 754;
+    t['a6'] = 494;
+    t['a7'] = 552;
+    t['a8'] = 537;
+    t['a9'] = 577;
+    t['a10'] = 692;
+    t['a29'] = 786;
+    t['a30'] = 788;
+    t['a31'] = 788;
+    t['a32'] = 790;
+    t['a33'] = 793;
+    t['a34'] = 794;
+    t['a35'] = 816;
+    t['a36'] = 823;
+    t['a37'] = 789;
+    t['a38'] = 841;
+    t['a39'] = 823;
+    t['a40'] = 833;
+    t['a41'] = 816;
+    t['a42'] = 831;
+    t['a43'] = 923;
+    t['a44'] = 744;
+    t['a45'] = 723;
+    t['a46'] = 749;
+    t['a47'] = 790;
+    t['a48'] = 792;
+    t['a49'] = 695;
+    t['a50'] = 776;
+    t['a51'] = 768;
+    t['a52'] = 792;
+    t['a53'] = 759;
+    t['a54'] = 707;
+    t['a55'] = 708;
+    t['a56'] = 682;
+    t['a57'] = 701;
+    t['a58'] = 826;
+    t['a59'] = 815;
+    t['a60'] = 789;
+    t['a61'] = 789;
+    t['a62'] = 707;
+    t['a63'] = 687;
+    t['a64'] = 696;
+    t['a65'] = 689;
+    t['a66'] = 786;
+    t['a67'] = 787;
+    t['a68'] = 713;
+    t['a69'] = 791;
+    t['a70'] = 785;
+    t['a71'] = 791;
+    t['a72'] = 873;
+    t['a73'] = 761;
+    t['a74'] = 762;
+    t['a203'] = 762;
+    t['a75'] = 759;
+    t['a204'] = 759;
+    t['a76'] = 892;
+    t['a77'] = 892;
+    t['a78'] = 788;
+    t['a79'] = 784;
+    t['a81'] = 438;
+    t['a82'] = 138;
+    t['a83'] = 277;
+    t['a84'] = 415;
+    t['a97'] = 392;
+    t['a98'] = 392;
+    t['a99'] = 668;
+    t['a100'] = 668;
+    t['a89'] = 390;
+    t['a90'] = 390;
+    t['a93'] = 317;
+    t['a94'] = 317;
+    t['a91'] = 276;
+    t['a92'] = 276;
+    t['a205'] = 509;
+    t['a85'] = 509;
+    t['a206'] = 410;
+    t['a86'] = 410;
+    t['a87'] = 234;
+    t['a88'] = 234;
+    t['a95'] = 334;
+    t['a96'] = 334;
+    t['a101'] = 732;
+    t['a102'] = 544;
+    t['a103'] = 544;
+    t['a104'] = 910;
+    t['a106'] = 667;
+    t['a107'] = 760;
+    t['a108'] = 760;
+    t['a112'] = 776;
+    t['a111'] = 595;
+    t['a110'] = 694;
+    t['a109'] = 626;
+    t['a120'] = 788;
+    t['a121'] = 788;
+    t['a122'] = 788;
+    t['a123'] = 788;
+    t['a124'] = 788;
+    t['a125'] = 788;
+    t['a126'] = 788;
+    t['a127'] = 788;
+    t['a128'] = 788;
+    t['a129'] = 788;
+    t['a130'] = 788;
+    t['a131'] = 788;
+    t['a132'] = 788;
+    t['a133'] = 788;
+    t['a134'] = 788;
+    t['a135'] = 788;
+    t['a136'] = 788;
+    t['a137'] = 788;
+    t['a138'] = 788;
+    t['a139'] = 788;
+    t['a140'] = 788;
+    t['a141'] = 788;
+    t['a142'] = 788;
+    t['a143'] = 788;
+    t['a144'] = 788;
+    t['a145'] = 788;
+    t['a146'] = 788;
+    t['a147'] = 788;
+    t['a148'] = 788;
+    t['a149'] = 788;
+    t['a150'] = 788;
+    t['a151'] = 788;
+    t['a152'] = 788;
+    t['a153'] = 788;
+    t['a154'] = 788;
+    t['a155'] = 788;
+    t['a156'] = 788;
+    t['a157'] = 788;
+    t['a158'] = 788;
+    t['a159'] = 788;
+    t['a160'] = 894;
+    t['a161'] = 838;
+    t['a163'] = 1016;
+    t['a164'] = 458;
+    t['a196'] = 748;
+    t['a165'] = 924;
+    t['a192'] = 748;
+    t['a166'] = 918;
+    t['a167'] = 927;
+    t['a168'] = 928;
+    t['a169'] = 928;
+    t['a170'] = 834;
+    t['a171'] = 873;
+    t['a172'] = 828;
+    t['a173'] = 924;
+    t['a162'] = 924;
+    t['a174'] = 917;
+    t['a175'] = 930;
+    t['a176'] = 931;
+    t['a177'] = 463;
+    t['a178'] = 883;
+    t['a179'] = 836;
+    t['a193'] = 836;
+    t['a180'] = 867;
+    t['a199'] = 867;
+    t['a181'] = 696;
+    t['a200'] = 696;
+    t['a182'] = 874;
+    t['a201'] = 874;
+    t['a183'] = 760;
+    t['a184'] = 946;
+    t['a197'] = 771;
+    t['a185'] = 865;
+    t['a194'] = 771;
+    t['a198'] = 888;
+    t['a186'] = 967;
+    t['a195'] = 888;
+    t['a187'] = 831;
+    t['a188'] = 873;
+    t['a189'] = 927;
+    t['a190'] = 970;
+    t['a191'] = 918;
+  });
+});
+exports.getMetrics = getMetrics;
+
+/***/ }),
+/* 186 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.isPDFFunction = isPDFFunction;
+exports.PostScriptCompiler = exports.PostScriptEvaluator = exports.PDFFunctionFactory = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _ps_parser = __w_pdfjs_require__(187);
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var IsEvalSupportedCached = {
+  get value() {
+    return (0, _util.shadow)(this, 'value', (0, _util.isEvalSupported)());
+  }
+
+};
+
+var PDFFunctionFactory =
+/*#__PURE__*/
+function () {
+  function PDFFunctionFactory(_ref) {
+    var xref = _ref.xref,
+        _ref$isEvalSupported = _ref.isEvalSupported,
+        isEvalSupported = _ref$isEvalSupported === void 0 ? true : _ref$isEvalSupported;
+
+    _classCallCheck(this, PDFFunctionFactory);
+
+    this.xref = xref;
+    this.isEvalSupported = isEvalSupported !== false;
+  }
+
+  _createClass(PDFFunctionFactory, [{
+    key: "create",
+    value: function create(fn) {
+      return PDFFunction.parse({
+        xref: this.xref,
+        isEvalSupported: this.isEvalSupported,
+        fn: fn
+      });
+    }
+  }, {
+    key: "createFromArray",
+    value: function createFromArray(fnObj) {
+      return PDFFunction.parseArray({
+        xref: this.xref,
+        isEvalSupported: this.isEvalSupported,
+        fnObj: fnObj
+      });
+    }
+  }]);
+
+  return PDFFunctionFactory;
+}();
+
+exports.PDFFunctionFactory = PDFFunctionFactory;
+
+function toNumberArray(arr) {
+  if (!Array.isArray(arr)) {
+    return null;
+  }
+
+  var length = arr.length;
+
+  for (var i = 0; i < length; i++) {
+    if (typeof arr[i] !== 'number') {
+      var result = new Array(length);
+
+      for (var _i = 0; _i < length; _i++) {
+        result[_i] = +arr[_i];
+      }
+
+      return result;
+    }
+  }
+
+  return arr;
+}
+
+var PDFFunction = function PDFFunctionClosure() {
+  var CONSTRUCT_SAMPLED = 0;
+  var CONSTRUCT_INTERPOLATED = 2;
+  var CONSTRUCT_STICHED = 3;
+  var CONSTRUCT_POSTSCRIPT = 4;
+  return {
+    getSampleArray: function getSampleArray(size, outputSize, bps, stream) {
+      var i, ii;
+      var length = 1;
+
+      for (i = 0, ii = size.length; i < ii; i++) {
+        length *= size[i];
+      }
+
+      length *= outputSize;
+      var array = new Array(length);
+      var codeSize = 0;
+      var codeBuf = 0;
+      var sampleMul = 1.0 / (Math.pow(2.0, bps) - 1);
+      var strBytes = stream.getBytes((length * bps + 7) / 8);
+      var strIdx = 0;
+
+      for (i = 0; i < length; i++) {
+        while (codeSize < bps) {
+          codeBuf <<= 8;
+          codeBuf |= strBytes[strIdx++];
+          codeSize += 8;
+        }
+
+        codeSize -= bps;
+        array[i] = (codeBuf >> codeSize) * sampleMul;
+        codeBuf &= (1 << codeSize) - 1;
+      }
+
+      return array;
+    },
+    getIR: function getIR(_ref2) {
+      var xref = _ref2.xref,
+          isEvalSupported = _ref2.isEvalSupported,
+          fn = _ref2.fn;
+      var dict = fn.dict;
+
+      if (!dict) {
+        dict = fn;
+      }
+
+      var types = [this.constructSampled, null, this.constructInterpolated, this.constructStiched, this.constructPostScript];
+      var typeNum = dict.get('FunctionType');
+      var typeFn = types[typeNum];
+
+      if (!typeFn) {
+        throw new _util.FormatError('Unknown type of function');
+      }
+
+      return typeFn.call(this, {
+        xref: xref,
+        isEvalSupported: isEvalSupported,
+        fn: fn,
+        dict: dict
+      });
+    },
+    fromIR: function fromIR(_ref3) {
+      var xref = _ref3.xref,
+          isEvalSupported = _ref3.isEvalSupported,
+          IR = _ref3.IR;
+      var type = IR[0];
+
+      switch (type) {
+        case CONSTRUCT_SAMPLED:
+          return this.constructSampledFromIR({
+            xref: xref,
+            isEvalSupported: isEvalSupported,
+            IR: IR
+          });
+
+        case CONSTRUCT_INTERPOLATED:
+          return this.constructInterpolatedFromIR({
+            xref: xref,
+            isEvalSupported: isEvalSupported,
+            IR: IR
+          });
+
+        case CONSTRUCT_STICHED:
+          return this.constructStichedFromIR({
+            xref: xref,
+            isEvalSupported: isEvalSupported,
+            IR: IR
+          });
+
+        default:
+          return this.constructPostScriptFromIR({
+            xref: xref,
+            isEvalSupported: isEvalSupported,
+            IR: IR
+          });
+      }
+    },
+    parse: function parse(_ref4) {
+      var xref = _ref4.xref,
+          isEvalSupported = _ref4.isEvalSupported,
+          fn = _ref4.fn;
+      var IR = this.getIR({
+        xref: xref,
+        isEvalSupported: isEvalSupported,
+        fn: fn
+      });
+      return this.fromIR({
+        xref: xref,
+        isEvalSupported: isEvalSupported,
+        IR: IR
+      });
+    },
+    parseArray: function parseArray(_ref5) {
+      var xref = _ref5.xref,
+          isEvalSupported = _ref5.isEvalSupported,
+          fnObj = _ref5.fnObj;
+
+      if (!Array.isArray(fnObj)) {
+        return this.parse({
+          xref: xref,
+          isEvalSupported: isEvalSupported,
+          fn: fnObj
+        });
+      }
+
+      var fnArray = [];
+
+      for (var j = 0, jj = fnObj.length; j < jj; j++) {
+        fnArray.push(this.parse({
+          xref: xref,
+          isEvalSupported: isEvalSupported,
+          fn: xref.fetchIfRef(fnObj[j])
+        }));
+      }
+
+      return function (src, srcOffset, dest, destOffset) {
+        for (var i = 0, ii = fnArray.length; i < ii; i++) {
+          fnArray[i](src, srcOffset, dest, destOffset + i);
+        }
+      };
+    },
+    constructSampled: function constructSampled(_ref6) {
+      var xref = _ref6.xref,
+          isEvalSupported = _ref6.isEvalSupported,
+          fn = _ref6.fn,
+          dict = _ref6.dict;
+
+      function toMultiArray(arr) {
+        var inputLength = arr.length;
+        var out = [];
+        var index = 0;
+
+        for (var i = 0; i < inputLength; i += 2) {
+          out[index] = [arr[i], arr[i + 1]];
+          ++index;
+        }
+
+        return out;
+      }
+
+      var domain = toNumberArray(dict.getArray('Domain'));
+      var range = toNumberArray(dict.getArray('Range'));
+
+      if (!domain || !range) {
+        throw new _util.FormatError('No domain or range');
+      }
+
+      var inputSize = domain.length / 2;
+      var outputSize = range.length / 2;
+      domain = toMultiArray(domain);
+      range = toMultiArray(range);
+      var size = toNumberArray(dict.getArray('Size'));
+      var bps = dict.get('BitsPerSample');
+      var order = dict.get('Order') || 1;
+
+      if (order !== 1) {
+        (0, _util.info)('No support for cubic spline interpolation: ' + order);
+      }
+
+      var encode = toNumberArray(dict.getArray('Encode'));
+
+      if (!encode) {
+        encode = [];
+
+        for (var i = 0; i < inputSize; ++i) {
+          encode.push([0, size[i] - 1]);
+        }
+      } else {
+        encode = toMultiArray(encode);
+      }
+
+      var decode = toNumberArray(dict.getArray('Decode'));
+
+      if (!decode) {
+        decode = range;
+      } else {
+        decode = toMultiArray(decode);
+      }
+
+      var samples = this.getSampleArray(size, outputSize, bps, fn);
+      return [CONSTRUCT_SAMPLED, inputSize, domain, encode, decode, samples, size, outputSize, Math.pow(2, bps) - 1, range];
+    },
+    constructSampledFromIR: function constructSampledFromIR(_ref7) {
+      var xref = _ref7.xref,
+          isEvalSupported = _ref7.isEvalSupported,
+          IR = _ref7.IR;
+
+      function interpolate(x, xmin, xmax, ymin, ymax) {
+        return ymin + (x - xmin) * ((ymax - ymin) / (xmax - xmin));
+      }
+
+      return function constructSampledFromIRResult(src, srcOffset, dest, destOffset) {
+        var m = IR[1];
+        var domain = IR[2];
+        var encode = IR[3];
+        var decode = IR[4];
+        var samples = IR[5];
+        var size = IR[6];
+        var n = IR[7];
+        var range = IR[9];
+        var cubeVertices = 1 << m;
+        var cubeN = new Float64Array(cubeVertices);
+        var cubeVertex = new Uint32Array(cubeVertices);
+        var i, j;
+
+        for (j = 0; j < cubeVertices; j++) {
+          cubeN[j] = 1;
+        }
+
+        var k = n,
+            pos = 1;
+
+        for (i = 0; i < m; ++i) {
+          var domain_2i = domain[i][0];
+          var domain_2i_1 = domain[i][1];
+          var xi = Math.min(Math.max(src[srcOffset + i], domain_2i), domain_2i_1);
+          var e = interpolate(xi, domain_2i, domain_2i_1, encode[i][0], encode[i][1]);
+          var size_i = size[i];
+          e = Math.min(Math.max(e, 0), size_i - 1);
+          var e0 = e < size_i - 1 ? Math.floor(e) : e - 1;
+          var n0 = e0 + 1 - e;
+          var n1 = e - e0;
+          var offset0 = e0 * k;
+          var offset1 = offset0 + k;
+
+          for (j = 0; j < cubeVertices; j++) {
+            if (j & pos) {
+              cubeN[j] *= n1;
+              cubeVertex[j] += offset1;
+            } else {
+              cubeN[j] *= n0;
+              cubeVertex[j] += offset0;
+            }
+          }
+
+          k *= size_i;
+          pos <<= 1;
+        }
+
+        for (j = 0; j < n; ++j) {
+          var rj = 0;
+
+          for (i = 0; i < cubeVertices; i++) {
+            rj += samples[cubeVertex[i] + j] * cubeN[i];
+          }
+
+          rj = interpolate(rj, 0, 1, decode[j][0], decode[j][1]);
+          dest[destOffset + j] = Math.min(Math.max(rj, range[j][0]), range[j][1]);
+        }
+      };
+    },
+    constructInterpolated: function constructInterpolated(_ref8) {
+      var xref = _ref8.xref,
+          isEvalSupported = _ref8.isEvalSupported,
+          fn = _ref8.fn,
+          dict = _ref8.dict;
+      var c0 = toNumberArray(dict.getArray('C0')) || [0];
+      var c1 = toNumberArray(dict.getArray('C1')) || [1];
+      var n = dict.get('N');
+      var length = c0.length;
+      var diff = [];
+
+      for (var i = 0; i < length; ++i) {
+        diff.push(c1[i] - c0[i]);
+      }
+
+      return [CONSTRUCT_INTERPOLATED, c0, diff, n];
+    },
+    constructInterpolatedFromIR: function constructInterpolatedFromIR(_ref9) {
+      var xref = _ref9.xref,
+          isEvalSupported = _ref9.isEvalSupported,
+          IR = _ref9.IR;
+      var c0 = IR[1];
+      var diff = IR[2];
+      var n = IR[3];
+      var length = diff.length;
+      return function constructInterpolatedFromIRResult(src, srcOffset, dest, destOffset) {
+        var x = n === 1 ? src[srcOffset] : Math.pow(src[srcOffset], n);
+
+        for (var j = 0; j < length; ++j) {
+          dest[destOffset + j] = c0[j] + x * diff[j];
+        }
+      };
+    },
+    constructStiched: function constructStiched(_ref10) {
+      var xref = _ref10.xref,
+          isEvalSupported = _ref10.isEvalSupported,
+          fn = _ref10.fn,
+          dict = _ref10.dict;
+      var domain = toNumberArray(dict.getArray('Domain'));
+
+      if (!domain) {
+        throw new _util.FormatError('No domain');
+      }
+
+      var inputSize = domain.length / 2;
+
+      if (inputSize !== 1) {
+        throw new _util.FormatError('Bad domain for stiched function');
+      }
+
+      var fnRefs = dict.get('Functions');
+      var fns = [];
+
+      for (var i = 0, ii = fnRefs.length; i < ii; ++i) {
+        fns.push(this.parse({
+          xref: xref,
+          isEvalSupported: isEvalSupported,
+          fn: xref.fetchIfRef(fnRefs[i])
+        }));
+      }
+
+      var bounds = toNumberArray(dict.getArray('Bounds'));
+      var encode = toNumberArray(dict.getArray('Encode'));
+      return [CONSTRUCT_STICHED, domain, bounds, encode, fns];
+    },
+    constructStichedFromIR: function constructStichedFromIR(_ref11) {
+      var xref = _ref11.xref,
+          isEvalSupported = _ref11.isEvalSupported,
+          IR = _ref11.IR;
+      var domain = IR[1];
+      var bounds = IR[2];
+      var encode = IR[3];
+      var fns = IR[4];
+      var tmpBuf = new Float32Array(1);
+      return function constructStichedFromIRResult(src, srcOffset, dest, destOffset) {
+        var clip = function constructStichedFromIRClip(v, min, max) {
+          if (v > max) {
+            v = max;
+          } else if (v < min) {
+            v = min;
+          }
+
+          return v;
+        };
+
+        var v = clip(src[srcOffset], domain[0], domain[1]);
+
+        for (var i = 0, ii = bounds.length; i < ii; ++i) {
+          if (v < bounds[i]) {
+            break;
+          }
+        }
+
+        var dmin = domain[0];
+
+        if (i > 0) {
+          dmin = bounds[i - 1];
+        }
+
+        var dmax = domain[1];
+
+        if (i < bounds.length) {
+          dmax = bounds[i];
+        }
+
+        var rmin = encode[2 * i];
+        var rmax = encode[2 * i + 1];
+        tmpBuf[0] = dmin === dmax ? rmin : rmin + (v - dmin) * (rmax - rmin) / (dmax - dmin);
+        fns[i](tmpBuf, 0, dest, destOffset);
+      };
+    },
+    constructPostScript: function constructPostScript(_ref12) {
+      var xref = _ref12.xref,
+          isEvalSupported = _ref12.isEvalSupported,
+          fn = _ref12.fn,
+          dict = _ref12.dict;
+      var domain = toNumberArray(dict.getArray('Domain'));
+      var range = toNumberArray(dict.getArray('Range'));
+
+      if (!domain) {
+        throw new _util.FormatError('No domain.');
+      }
+
+      if (!range) {
+        throw new _util.FormatError('No range.');
+      }
+
+      var lexer = new _ps_parser.PostScriptLexer(fn);
+      var parser = new _ps_parser.PostScriptParser(lexer);
+      var code = parser.parse();
+      return [CONSTRUCT_POSTSCRIPT, domain, range, code];
+    },
+    constructPostScriptFromIR: function constructPostScriptFromIR(_ref13) {
+      var xref = _ref13.xref,
+          isEvalSupported = _ref13.isEvalSupported,
+          IR = _ref13.IR;
+      var domain = IR[1];
+      var range = IR[2];
+      var code = IR[3];
+
+      if (isEvalSupported && IsEvalSupportedCached.value) {
+        var compiled = new PostScriptCompiler().compile(code, domain, range);
+
+        if (compiled) {
+          return new Function('src', 'srcOffset', 'dest', 'destOffset', compiled);
+        }
+      }
+
+      (0, _util.info)('Unable to compile PS function');
+      var numOutputs = range.length >> 1;
+      var numInputs = domain.length >> 1;
+      var evaluator = new PostScriptEvaluator(code);
+      var cache = Object.create(null);
+      var MAX_CACHE_SIZE = 2048 * 4;
+      var cache_available = MAX_CACHE_SIZE;
+      var tmpBuf = new Float32Array(numInputs);
+      return function constructPostScriptFromIRResult(src, srcOffset, dest, destOffset) {
+        var i, value;
+        var key = '';
+        var input = tmpBuf;
+
+        for (i = 0; i < numInputs; i++) {
+          value = src[srcOffset + i];
+          input[i] = value;
+          key += value + '_';
+        }
+
+        var cachedValue = cache[key];
+
+        if (cachedValue !== undefined) {
+          dest.set(cachedValue, destOffset);
+          return;
+        }
+
+        var output = new Float32Array(numOutputs);
+        var stack = evaluator.execute(input);
+        var stackIndex = stack.length - numOutputs;
+
+        for (i = 0; i < numOutputs; i++) {
+          value = stack[stackIndex + i];
+          var bound = range[i * 2];
+
+          if (value < bound) {
+            value = bound;
+          } else {
+            bound = range[i * 2 + 1];
+
+            if (value > bound) {
+              value = bound;
+            }
+          }
+
+          output[i] = value;
+        }
+
+        if (cache_available > 0) {
+          cache_available--;
+          cache[key] = output;
+        }
+
+        dest.set(output, destOffset);
+      };
+    }
+  };
+}();
+
+function isPDFFunction(v) {
+  var fnDict;
+
+  if (_typeof(v) !== 'object') {
+    return false;
+  } else if ((0, _primitives.isDict)(v)) {
+    fnDict = v;
+  } else if ((0, _primitives.isStream)(v)) {
+    fnDict = v.dict;
+  } else {
+    return false;
+  }
+
+  return fnDict.has('FunctionType');
+}
+
+var PostScriptStack = function PostScriptStackClosure() {
+  var MAX_STACK_SIZE = 100;
+
+  function PostScriptStack(initialStack) {
+    this.stack = !initialStack ? [] : Array.prototype.slice.call(initialStack, 0);
+  }
+
+  PostScriptStack.prototype = {
+    push: function PostScriptStack_push(value) {
+      if (this.stack.length >= MAX_STACK_SIZE) {
+        throw new Error('PostScript function stack overflow.');
+      }
+
+      this.stack.push(value);
+    },
+    pop: function PostScriptStack_pop() {
+      if (this.stack.length <= 0) {
+        throw new Error('PostScript function stack underflow.');
+      }
+
+      return this.stack.pop();
+    },
+    copy: function PostScriptStack_copy(n) {
+      if (this.stack.length + n >= MAX_STACK_SIZE) {
+        throw new Error('PostScript function stack overflow.');
+      }
+
+      var stack = this.stack;
+
+      for (var i = stack.length - n, j = n - 1; j >= 0; j--, i++) {
+        stack.push(stack[i]);
+      }
+    },
+    index: function PostScriptStack_index(n) {
+      this.push(this.stack[this.stack.length - n - 1]);
+    },
+    roll: function PostScriptStack_roll(n, p) {
+      var stack = this.stack;
+      var l = stack.length - n;
+      var r = stack.length - 1,
+          c = l + (p - Math.floor(p / n) * n),
+          i,
+          j,
+          t;
+
+      for (i = l, j = r; i < j; i++, j--) {
+        t = stack[i];
+        stack[i] = stack[j];
+        stack[j] = t;
+      }
+
+      for (i = l, j = c - 1; i < j; i++, j--) {
+        t = stack[i];
+        stack[i] = stack[j];
+        stack[j] = t;
+      }
+
+      for (i = c, j = r; i < j; i++, j--) {
+        t = stack[i];
+        stack[i] = stack[j];
+        stack[j] = t;
+      }
+    }
+  };
+  return PostScriptStack;
+}();
+
+var PostScriptEvaluator = function PostScriptEvaluatorClosure() {
+  function PostScriptEvaluator(operators) {
+    this.operators = operators;
+  }
+
+  PostScriptEvaluator.prototype = {
+    execute: function PostScriptEvaluator_execute(initialStack) {
+      var stack = new PostScriptStack(initialStack);
+      var counter = 0;
+      var operators = this.operators;
+      var length = operators.length;
+      var operator, a, b;
+
+      while (counter < length) {
+        operator = operators[counter++];
+
+        if (typeof operator === 'number') {
+          stack.push(operator);
+          continue;
+        }
+
+        switch (operator) {
+          case 'jz':
+            b = stack.pop();
+            a = stack.pop();
+
+            if (!a) {
+              counter = b;
+            }
+
+            break;
+
+          case 'j':
+            a = stack.pop();
+            counter = a;
+            break;
+
+          case 'abs':
+            a = stack.pop();
+            stack.push(Math.abs(a));
+            break;
+
+          case 'add':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a + b);
+            break;
+
+          case 'and':
+            b = stack.pop();
+            a = stack.pop();
+
+            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
+              stack.push(a && b);
+            } else {
+              stack.push(a & b);
+            }
+
+            break;
+
+          case 'atan':
+            a = stack.pop();
+            stack.push(Math.atan(a));
+            break;
+
+          case 'bitshift':
+            b = stack.pop();
+            a = stack.pop();
+
+            if (a > 0) {
+              stack.push(a << b);
+            } else {
+              stack.push(a >> b);
+            }
+
+            break;
+
+          case 'ceiling':
+            a = stack.pop();
+            stack.push(Math.ceil(a));
+            break;
+
+          case 'copy':
+            a = stack.pop();
+            stack.copy(a);
+            break;
+
+          case 'cos':
+            a = stack.pop();
+            stack.push(Math.cos(a));
+            break;
+
+          case 'cvi':
+            a = stack.pop() | 0;
+            stack.push(a);
+            break;
+
+          case 'cvr':
+            break;
+
+          case 'div':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a / b);
+            break;
+
+          case 'dup':
+            stack.copy(1);
+            break;
+
+          case 'eq':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a === b);
+            break;
+
+          case 'exch':
+            stack.roll(2, 1);
+            break;
+
+          case 'exp':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(Math.pow(a, b));
+            break;
+
+          case 'false':
+            stack.push(false);
+            break;
+
+          case 'floor':
+            a = stack.pop();
+            stack.push(Math.floor(a));
+            break;
+
+          case 'ge':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a >= b);
+            break;
+
+          case 'gt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a > b);
+            break;
+
+          case 'idiv':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a / b | 0);
+            break;
+
+          case 'index':
+            a = stack.pop();
+            stack.index(a);
+            break;
+
+          case 'le':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a <= b);
+            break;
+
+          case 'ln':
+            a = stack.pop();
+            stack.push(Math.log(a));
+            break;
+
+          case 'log':
+            a = stack.pop();
+            stack.push(Math.log(a) / Math.LN10);
+            break;
+
+          case 'lt':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a < b);
+            break;
+
+          case 'mod':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a % b);
+            break;
+
+          case 'mul':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a * b);
+            break;
+
+          case 'ne':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a !== b);
+            break;
+
+          case 'neg':
+            a = stack.pop();
+            stack.push(-a);
+            break;
+
+          case 'not':
+            a = stack.pop();
+
+            if ((0, _util.isBool)(a)) {
+              stack.push(!a);
+            } else {
+              stack.push(~a);
+            }
+
+            break;
+
+          case 'or':
+            b = stack.pop();
+            a = stack.pop();
+
+            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
+              stack.push(a || b);
+            } else {
+              stack.push(a | b);
+            }
+
+            break;
+
+          case 'pop':
+            stack.pop();
+            break;
+
+          case 'roll':
+            b = stack.pop();
+            a = stack.pop();
+            stack.roll(a, b);
+            break;
+
+          case 'round':
+            a = stack.pop();
+            stack.push(Math.round(a));
+            break;
+
+          case 'sin':
+            a = stack.pop();
+            stack.push(Math.sin(a));
+            break;
+
+          case 'sqrt':
+            a = stack.pop();
+            stack.push(Math.sqrt(a));
+            break;
+
+          case 'sub':
+            b = stack.pop();
+            a = stack.pop();
+            stack.push(a - b);
+            break;
+
+          case 'true':
+            stack.push(true);
+            break;
+
+          case 'truncate':
+            a = stack.pop();
+            a = a < 0 ? Math.ceil(a) : Math.floor(a);
+            stack.push(a);
+            break;
+
+          case 'xor':
+            b = stack.pop();
+            a = stack.pop();
+
+            if ((0, _util.isBool)(a) && (0, _util.isBool)(b)) {
+              stack.push(a !== b);
+            } else {
+              stack.push(a ^ b);
+            }
+
+            break;
+
+          default:
+            throw new _util.FormatError("Unknown operator ".concat(operator));
+        }
+      }
+
+      return stack.stack;
+    }
+  };
+  return PostScriptEvaluator;
+}();
+
+exports.PostScriptEvaluator = PostScriptEvaluator;
+
+var PostScriptCompiler = function PostScriptCompilerClosure() {
+  function AstNode(type) {
+    this.type = type;
+  }
+
+  AstNode.prototype.visit = function (visitor) {
+    (0, _util.unreachable)('abstract method');
+  };
+
+  function AstArgument(index, min, max) {
+    AstNode.call(this, 'args');
+    this.index = index;
+    this.min = min;
+    this.max = max;
+  }
+
+  AstArgument.prototype = Object.create(AstNode.prototype);
+
+  AstArgument.prototype.visit = function (visitor) {
+    visitor.visitArgument(this);
+  };
+
+  function AstLiteral(number) {
+    AstNode.call(this, 'literal');
+    this.number = number;
+    this.min = number;
+    this.max = number;
+  }
+
+  AstLiteral.prototype = Object.create(AstNode.prototype);
+
+  AstLiteral.prototype.visit = function (visitor) {
+    visitor.visitLiteral(this);
+  };
+
+  function AstBinaryOperation(op, arg1, arg2, min, max) {
+    AstNode.call(this, 'binary');
+    this.op = op;
+    this.arg1 = arg1;
+    this.arg2 = arg2;
+    this.min = min;
+    this.max = max;
+  }
+
+  AstBinaryOperation.prototype = Object.create(AstNode.prototype);
+
+  AstBinaryOperation.prototype.visit = function (visitor) {
+    visitor.visitBinaryOperation(this);
+  };
+
+  function AstMin(arg, max) {
+    AstNode.call(this, 'max');
+    this.arg = arg;
+    this.min = arg.min;
+    this.max = max;
+  }
+
+  AstMin.prototype = Object.create(AstNode.prototype);
+
+  AstMin.prototype.visit = function (visitor) {
+    visitor.visitMin(this);
+  };
+
+  function AstVariable(index, min, max) {
+    AstNode.call(this, 'var');
+    this.index = index;
+    this.min = min;
+    this.max = max;
+  }
+
+  AstVariable.prototype = Object.create(AstNode.prototype);
+
+  AstVariable.prototype.visit = function (visitor) {
+    visitor.visitVariable(this);
+  };
+
+  function AstVariableDefinition(variable, arg) {
+    AstNode.call(this, 'definition');
+    this.variable = variable;
+    this.arg = arg;
+  }
+
+  AstVariableDefinition.prototype = Object.create(AstNode.prototype);
+
+  AstVariableDefinition.prototype.visit = function (visitor) {
+    visitor.visitVariableDefinition(this);
+  };
+
+  function ExpressionBuilderVisitor() {
+    this.parts = [];
+  }
+
+  ExpressionBuilderVisitor.prototype = {
+    visitArgument: function visitArgument(arg) {
+      this.parts.push('Math.max(', arg.min, ', Math.min(', arg.max, ', src[srcOffset + ', arg.index, ']))');
+    },
+    visitVariable: function visitVariable(variable) {
+      this.parts.push('v', variable.index);
+    },
+    visitLiteral: function visitLiteral(literal) {
+      this.parts.push(literal.number);
+    },
+    visitBinaryOperation: function visitBinaryOperation(operation) {
+      this.parts.push('(');
+      operation.arg1.visit(this);
+      this.parts.push(' ', operation.op, ' ');
+      operation.arg2.visit(this);
+      this.parts.push(')');
+    },
+    visitVariableDefinition: function visitVariableDefinition(definition) {
+      this.parts.push('var ');
+      definition.variable.visit(this);
+      this.parts.push(' = ');
+      definition.arg.visit(this);
+      this.parts.push(';');
+    },
+    visitMin: function visitMin(max) {
+      this.parts.push('Math.min(');
+      max.arg.visit(this);
+      this.parts.push(', ', max.max, ')');
+    },
+    toString: function toString() {
+      return this.parts.join('');
+    }
+  };
+
+  function buildAddOperation(num1, num2) {
+    if (num2.type === 'literal' && num2.number === 0) {
+      return num1;
+    }
+
+    if (num1.type === 'literal' && num1.number === 0) {
+      return num2;
+    }
+
+    if (num2.type === 'literal' && num1.type === 'literal') {
+      return new AstLiteral(num1.number + num2.number);
+    }
+
+    return new AstBinaryOperation('+', num1, num2, num1.min + num2.min, num1.max + num2.max);
+  }
+
+  function buildMulOperation(num1, num2) {
+    if (num2.type === 'literal') {
+      if (num2.number === 0) {
+        return new AstLiteral(0);
+      } else if (num2.number === 1) {
+        return num1;
+      } else if (num1.type === 'literal') {
+        return new AstLiteral(num1.number * num2.number);
+      }
+    }
+
+    if (num1.type === 'literal') {
+      if (num1.number === 0) {
+        return new AstLiteral(0);
+      } else if (num1.number === 1) {
+        return num2;
+      }
+    }
+
+    var min = Math.min(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
+    var max = Math.max(num1.min * num2.min, num1.min * num2.max, num1.max * num2.min, num1.max * num2.max);
+    return new AstBinaryOperation('*', num1, num2, min, max);
+  }
+
+  function buildSubOperation(num1, num2) {
+    if (num2.type === 'literal') {
+      if (num2.number === 0) {
+        return num1;
+      } else if (num1.type === 'literal') {
+        return new AstLiteral(num1.number - num2.number);
+      }
+    }
+
+    if (num2.type === 'binary' && num2.op === '-' && num1.type === 'literal' && num1.number === 1 && num2.arg1.type === 'literal' && num2.arg1.number === 1) {
+      return num2.arg2;
+    }
+
+    return new AstBinaryOperation('-', num1, num2, num1.min - num2.max, num1.max - num2.min);
+  }
+
+  function buildMinOperation(num1, max) {
+    if (num1.min >= max) {
+      return new AstLiteral(max);
+    } else if (num1.max <= max) {
+      return num1;
+    }
+
+    return new AstMin(num1, max);
+  }
+
+  function PostScriptCompiler() {}
+
+  PostScriptCompiler.prototype = {
+    compile: function PostScriptCompiler_compile(code, domain, range) {
+      var stack = [];
+      var i, ii;
+      var instructions = [];
+      var inputSize = domain.length >> 1,
+          outputSize = range.length >> 1;
+      var lastRegister = 0;
+      var n, j;
+      var num1, num2, ast1, ast2, tmpVar, item;
+
+      for (i = 0; i < inputSize; i++) {
+        stack.push(new AstArgument(i, domain[i * 2], domain[i * 2 + 1]));
+      }
+
+      for (i = 0, ii = code.length; i < ii; i++) {
+        item = code[i];
+
+        if (typeof item === 'number') {
+          stack.push(new AstLiteral(item));
+          continue;
+        }
+
+        switch (item) {
+          case 'add':
+            if (stack.length < 2) {
+              return null;
+            }
+
+            num2 = stack.pop();
+            num1 = stack.pop();
+            stack.push(buildAddOperation(num1, num2));
+            break;
+
+          case 'cvr':
+            if (stack.length < 1) {
+              return null;
+            }
+
+            break;
+
+          case 'mul':
+            if (stack.length < 2) {
+              return null;
+            }
+
+            num2 = stack.pop();
+            num1 = stack.pop();
+            stack.push(buildMulOperation(num1, num2));
+            break;
+
+          case 'sub':
+            if (stack.length < 2) {
+              return null;
+            }
+
+            num2 = stack.pop();
+            num1 = stack.pop();
+            stack.push(buildSubOperation(num1, num2));
+            break;
+
+          case 'exch':
+            if (stack.length < 2) {
+              return null;
+            }
+
+            ast1 = stack.pop();
+            ast2 = stack.pop();
+            stack.push(ast1, ast2);
+            break;
+
+          case 'pop':
+            if (stack.length < 1) {
+              return null;
+            }
+
+            stack.pop();
+            break;
+
+          case 'index':
+            if (stack.length < 1) {
+              return null;
+            }
+
+            num1 = stack.pop();
+
+            if (num1.type !== 'literal') {
+              return null;
+            }
+
+            n = num1.number;
+
+            if (n < 0 || !Number.isInteger(n) || stack.length < n) {
+              return null;
+            }
+
+            ast1 = stack[stack.length - n - 1];
+
+            if (ast1.type === 'literal' || ast1.type === 'var') {
+              stack.push(ast1);
+              break;
+            }
+
+            tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
+            stack[stack.length - n - 1] = tmpVar;
+            stack.push(tmpVar);
+            instructions.push(new AstVariableDefinition(tmpVar, ast1));
+            break;
+
+          case 'dup':
+            if (stack.length < 1) {
+              return null;
+            }
+
+            if (typeof code[i + 1] === 'number' && code[i + 2] === 'gt' && code[i + 3] === i + 7 && code[i + 4] === 'jz' && code[i + 5] === 'pop' && code[i + 6] === code[i + 1]) {
+              num1 = stack.pop();
+              stack.push(buildMinOperation(num1, code[i + 1]));
+              i += 6;
+              break;
+            }
+
+            ast1 = stack[stack.length - 1];
+
+            if (ast1.type === 'literal' || ast1.type === 'var') {
+              stack.push(ast1);
+              break;
+            }
+
+            tmpVar = new AstVariable(lastRegister++, ast1.min, ast1.max);
+            stack[stack.length - 1] = tmpVar;
+            stack.push(tmpVar);
+            instructions.push(new AstVariableDefinition(tmpVar, ast1));
+            break;
+
+          case 'roll':
+            if (stack.length < 2) {
+              return null;
+            }
+
+            num2 = stack.pop();
+            num1 = stack.pop();
+
+            if (num2.type !== 'literal' || num1.type !== 'literal') {
+              return null;
+            }
+
+            j = num2.number;
+            n = num1.number;
+
+            if (n <= 0 || !Number.isInteger(n) || !Number.isInteger(j) || stack.length < n) {
+              return null;
+            }
+
+            j = (j % n + n) % n;
+
+            if (j === 0) {
+              break;
+            }
+
+            Array.prototype.push.apply(stack, stack.splice(stack.length - n, n - j));
+            break;
+
+          default:
+            return null;
+        }
+      }
+
+      if (stack.length !== outputSize) {
+        return null;
+      }
+
+      var result = [];
+      instructions.forEach(function (instruction) {
+        var statementBuilder = new ExpressionBuilderVisitor();
+        instruction.visit(statementBuilder);
+        result.push(statementBuilder.toString());
+      });
+      stack.forEach(function (expr, i) {
+        var statementBuilder = new ExpressionBuilderVisitor();
+        expr.visit(statementBuilder);
+        var min = range[i * 2],
+            max = range[i * 2 + 1];
+        var out = [statementBuilder.toString()];
+
+        if (min > expr.min) {
+          out.unshift('Math.max(', min, ', ');
+          out.push(')');
+        }
+
+        if (max < expr.max) {
+          out.unshift('Math.min(', max, ', ');
+          out.push(')');
+        }
+
+        out.unshift('dest[destOffset + ', i, '] = ');
+        out.push(';');
+        result.push(out.join(''));
+      });
+      return result.join('\n');
+    }
+  };
+  return PostScriptCompiler;
+}();
+
+exports.PostScriptCompiler = PostScriptCompiler;
+
+/***/ }),
+/* 187 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PostScriptParser = exports.PostScriptLexer = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var PostScriptParser =
+/*#__PURE__*/
+function () {
+  function PostScriptParser(lexer) {
+    _classCallCheck(this, PostScriptParser);
+
+    this.lexer = lexer;
+    this.operators = [];
+    this.token = null;
+    this.prev = null;
+  }
+
+  _createClass(PostScriptParser, [{
+    key: "nextToken",
+    value: function nextToken() {
+      this.prev = this.token;
+      this.token = this.lexer.getToken();
+    }
+  }, {
+    key: "accept",
+    value: function accept(type) {
+      if (this.token.type === type) {
+        this.nextToken();
+        return true;
+      }
+
+      return false;
+    }
+  }, {
+    key: "expect",
+    value: function expect(type) {
+      if (this.accept(type)) {
+        return true;
+      }
+
+      throw new _util.FormatError("Unexpected symbol: found ".concat(this.token.type, " expected ").concat(type, "."));
+    }
+  }, {
+    key: "parse",
+    value: function parse() {
+      this.nextToken();
+      this.expect(PostScriptTokenTypes.LBRACE);
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+      return this.operators;
+    }
+  }, {
+    key: "parseBlock",
+    value: function parseBlock() {
+      while (true) {
+        if (this.accept(PostScriptTokenTypes.NUMBER)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.OPERATOR)) {
+          this.operators.push(this.prev.value);
+        } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+          this.parseCondition();
+        } else {
+          return;
+        }
+      }
+    }
+  }, {
+    key: "parseCondition",
+    value: function parseCondition() {
+      var conditionLocation = this.operators.length;
+      this.operators.push(null, null);
+      this.parseBlock();
+      this.expect(PostScriptTokenTypes.RBRACE);
+
+      if (this.accept(PostScriptTokenTypes.IF)) {
+        this.operators[conditionLocation] = this.operators.length;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else if (this.accept(PostScriptTokenTypes.LBRACE)) {
+        var jumpLocation = this.operators.length;
+        this.operators.push(null, null);
+        var endOfTrue = this.operators.length;
+        this.parseBlock();
+        this.expect(PostScriptTokenTypes.RBRACE);
+        this.expect(PostScriptTokenTypes.IFELSE);
+        this.operators[jumpLocation] = this.operators.length;
+        this.operators[jumpLocation + 1] = 'j';
+        this.operators[conditionLocation] = endOfTrue;
+        this.operators[conditionLocation + 1] = 'jz';
+      } else {
+        throw new _util.FormatError('PS Function: error parsing conditional.');
+      }
+    }
+  }]);
+
+  return PostScriptParser;
+}();
+
+exports.PostScriptParser = PostScriptParser;
+var PostScriptTokenTypes = {
+  LBRACE: 0,
+  RBRACE: 1,
+  NUMBER: 2,
+  OPERATOR: 3,
+  IF: 4,
+  IFELSE: 5
+};
+
+var PostScriptToken = function PostScriptTokenClosure() {
+  var opCache = Object.create(null);
+
+  var PostScriptToken =
+  /*#__PURE__*/
+  function () {
+    function PostScriptToken(type, value) {
+      _classCallCheck(this, PostScriptToken);
+
+      this.type = type;
+      this.value = value;
+    }
+
+    _createClass(PostScriptToken, null, [{
+      key: "getOperator",
+      value: function getOperator(op) {
+        var opValue = opCache[op];
+
+        if (opValue) {
+          return opValue;
+        }
+
+        return opCache[op] = new PostScriptToken(PostScriptTokenTypes.OPERATOR, op);
+      }
+    }, {
+      key: "LBRACE",
+      get: function get() {
+        return (0, _util.shadow)(this, 'LBRACE', new PostScriptToken(PostScriptTokenTypes.LBRACE, '{'));
+      }
+    }, {
+      key: "RBRACE",
+      get: function get() {
+        return (0, _util.shadow)(this, 'RBRACE', new PostScriptToken(PostScriptTokenTypes.RBRACE, '}'));
+      }
+    }, {
+      key: "IF",
+      get: function get() {
+        return (0, _util.shadow)(this, 'IF', new PostScriptToken(PostScriptTokenTypes.IF, 'IF'));
+      }
+    }, {
+      key: "IFELSE",
+      get: function get() {
+        return (0, _util.shadow)(this, 'IFELSE', new PostScriptToken(PostScriptTokenTypes.IFELSE, 'IFELSE'));
+      }
+    }]);
+
+    return PostScriptToken;
+  }();
+
+  return PostScriptToken;
+}();
+
+var PostScriptLexer =
+/*#__PURE__*/
+function () {
+  function PostScriptLexer(stream) {
+    _classCallCheck(this, PostScriptLexer);
+
+    this.stream = stream;
+    this.nextChar();
+    this.strBuf = [];
+  }
+
+  _createClass(PostScriptLexer, [{
+    key: "nextChar",
+    value: function nextChar() {
+      return this.currentChar = this.stream.getByte();
+    }
+  }, {
+    key: "getToken",
+    value: function getToken() {
+      var comment = false;
+      var ch = this.currentChar;
+
+      while (true) {
+        if (ch < 0) {
+          return _primitives.EOF;
+        }
+
+        if (comment) {
+          if (ch === 0x0A || ch === 0x0D) {
+            comment = false;
+          }
+        } else if (ch === 0x25) {
+          comment = true;
+        } else if (!(0, _util.isSpace)(ch)) {
+          break;
+        }
+
+        ch = this.nextChar();
+      }
+
+      switch (ch | 0) {
+        case 0x30:
+        case 0x31:
+        case 0x32:
+        case 0x33:
+        case 0x34:
+        case 0x35:
+        case 0x36:
+        case 0x37:
+        case 0x38:
+        case 0x39:
+        case 0x2B:
+        case 0x2D:
+        case 0x2E:
+          return new PostScriptToken(PostScriptTokenTypes.NUMBER, this.getNumber());
+
+        case 0x7B:
+          this.nextChar();
+          return PostScriptToken.LBRACE;
+
+        case 0x7D:
+          this.nextChar();
+          return PostScriptToken.RBRACE;
+      }
+
+      var strBuf = this.strBuf;
+      strBuf.length = 0;
+      strBuf[0] = String.fromCharCode(ch);
+
+      while ((ch = this.nextChar()) >= 0 && (ch >= 0x41 && ch <= 0x5A || ch >= 0x61 && ch <= 0x7A)) {
+        strBuf.push(String.fromCharCode(ch));
+      }
+
+      var str = strBuf.join('');
+
+      switch (str.toLowerCase()) {
+        case 'if':
+          return PostScriptToken.IF;
+
+        case 'ifelse':
+          return PostScriptToken.IFELSE;
+
+        default:
+          return PostScriptToken.getOperator(str);
+      }
+    }
+  }, {
+    key: "getNumber",
+    value: function getNumber() {
+      var ch = this.currentChar;
+      var strBuf = this.strBuf;
+      strBuf.length = 0;
+      strBuf[0] = String.fromCharCode(ch);
+
+      while ((ch = this.nextChar()) >= 0) {
+        if (ch >= 0x30 && ch <= 0x39 || ch === 0x2D || ch === 0x2E) {
+          strBuf.push(String.fromCharCode(ch));
+        } else {
+          break;
+        }
+      }
+
+      var value = parseFloat(strBuf.join(''));
+
+      if (isNaN(value)) {
+        throw new _util.FormatError("Invalid floating point number: ".concat(value));
+      }
+
+      return value;
+    }
+  }]);
+
+  return PostScriptLexer;
+}();
+
+exports.PostScriptLexer = PostScriptLexer;
+
+/***/ }),
+/* 188 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.MurmurHash3_64 = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var SEED = 0xc3d2e1f0;
+var MASK_HIGH = 0xffff0000;
+var MASK_LOW = 0xffff;
+
+var MurmurHash3_64 =
+/*#__PURE__*/
+function () {
+  function MurmurHash3_64(seed) {
+    _classCallCheck(this, MurmurHash3_64);
+
+    this.h1 = seed ? seed & 0xffffffff : SEED;
+    this.h2 = seed ? seed & 0xffffffff : SEED;
+  }
+
+  _createClass(MurmurHash3_64, [{
+    key: "update",
+    value: function update(input) {
+      var data, length;
+
+      if ((0, _util.isString)(input)) {
+        data = new Uint8Array(input.length * 2);
+        length = 0;
+
+        for (var i = 0, ii = input.length; i < ii; i++) {
+          var code = input.charCodeAt(i);
+
+          if (code <= 0xff) {
+            data[length++] = code;
+          } else {
+            data[length++] = code >>> 8;
+            data[length++] = code & 0xff;
+          }
+        }
+      } else if ((0, _util.isArrayBuffer)(input)) {
+        data = input;
+        length = data.byteLength;
+      } else {
+        throw new Error('Wrong data format in MurmurHash3_64_update. ' + 'Input must be a string or array.');
+      }
+
+      var blockCounts = length >> 2;
+      var tailLength = length - blockCounts * 4;
+      var dataUint32 = new Uint32Array(data.buffer, 0, blockCounts);
+      var k1 = 0,
+          k2 = 0;
+      var h1 = this.h1,
+          h2 = this.h2;
+      var C1 = 0xcc9e2d51,
+          C2 = 0x1b873593;
+      var C1_LOW = C1 & MASK_LOW,
+          C2_LOW = C2 & MASK_LOW;
+
+      for (var _i = 0; _i < blockCounts; _i++) {
+        if (_i & 1) {
+          k1 = dataUint32[_i];
+          k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+          k1 = k1 << 15 | k1 >>> 17;
+          k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+          h1 ^= k1;
+          h1 = h1 << 13 | h1 >>> 19;
+          h1 = h1 * 5 + 0xe6546b64;
+        } else {
+          k2 = dataUint32[_i];
+          k2 = k2 * C1 & MASK_HIGH | k2 * C1_LOW & MASK_LOW;
+          k2 = k2 << 15 | k2 >>> 17;
+          k2 = k2 * C2 & MASK_HIGH | k2 * C2_LOW & MASK_LOW;
+          h2 ^= k2;
+          h2 = h2 << 13 | h2 >>> 19;
+          h2 = h2 * 5 + 0xe6546b64;
+        }
+      }
+
+      k1 = 0;
+
+      switch (tailLength) {
+        case 3:
+          k1 ^= data[blockCounts * 4 + 2] << 16;
+
+        case 2:
+          k1 ^= data[blockCounts * 4 + 1] << 8;
+
+        case 1:
+          k1 ^= data[blockCounts * 4];
+          k1 = k1 * C1 & MASK_HIGH | k1 * C1_LOW & MASK_LOW;
+          k1 = k1 << 15 | k1 >>> 17;
+          k1 = k1 * C2 & MASK_HIGH | k1 * C2_LOW & MASK_LOW;
+
+          if (blockCounts & 1) {
+            h1 ^= k1;
+          } else {
+            h2 ^= k1;
+          }
+
+      }
+
+      this.h1 = h1;
+      this.h2 = h2;
+    }
+  }, {
+    key: "hexdigest",
+    value: function hexdigest() {
+      var h1 = this.h1,
+          h2 = this.h2;
+      h1 ^= h2 >>> 1;
+      h1 = h1 * 0xed558ccd & MASK_HIGH | h1 * 0x8ccd & MASK_LOW;
+      h2 = h2 * 0xff51afd7 & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xafd7ed55 & MASK_HIGH) >>> 16;
+      h1 ^= h2 >>> 1;
+      h1 = h1 * 0x1a85ec53 & MASK_HIGH | h1 * 0xec53 & MASK_LOW;
+      h2 = h2 * 0xc4ceb9fe & MASK_HIGH | ((h2 << 16 | h1 >>> 16) * 0xb9fe1a85 & MASK_HIGH) >>> 16;
+      h1 ^= h2 >>> 1;
+      var hex1 = (h1 >>> 0).toString(16),
+          hex2 = (h2 >>> 0).toString(16);
+      return hex1.padStart(8, '0') + hex2.padStart(8, '0');
+    }
+  }]);
+
+  return MurmurHash3_64;
+}();
+
+exports.MurmurHash3_64 = MurmurHash3_64;
+
+/***/ }),
+/* 189 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.NativeImageDecoder = void 0;
+
+var _colorspace = __w_pdfjs_require__(169);
+
+var _jpeg_stream = __w_pdfjs_require__(164);
+
+var _stream = __w_pdfjs_require__(158);
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var NativeImageDecoder =
+/*#__PURE__*/
+function () {
+  function NativeImageDecoder(_ref) {
+    var xref = _ref.xref,
+        resources = _ref.resources,
+        handler = _ref.handler,
+        _ref$forceDataSchema = _ref.forceDataSchema,
+        forceDataSchema = _ref$forceDataSchema === void 0 ? false : _ref$forceDataSchema,
+        pdfFunctionFactory = _ref.pdfFunctionFactory;
+
+    _classCallCheck(this, NativeImageDecoder);
+
+    this.xref = xref;
+    this.resources = resources;
+    this.handler = handler;
+    this.forceDataSchema = forceDataSchema;
+    this.pdfFunctionFactory = pdfFunctionFactory;
+  }
+
+  _createClass(NativeImageDecoder, [{
+    key: "canDecode",
+    value: function canDecode(image) {
+      return image instanceof _jpeg_stream.JpegStream && NativeImageDecoder.isDecodable(image, this.xref, this.resources, this.pdfFunctionFactory);
+    }
+  }, {
+    key: "decode",
+    value: function decode(image) {
+      var dict = image.dict;
+      var colorSpace = dict.get('ColorSpace', 'CS');
+      colorSpace = _colorspace.ColorSpace.parse(colorSpace, this.xref, this.resources, this.pdfFunctionFactory);
+      return this.handler.sendWithPromise('JpegDecode', [image.getIR(this.forceDataSchema), colorSpace.numComps]).then(function (_ref2) {
+        var data = _ref2.data,
+            width = _ref2.width,
+            height = _ref2.height;
+        return new _stream.Stream(data, 0, data.length, dict);
+      });
+    }
+  }], [{
+    key: "isSupported",
+    value: function isSupported(image, xref, res, pdfFunctionFactory) {
+      var dict = image.dict;
+
+      if (dict.has('DecodeParms') || dict.has('DP')) {
+        return false;
+      }
+
+      var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory);
+
+      return (cs.name === 'DeviceGray' || cs.name === 'DeviceRGB') && cs.isDefaultDecode(dict.getArray('Decode', 'D'));
+    }
+  }, {
+    key: "isDecodable",
+    value: function isDecodable(image, xref, res, pdfFunctionFactory) {
+      var dict = image.dict;
+
+      if (dict.has('DecodeParms') || dict.has('DP')) {
+        return false;
+      }
+
+      var cs = _colorspace.ColorSpace.parse(dict.get('ColorSpace', 'CS'), xref, res, pdfFunctionFactory);
+
+      var bpc = dict.get('BitsPerComponent', 'BPC') || 1;
+      return (cs.numComps === 1 || cs.numComps === 3) && cs.isDefaultDecode(dict.getArray('Decode', 'D'), bpc);
+    }
+  }]);
+
+  return NativeImageDecoder;
+}();
+
+exports.NativeImageDecoder = NativeImageDecoder;
+
+/***/ }),
+/* 190 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFImage = void 0;
+
+var _util = __w_pdfjs_require__(5);
+
+var _primitives = __w_pdfjs_require__(151);
+
+var _colorspace = __w_pdfjs_require__(169);
+
+var _stream = __w_pdfjs_require__(158);
+
+var _jpeg_stream = __w_pdfjs_require__(164);
+
+var _jpx = __w_pdfjs_require__(167);
+
+function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); }
+
+function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); }
+
+function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
+
+function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
+
+var PDFImage = function PDFImageClosure() {
+  function handleImageData(image, nativeDecoder) {
+    if (nativeDecoder && nativeDecoder.canDecode(image)) {
+      return nativeDecoder.decode(image)["catch"](function (reason) {
+        (0, _util.warn)('Native image decoding failed -- trying to recover: ' + (reason && reason.message));
+        return image;
+      });
+    }
+
+    return Promise.resolve(image);
+  }
+
+  function decodeAndClamp(value, addend, coefficient, max) {
+    value = addend + value * coefficient;
+    return value < 0 ? 0 : value > max ? max : value;
+  }
+
+  function resizeImageMask(src, bpc, w1, h1, w2, h2) {
+    var length = w2 * h2;
+    var dest = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
+    var xRatio = w1 / w2;
+    var yRatio = h1 / h2;
+    var i,
+        j,
+        py,
+        newIndex = 0,
+        oldIndex;
+    var xScaled = new Uint16Array(w2);
+    var w1Scanline = w1;
+
+    for (i = 0; i < w2; i++) {
+      xScaled[i] = Math.floor(i * xRatio);
+    }
+
+    for (i = 0; i < h2; i++) {
+      py = Math.floor(i * yRatio) * w1Scanline;
+
+      for (j = 0; j < w2; j++) {
+        oldIndex = py + xScaled[j];
+        dest[newIndex++] = src[oldIndex];
+      }
+    }
+
+    return dest;
+  }
+
+  function PDFImage(_ref) {
+    var xref = _ref.xref,
+        res = _ref.res,
+        image = _ref.image,
+        _ref$isInline = _ref.isInline,
+        isInline = _ref$isInline === void 0 ? false : _ref$isInline,
+        _ref$smask = _ref.smask,
+        smask = _ref$smask === void 0 ? null : _ref$smask,
+        _ref$mask = _ref.mask,
+        mask = _ref$mask === void 0 ? null : _ref$mask,
+        _ref$isMask = _ref.isMask,
+        isMask = _ref$isMask === void 0 ? false : _ref$isMask,
+        pdfFunctionFactory = _ref.pdfFunctionFactory;
+    this.image = image;
+    var dict = image.dict;
+    var filter = dict.get('Filter');
+
+    if ((0, _primitives.isName)(filter)) {
+      switch (filter.name) {
+        case 'JPXDecode':
+          var jpxImage = new _jpx.JpxImage();
+          jpxImage.parseImageProperties(image.stream);
+          image.stream.reset();
+          image.width = jpxImage.width;
+          image.height = jpxImage.height;
+          image.bitsPerComponent = jpxImage.bitsPerComponent;
+          image.numComps = jpxImage.componentsCount;
+          break;
+
+        case 'JBIG2Decode':
+          image.bitsPerComponent = 1;
+          image.numComps = 1;
+          break;
+      }
+    }
+
+    var width = dict.get('Width', 'W');
+    var height = dict.get('Height', 'H');
+
+    if (Number.isInteger(image.width) && image.width > 0 && Number.isInteger(image.height) && image.height > 0 && (image.width !== width || image.height !== height)) {
+      (0, _util.warn)('PDFImage - using the Width/Height of the image data, ' + 'rather than the image dictionary.');
+      width = image.width;
+      height = image.height;
+    }
+
+    if (width < 1 || height < 1) {
+      throw new _util.FormatError("Invalid image width: ".concat(width, " or ") + "height: ".concat(height));
+    }
+
+    this.width = width;
+    this.height = height;
+    this.interpolate = dict.get('Interpolate', 'I') || false;
+    this.imageMask = dict.get('ImageMask', 'IM') || false;
+    this.matte = dict.get('Matte') || false;
+    var bitsPerComponent = image.bitsPerComponent;
+
+    if (!bitsPerComponent) {
+      bitsPerComponent = dict.get('BitsPerComponent', 'BPC');
+
+      if (!bitsPerComponent) {
+        if (this.imageMask) {
+          bitsPerComponent = 1;
+        } else {
+          throw new _util.FormatError("Bits per component missing in image: ".concat(this.imageMask));
+        }
+      }
+    }
+
+    this.bpc = bitsPerComponent;
+
+    if (!this.imageMask) {
+      var colorSpace = dict.get('ColorSpace', 'CS');
+
+      if (!colorSpace) {
+        (0, _util.info)('JPX images (which do not require color spaces)');
+
+        switch (image.numComps) {
+          case 1:
+            colorSpace = _primitives.Name.get('DeviceGray');
+            break;
+
+          case 3:
+            colorSpace = _primitives.Name.get('DeviceRGB');
+            break;
+
+          case 4:
+            colorSpace = _primitives.Name.get('DeviceCMYK');
+            break;
+
+          default:
+            throw new Error("JPX images with ".concat(image.numComps, " ") + 'color components not supported.');
+        }
+      }
+
+      var resources = isInline ? res : null;
+      this.colorSpace = _colorspace.ColorSpace.parse(colorSpace, xref, resources, pdfFunctionFactory);
+      this.numComps = this.colorSpace.numComps;
+    }
+
+    this.decode = dict.getArray('Decode', 'D');
+    this.needsDecode = false;
+
+    if (this.decode && (this.colorSpace && !this.colorSpace.isDefaultDecode(this.decode, bitsPerComponent) || isMask && !_colorspace.ColorSpace.isDefaultDecode(this.decode, 1))) {
+      this.needsDecode = true;
+      var max = (1 << bitsPerComponent) - 1;
+      this.decodeCoefficients = [];
+      this.decodeAddends = [];
+      var isIndexed = this.colorSpace && this.colorSpace.name === 'Indexed';
+
+      for (var i = 0, j = 0; i < this.decode.length; i += 2, ++j) {
+        var dmin = this.decode[i];
+        var dmax = this.decode[i + 1];
+        this.decodeCoefficients[j] = isIndexed ? (dmax - dmin) / max : dmax - dmin;
+        this.decodeAddends[j] = isIndexed ? dmin : max * dmin;
+      }
+    }
+
+    if (smask) {
+      this.smask = new PDFImage({
+        xref: xref,
+        res: res,
+        image: smask,
+        isInline: isInline,
+        pdfFunctionFactory: pdfFunctionFactory
+      });
+    } else if (mask) {
+      if ((0, _primitives.isStream)(mask)) {
+        var maskDict = mask.dict,
+            imageMask = maskDict.get('ImageMask', 'IM');
+
+        if (!imageMask) {
+          (0, _util.warn)('Ignoring /Mask in image without /ImageMask.');
+        } else {
+          this.mask = new PDFImage({
+            xref: xref,
+            res: res,
+            image: mask,
+            isInline: isInline,
+            isMask: true,
+            pdfFunctionFactory: pdfFunctionFactory
+          });
+        }
+      } else {
+        this.mask = mask;
+      }
+    }
+  }
+
+  PDFImage.buildImage = function (_ref2) {
+    var handler = _ref2.handler,
+        xref = _ref2.xref,
+        res = _ref2.res,
+        image = _ref2.image,
+        _ref2$isInline = _ref2.isInline,
+        isInline = _ref2$isInline === void 0 ? false : _ref2$isInline,
+        _ref2$nativeDecoder = _ref2.nativeDecoder,
+        nativeDecoder = _ref2$nativeDecoder === void 0 ? null : _ref2$nativeDecoder,
+        pdfFunctionFactory = _ref2.pdfFunctionFactory;
+    var imagePromise = handleImageData(image, nativeDecoder);
+    var smaskPromise;
+    var maskPromise;
+    var smask = image.dict.get('SMask');
+    var mask = image.dict.get('Mask');
+
+    if (smask) {
+      smaskPromise = handleImageData(smask, nativeDecoder);
+      maskPromise = Promise.resolve(null);
+    } else {
+      smaskPromise = Promise.resolve(null);
+
+      if (mask) {
+        if ((0, _primitives.isStream)(mask)) {
+          maskPromise = handleImageData(mask, nativeDecoder);
+        } else if (Array.isArray(mask)) {
+          maskPromise = Promise.resolve(mask);
+        } else {
+          (0, _util.warn)('Unsupported mask format.');
+          maskPromise = Promise.resolve(null);
+        }
+      } else {
+        maskPromise = Promise.resolve(null);
+      }
+    }
+
+    return Promise.all([imagePromise, smaskPromise, maskPromise]).then(function (_ref3) {
+      var _ref4 = _slicedToArray(_ref3, 3),
+          imageData = _ref4[0],
+          smaskData = _ref4[1],
+          maskData = _ref4[2];
+
+      return new PDFImage({
+        xref: xref,
+        res: res,
+        image: imageData,
+        isInline: isInline,
+        smask: smaskData,
+        mask: maskData,
+        pdfFunctionFactory: pdfFunctionFactory
+      });
+    });
+  };
+
+  PDFImage.createMask = function (_ref5) {
+    var imgArray = _ref5.imgArray,
+        width = _ref5.width,
+        height = _ref5.height,
+        imageIsFromDecodeStream = _ref5.imageIsFromDecodeStream,
+        inverseDecode = _ref5.inverseDecode;
+    var computedLength = (width + 7 >> 3) * height;
+    var actualLength = imgArray.byteLength;
+    var haveFullData = computedLength === actualLength;
+    var data, i;
+
+    if (imageIsFromDecodeStream && (!inverseDecode || haveFullData)) {
+      data = imgArray;
+    } else if (!inverseDecode) {
+      data = new Uint8ClampedArray(actualLength);
+      data.set(imgArray);
+    } else {
+      data = new Uint8ClampedArray(computedLength);
+      data.set(imgArray);
+
+      for (i = actualLength; i < computedLength; i++) {
+        data[i] = 0xff;
+      }
+    }
+
+    if (inverseDecode) {
+      for (i = 0; i < actualLength; i++) {
+        data[i] ^= 0xFF;
+      }
+    }
+
+    return {
+      data: data,
+      width: width,
+      height: height
+    };
+  };
+
+  PDFImage.prototype = {
+    get drawWidth() {
+      return Math.max(this.width, this.smask && this.smask.width || 0, this.mask && this.mask.width || 0);
+    },
+
+    get drawHeight() {
+      return Math.max(this.height, this.smask && this.smask.height || 0, this.mask && this.mask.height || 0);
+    },
+
+    decodeBuffer: function decodeBuffer(buffer) {
+      var bpc = this.bpc;
+      var numComps = this.numComps;
+      var decodeAddends = this.decodeAddends;
+      var decodeCoefficients = this.decodeCoefficients;
+      var max = (1 << bpc) - 1;
+      var i, ii;
+
+      if (bpc === 1) {
+        for (i = 0, ii = buffer.length; i < ii; i++) {
+          buffer[i] = +!buffer[i];
+        }
+
+        return;
+      }
+
+      var index = 0;
+
+      for (i = 0, ii = this.width * this.height; i < ii; i++) {
+        for (var j = 0; j < numComps; j++) {
+          buffer[index] = decodeAndClamp(buffer[index], decodeAddends[j], decodeCoefficients[j], max);
+          index++;
+        }
+      }
+    },
+    getComponents: function getComponents(buffer) {
+      var bpc = this.bpc;
+
+      if (bpc === 8) {
+        return buffer;
+      }
+
+      var width = this.width;
+      var height = this.height;
+      var numComps = this.numComps;
+      var length = width * height * numComps;
+      var bufferPos = 0;
+      var output = bpc <= 8 ? new Uint8Array(length) : bpc <= 16 ? new Uint16Array(length) : new Uint32Array(length);
+      var rowComps = width * numComps;
+      var max = (1 << bpc) - 1;
+      var i = 0,
+          ii,
+          buf;
+
+      if (bpc === 1) {
+        var mask, loop1End, loop2End;
+
+        for (var j = 0; j < height; j++) {
+          loop1End = i + (rowComps & ~7);
+          loop2End = i + rowComps;
+
+          while (i < loop1End) {
+            buf = buffer[bufferPos++];
+            output[i] = buf >> 7 & 1;
+            output[i + 1] = buf >> 6 & 1;
+            output[i + 2] = buf >> 5 & 1;
+            output[i + 3] = buf >> 4 & 1;
+            output[i + 4] = buf >> 3 & 1;
+            output[i + 5] = buf >> 2 & 1;
+            output[i + 6] = buf >> 1 & 1;
+            output[i + 7] = buf & 1;
+            i += 8;
+          }
+
+          if (i < loop2End) {
+            buf = buffer[bufferPos++];
+            mask = 128;
+
+            while (i < loop2End) {
+              output[i++] = +!!(buf & mask);
+              mask >>= 1;
+            }
+          }
+        }
+      } else {
+        var bits = 0;
+        buf = 0;
+
+        for (i = 0, ii = length; i < ii; ++i) {
+          if (i % rowComps === 0) {
+            buf = 0;
+            bits = 0;
+          }
+
+          while (bits < bpc) {
+            buf = buf << 8 | buffer[bufferPos++];
+            bits += 8;
+          }
+
+          var remainingBits = bits - bpc;
+          var value = buf >> remainingBits;
+          output[i] = value < 0 ? 0 : value > max ? max : value;
+          buf = buf & (1 << remainingBits) - 1;
+          bits = remainingBits;
+        }
+      }
+
+      return output;
+    },
+    fillOpacity: function fillOpacity(rgbaBuf, width, height, actualHeight, image) {
+      var smask = this.smask;
+      var mask = this.mask;
+      var alphaBuf, sw, sh, i, ii, j;
+
+      if (smask) {
+        sw = smask.width;
+        sh = smask.height;
+        alphaBuf = new Uint8ClampedArray(sw * sh);
+        smask.fillGrayBuffer(alphaBuf);
+
+        if (sw !== width || sh !== height) {
+          alphaBuf = resizeImageMask(alphaBuf, smask.bpc, sw, sh, width, height);
+        }
+      } else if (mask) {
+        if (mask instanceof PDFImage) {
+          sw = mask.width;
+          sh = mask.height;
+          alphaBuf = new Uint8ClampedArray(sw * sh);
+          mask.numComps = 1;
+          mask.fillGrayBuffer(alphaBuf);
+
+          for (i = 0, ii = sw * sh; i < ii; ++i) {
+            alphaBuf[i] = 255 - alphaBuf[i];
+          }
+
+          if (sw !== width || sh !== height) {
+            alphaBuf = resizeImageMask(alphaBuf, mask.bpc, sw, sh, width, height);
+          }
+        } else if (Array.isArray(mask)) {
+          alphaBuf = new Uint8ClampedArray(width * height);
+          var numComps = this.numComps;
+
+          for (i = 0, ii = width * height; i < ii; ++i) {
+            var opacity = 0;
+            var imageOffset = i * numComps;
+
+            for (j = 0; j < numComps; ++j) {
+              var color = image[imageOffset + j];
+              var maskOffset = j * 2;
+
+              if (color < mask[maskOffset] || color > mask[maskOffset + 1]) {
+                opacity = 255;
+                break;
+              }
+            }
+
+            alphaBuf[i] = opacity;
+          }
+        } else {
+          throw new _util.FormatError('Unknown mask format.');
+        }
+      }
+
+      if (alphaBuf) {
+        for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+          rgbaBuf[j] = alphaBuf[i];
+        }
+      } else {
+        for (i = 0, j = 3, ii = width * actualHeight; i < ii; ++i, j += 4) {
+          rgbaBuf[j] = 255;
+        }
+      }
+    },
+    undoPreblend: function undoPreblend(buffer, width, height) {
+      var matte = this.smask && this.smask.matte;
+
+      if (!matte) {
+        return;
+      }
+
+      var matteRgb = this.colorSpace.getRgb(matte, 0);
+      var matteR = matteRgb[0];
+      var matteG = matteRgb[1];
+      var matteB = matteRgb[2];
+      var length = width * height * 4;
+
+      for (var i = 0; i < length; i += 4) {
+        var alpha = buffer[i + 3];
+
+        if (alpha === 0) {
+          buffer[i] = 255;
+          buffer[i + 1] = 255;
+          buffer[i + 2] = 255;
+          continue;
+        }
+
+        var k = 255 / alpha;
+        buffer[i] = (buffer[i] - matteR) * k + matteR;
+        buffer[i + 1] = (buffer[i + 1] - matteG) * k + matteG;
+        buffer[i + 2] = (buffer[i + 2] - matteB) * k + matteB;
+      }
+    },
+    createImageData: function createImageData() {
+      var forceRGBA = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
+      var drawWidth = this.drawWidth;
+      var drawHeight = this.drawHeight;
+      var imgData = {
+        width: drawWidth,
+        height: drawHeight,
+        kind: 0,
+        data: null
+      };
+      var numComps = this.numComps;
+      var originalWidth = this.width;
+      var originalHeight = this.height;
+      var bpc = this.bpc;
+      var rowBytes = originalWidth * numComps * bpc + 7 >> 3;
+      var imgArray;
+
+      if (!forceRGBA) {
+        var kind;
+
+        if (this.colorSpace.name === 'DeviceGray' && bpc === 1) {
+          kind = _util.ImageKind.GRAYSCALE_1BPP;
+        } else if (this.colorSpace.name === 'DeviceRGB' && bpc === 8 && !this.needsDecode) {
+          kind = _util.ImageKind.RGB_24BPP;
+        }
+
+        if (kind && !this.smask && !this.mask && drawWidth === originalWidth && drawHeight === originalHeight) {
+          imgData.kind = kind;
+          imgArray = this.getImageBytes(originalHeight * rowBytes);
+
+          if (this.image instanceof _stream.DecodeStream) {
+            imgData.data = imgArray;
+          } else {
+            var newArray = new Uint8ClampedArray(imgArray.length);
+            newArray.set(imgArray);
+            imgData.data = newArray;
+          }
+
+          if (this.needsDecode) {
+            (0, _util.assert)(kind === _util.ImageKind.GRAYSCALE_1BPP, 'PDFImage.createImageData: The image must be grayscale.');
+            var buffer = imgData.data;
+
+            for (var i = 0, ii = buffer.length; i < ii; i++) {
+              buffer[i] ^= 0xff;
+            }
+          }
+
+          return imgData;
+        }
+
+        if (this.image instanceof _jpeg_stream.JpegStream && !this.smask && !this.mask) {
+          var imageLength = originalHeight * rowBytes;
+
+          switch (this.colorSpace.name) {
+            case 'DeviceGray':
+              imageLength *= 3;
+
+            case 'DeviceRGB':
+            case 'DeviceCMYK':
+              imgData.kind = _util.ImageKind.RGB_24BPP;
+              imgData.data = this.getImageBytes(imageLength, drawWidth, drawHeight, true);
+              return imgData;
+          }
+        }
+      }
+
+      imgArray = this.getImageBytes(originalHeight * rowBytes);
+      var actualHeight = 0 | imgArray.length / rowBytes * drawHeight / originalHeight;
+      var comps = this.getComponents(imgArray);
+      var alpha01, maybeUndoPreblend;
+
+      if (!forceRGBA && !this.smask && !this.mask) {
+        imgData.kind = _util.ImageKind.RGB_24BPP;
+        imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 3);
+        alpha01 = 0;
+        maybeUndoPreblend = false;
+      } else {
+        imgData.kind = _util.ImageKind.RGBA_32BPP;
+        imgData.data = new Uint8ClampedArray(drawWidth * drawHeight * 4);
+        alpha01 = 1;
+        maybeUndoPreblend = true;
+        this.fillOpacity(imgData.data, drawWidth, drawHeight, actualHeight, comps);
+      }
+
+      if (this.needsDecode) {
+        this.decodeBuffer(comps);
+      }
+
+      this.colorSpace.fillRgb(imgData.data, originalWidth, originalHeight, drawWidth, drawHeight, actualHeight, bpc, comps, alpha01);
+
+      if (maybeUndoPreblend) {
+        this.undoPreblend(imgData.data, drawWidth, actualHeight);
+      }
+
+      return imgData;
+    },
+    fillGrayBuffer: function fillGrayBuffer(buffer) {
+      var numComps = this.numComps;
+
+      if (numComps !== 1) {
+        throw new _util.FormatError("Reading gray scale from a color image: ".concat(numComps));
+      }
+
+      var width = this.width;
+      var height = this.height;
+      var bpc = this.bpc;
+      var rowBytes = width * numComps * bpc + 7 >> 3;
+      var imgArray = this.getImageBytes(height * rowBytes);
+      var comps = this.getComponents(imgArray);
+      var i, length;
+
+      if (bpc === 1) {
+        length = width * height;
+
+        if (this.needsDecode) {
+          for (i = 0; i < length; ++i) {
+            buffer[i] = comps[i] - 1 & 255;
+          }
+        } else {
+          for (i = 0; i < length; ++i) {
+            buffer[i] = -comps[i] & 255;
+          }
+        }
+
+        return;
+      }
+
+      if (this.needsDecode) {
+        this.decodeBuffer(comps);
+      }
+
+      length = width * height;
+      var scale = 255 / ((1 << bpc) - 1);
+
+      for (i = 0; i < length; ++i) {
+        buffer[i] = scale * comps[i];
+      }
+    },
+    getImageBytes: function getImageBytes(length, drawWidth, drawHeight) {
+      var forceRGB = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false;
+      this.image.reset();
+      this.image.drawWidth = drawWidth || this.width;
+      this.image.drawHeight = drawHeight || this.height;
+      this.image.forceRGB = !!forceRGB;
+      return this.image.getBytes(length, true);
+    }
+  };
+  return PDFImage;
+}();
+
+exports.PDFImage = PDFImage;
+
+/***/ }),
+/* 191 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.MessageHandler = MessageHandler;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
+
+function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function resolveCall(_x, _x2) {
+  return _resolveCall.apply(this, arguments);
+}
+
+function _resolveCall() {
+  _resolveCall = _asyncToGenerator(
+  /*#__PURE__*/
+  _regenerator["default"].mark(function _callee(fn, args) {
+    var thisArg,
+        _args = arguments;
+    return _regenerator["default"].wrap(function _callee$(_context) {
+      while (1) {
+        switch (_context.prev = _context.next) {
+          case 0:
+            thisArg = _args.length > 2 && _args[2] !== undefined ? _args[2] : null;
+
+            if (fn) {
+              _context.next = 3;
+              break;
+            }
+
+            return _context.abrupt("return", undefined);
+
+          case 3:
+            return _context.abrupt("return", fn.apply(thisArg, args));
+
+          case 4:
+          case "end":
+            return _context.stop();
+        }
+      }
+    }, _callee);
+  }));
+  return _resolveCall.apply(this, arguments);
+}
+
+function wrapReason(reason) {
+  if (_typeof(reason) !== 'object') {
+    return reason;
+  }
+
+  switch (reason.name) {
+    case 'AbortException':
+      return new _util.AbortException(reason.message);
+
+    case 'MissingPDFException':
+      return new _util.MissingPDFException(reason.message);
+
+    case 'UnexpectedResponseException':
+      return new _util.UnexpectedResponseException(reason.message, reason.status);
+
+    default:
+      return new _util.UnknownErrorException(reason.message, reason.details);
+  }
+}
+
+function makeReasonSerializable(reason) {
+  if (!(reason instanceof Error) || reason instanceof _util.AbortException || reason instanceof _util.MissingPDFException || reason instanceof _util.UnexpectedResponseException || reason instanceof _util.UnknownErrorException) {
+    return reason;
+  }
+
+  return new _util.UnknownErrorException(reason.message, reason.toString());
+}
+
+function resolveOrReject(capability, success, reason) {
+  if (success) {
+    capability.resolve();
+  } else {
+    capability.reject(reason);
+  }
+}
+
+function finalize(promise) {
+  return Promise.resolve(promise)["catch"](function () {});
+}
+
+function MessageHandler(sourceName, targetName, comObj) {
+  var _this = this;
+
+  this.sourceName = sourceName;
+  this.targetName = targetName;
+  this.comObj = comObj;
+  this.callbackId = 1;
+  this.streamId = 1;
+  this.postMessageTransfers = true;
+  this.streamSinks = Object.create(null);
+  this.streamControllers = Object.create(null);
+  var callbacksCapabilities = this.callbacksCapabilities = Object.create(null);
+  var ah = this.actionHandler = Object.create(null);
+
+  this._onComObjOnMessage = function (event) {
+    var data = event.data;
+
+    if (data.targetName !== _this.sourceName) {
+      return;
+    }
+
+    if (data.stream) {
+      _this._processStreamMessage(data);
+    } else if (data.isReply) {
+      var callbackId = data.callbackId;
+
+      if (data.callbackId in callbacksCapabilities) {
+        var callback = callbacksCapabilities[callbackId];
+        delete callbacksCapabilities[callbackId];
+
+        if ('error' in data) {
+          callback.reject(wrapReason(data.error));
+        } else {
+          callback.resolve(data.data);
+        }
+      } else {
+        throw new Error("Cannot resolve callback ".concat(callbackId));
+      }
+    } else if (data.action in ah) {
+      var action = ah[data.action];
+
+      if (data.callbackId) {
+        var _sourceName = _this.sourceName;
+        var _targetName = data.sourceName;
+        Promise.resolve().then(function () {
+          return action[0].call(action[1], data.data);
+        }).then(function (result) {
+          comObj.postMessage({
+            sourceName: _sourceName,
+            targetName: _targetName,
+            isReply: true,
+            callbackId: data.callbackId,
+            data: result
+          });
+        }, function (reason) {
+          comObj.postMessage({
+            sourceName: _sourceName,
+            targetName: _targetName,
+            isReply: true,
+            callbackId: data.callbackId,
+            error: makeReasonSerializable(reason)
+          });
+        });
+      } else if (data.streamId) {
+        _this._createStreamSink(data);
+      } else {
+        action[0].call(action[1], data.data);
+      }
+    } else {
+      throw new Error("Unknown action from worker: ".concat(data.action));
+    }
+  };
+
+  comObj.addEventListener('message', this._onComObjOnMessage);
+}
+
+MessageHandler.prototype = {
+  on: function on(actionName, handler, scope) {
+    var ah = this.actionHandler;
+
+    if (ah[actionName]) {
+      throw new Error("There is already an actionName called \"".concat(actionName, "\""));
+    }
+
+    ah[actionName] = [handler, scope];
+  },
+  send: function send(actionName, data, transfers) {
+    var message = {
+      sourceName: this.sourceName,
+      targetName: this.targetName,
+      action: actionName,
+      data: data
+    };
+    this.postMessage(message, transfers);
+  },
+  sendWithPromise: function sendWithPromise(actionName, data, transfers) {
+    var callbackId = this.callbackId++;
+    var message = {
+      sourceName: this.sourceName,
+      targetName: this.targetName,
+      action: actionName,
+      data: data,
+      callbackId: callbackId
+    };
+    var capability = (0, _util.createPromiseCapability)();
+    this.callbacksCapabilities[callbackId] = capability;
+
+    try {
+      this.postMessage(message, transfers);
+    } catch (e) {
+      capability.reject(e);
+    }
+
+    return capability.promise;
+  },
+  sendWithStream: function sendWithStream(actionName, data, queueingStrategy, transfers) {
+    var _this2 = this;
+
+    var streamId = this.streamId++;
+    var sourceName = this.sourceName;
+    var targetName = this.targetName;
+    return new _util.ReadableStream({
+      start: function start(controller) {
+        var startCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId] = {
+          controller: controller,
+          startCall: startCapability,
+          isClosed: false
+        };
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          action: actionName,
+          streamId: streamId,
+          data: data,
+          desiredSize: controller.desiredSize
+        });
+
+        return startCapability.promise;
+      },
+      pull: function pull(controller) {
+        var pullCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId].pullCall = pullCapability;
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          stream: 'pull',
+          streamId: streamId,
+          desiredSize: controller.desiredSize
+        });
+
+        return pullCapability.promise;
+      },
+      cancel: function cancel(reason) {
+        var cancelCapability = (0, _util.createPromiseCapability)();
+        _this2.streamControllers[streamId].cancelCall = cancelCapability;
+        _this2.streamControllers[streamId].isClosed = true;
+
+        _this2.postMessage({
+          sourceName: sourceName,
+          targetName: targetName,
+          stream: 'cancel',
+          reason: reason,
+          streamId: streamId
+        });
+
+        return cancelCapability.promise;
+      }
+    }, queueingStrategy);
+  },
+  _createStreamSink: function _createStreamSink(data) {
+    var _this3 = this;
+
+    var self = this;
+    var action = this.actionHandler[data.action];
+    var streamId = data.streamId;
+    var desiredSize = data.desiredSize;
+    var sourceName = this.sourceName;
+    var targetName = data.sourceName;
+    var capability = (0, _util.createPromiseCapability)();
+
+    var sendStreamRequest = function sendStreamRequest(_ref) {
+      var stream = _ref.stream,
+          chunk = _ref.chunk,
+          transfers = _ref.transfers,
+          success = _ref.success,
+          reason = _ref.reason;
+
+      _this3.postMessage({
+        sourceName: sourceName,
+        targetName: targetName,
+        stream: stream,
+        streamId: streamId,
+        chunk: chunk,
+        success: success,
+        reason: reason
+      }, transfers);
+    };
+
+    var streamSink = {
+      enqueue: function enqueue(chunk) {
+        var size = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
+        var transfers = arguments.length > 2 ? arguments[2] : undefined;
+
+        if (this.isCancelled) {
+          return;
+        }
+
+        var lastDesiredSize = this.desiredSize;
+        this.desiredSize -= size;
+
+        if (lastDesiredSize > 0 && this.desiredSize <= 0) {
+          this.sinkCapability = (0, _util.createPromiseCapability)();
+          this.ready = this.sinkCapability.promise;
+        }
+
+        sendStreamRequest({
+          stream: 'enqueue',
+          chunk: chunk,
+          transfers: transfers
+        });
+      },
+      close: function close() {
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        sendStreamRequest({
+          stream: 'close'
+        });
+        delete self.streamSinks[streamId];
+      },
+      error: function error(reason) {
+        if (this.isCancelled) {
+          return;
+        }
+
+        this.isCancelled = true;
+        sendStreamRequest({
+          stream: 'error',
+          reason: reason
+        });
+      },
+      sinkCapability: capability,
+      onPull: null,
+      onCancel: null,
+      isCancelled: false,
+      desiredSize: desiredSize,
+      ready: null
+    };
+    streamSink.sinkCapability.resolve();
+    streamSink.ready = streamSink.sinkCapability.promise;
+    this.streamSinks[streamId] = streamSink;
+    resolveCall(action[0], [data.data, streamSink], action[1]).then(function () {
+      sendStreamRequest({
+        stream: 'start_complete',
+        success: true
+      });
+    }, function (reason) {
+      sendStreamRequest({
+        stream: 'start_complete',
+        success: false,
+        reason: reason
+      });
+    });
+  },
+  _processStreamMessage: function _processStreamMessage(data) {
+    var _this4 = this;
+
+    var sourceName = this.sourceName;
+    var targetName = data.sourceName;
+    var streamId = data.streamId;
+
+    var sendStreamResponse = function sendStreamResponse(_ref2) {
+      var stream = _ref2.stream,
+          success = _ref2.success,
+          reason = _ref2.reason;
+
+      _this4.comObj.postMessage({
+        sourceName: sourceName,
+        targetName: targetName,
+        stream: stream,
+        success: success,
+        streamId: streamId,
+        reason: reason
+      });
+    };
+
+    var deleteStreamController = function deleteStreamController() {
+      Promise.all([_this4.streamControllers[data.streamId].startCall, _this4.streamControllers[data.streamId].pullCall, _this4.streamControllers[data.streamId].cancelCall].map(function (capability) {
+        return capability && finalize(capability.promise);
+      })).then(function () {
+        delete _this4.streamControllers[data.streamId];
+      });
+    };
+
+    switch (data.stream) {
+      case 'start_complete':
+        resolveOrReject(this.streamControllers[data.streamId].startCall, data.success, wrapReason(data.reason));
+        break;
+
+      case 'pull_complete':
+        resolveOrReject(this.streamControllers[data.streamId].pullCall, data.success, wrapReason(data.reason));
+        break;
+
+      case 'pull':
+        if (!this.streamSinks[data.streamId]) {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: true
+          });
+          break;
+        }
+
+        if (this.streamSinks[data.streamId].desiredSize <= 0 && data.desiredSize > 0) {
+          this.streamSinks[data.streamId].sinkCapability.resolve();
+        }
+
+        this.streamSinks[data.streamId].desiredSize = data.desiredSize;
+        resolveCall(this.streamSinks[data.streamId].onPull).then(function () {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: true
+          });
+        }, function (reason) {
+          sendStreamResponse({
+            stream: 'pull_complete',
+            success: false,
+            reason: reason
+          });
+        });
+        break;
+
+      case 'enqueue':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'enqueue should have stream controller');
+
+        if (!this.streamControllers[data.streamId].isClosed) {
+          this.streamControllers[data.streamId].controller.enqueue(data.chunk);
+        }
+
+        break;
+
+      case 'close':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'close should have stream controller');
+
+        if (this.streamControllers[data.streamId].isClosed) {
+          break;
+        }
+
+        this.streamControllers[data.streamId].isClosed = true;
+        this.streamControllers[data.streamId].controller.close();
+        deleteStreamController();
+        break;
+
+      case 'error':
+        (0, _util.assert)(this.streamControllers[data.streamId], 'error should have stream controller');
+        this.streamControllers[data.streamId].controller.error(wrapReason(data.reason));
+        deleteStreamController();
+        break;
+
+      case 'cancel_complete':
+        resolveOrReject(this.streamControllers[data.streamId].cancelCall, data.success, wrapReason(data.reason));
+        deleteStreamController();
+        break;
+
+      case 'cancel':
+        if (!this.streamSinks[data.streamId]) {
+          break;
+        }
+
+        resolveCall(this.streamSinks[data.streamId].onCancel, [wrapReason(data.reason)]).then(function () {
+          sendStreamResponse({
+            stream: 'cancel_complete',
+            success: true
+          });
+        }, function (reason) {
+          sendStreamResponse({
+            stream: 'cancel_complete',
+            success: false,
+            reason: reason
+          });
+        });
+        this.streamSinks[data.streamId].sinkCapability.reject(wrapReason(data.reason));
+        this.streamSinks[data.streamId].isCancelled = true;
+        delete this.streamSinks[data.streamId];
+        break;
+
+      default:
+        throw new Error('Unexpected stream case');
+    }
+  },
+  postMessage: function postMessage(message, transfers) {
+    if (transfers && this.postMessageTransfers) {
+      this.comObj.postMessage(message, transfers);
+    } else {
+      this.comObj.postMessage(message);
+    }
+  },
+  destroy: function destroy() {
+    this.comObj.removeEventListener('message', this._onComObjOnMessage);
+  }
+};
+
+/***/ }),
+/* 192 */
+/***/ (function(module, exports, __w_pdfjs_require__) {
+
+"use strict";
+
+
+Object.defineProperty(exports, "__esModule", {
+  value: true
+});
+exports.PDFWorkerStream = void 0;
+
+var _regenerator = _interopRequireDefault(__w_pdfjs_require__(2));
+
+var _util = __w_pdfjs_require__(5);
+
+function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
+
+function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
+
+function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
+
+function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
+
+function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
+
+function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
+
+var PDFWorkerStream =
+/*#__PURE__*/
+function () {
+  function PDFWorkerStream(msgHandler) {
+    _classCallCheck(this, PDFWorkerStream);
+
+    this._msgHandler = msgHandler;
+    this._contentLength = null;
+    this._fullRequestReader = null;
+    this._rangeRequestReaders = [];
+  }
+
+  _createClass(PDFWorkerStream, [{
+    key: "getFullReader",
+    value: function getFullReader() {
+      (0, _util.assert)(!this._fullRequestReader);
+      this._fullRequestReader = new PDFWorkerStreamReader(this._msgHandler);
+      return this._fullRequestReader;
+    }
+  }, {
+    key: "getRangeReader",
+    value: function getRangeReader(begin, end) {
+      var reader = new PDFWorkerStreamRangeReader(begin, end, this._msgHandler);
+
+      this._rangeRequestReaders.push(reader);
+
+      return reader;
+    }
+  }, {
+    key: "cancelAllRequests",
+    value: function cancelAllRequests(reason) {
+      if (this._fullRequestReader) {
+        this._fullRequestReader.cancel(reason);
+      }
+
+      var readers = this._rangeRequestReaders.slice(0);
+
+      readers.forEach(function (reader) {
+        reader.cancel(reason);
+      });
+    }
+  }]);
+
+  return PDFWorkerStream;
+}();
+
+exports.PDFWorkerStream = PDFWorkerStream;
+
+var PDFWorkerStreamReader =
+/*#__PURE__*/
+function () {
+  function PDFWorkerStreamReader(msgHandler) {
+    var _this = this;
+
+    _classCallCheck(this, PDFWorkerStreamReader);
+
+    this._msgHandler = msgHandler;
+    this.onProgress = null;
+    this._contentLength = null;
+    this._isRangeSupported = false;
+    this._isStreamingSupported = false;
+
+    var readableStream = this._msgHandler.sendWithStream('GetReader');
+
+    this._reader = readableStream.getReader();
+    this._headersReady = this._msgHandler.sendWithPromise('ReaderHeadersReady').then(function (data) {
+      _this._isStreamingSupported = data.isStreamingSupported;
+      _this._isRangeSupported = data.isRangeSupported;
+      _this._contentLength = data.contentLength;
+    });
+  }
+
+  _createClass(PDFWorkerStreamReader, [{
+    key: "read",
+    value: function () {
+      var _read = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee() {
+        var _ref, value, done;
+
+        return _regenerator["default"].wrap(function _callee$(_context) {
+          while (1) {
+            switch (_context.prev = _context.next) {
+              case 0:
+                _context.next = 2;
+                return this._reader.read();
+
+              case 2:
+                _ref = _context.sent;
+                value = _ref.value;
+                done = _ref.done;
+
+                if (!done) {
+                  _context.next = 7;
+                  break;
+                }
+
+                return _context.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 7:
+                return _context.abrupt("return", {
+                  value: value.buffer,
+                  done: false
+                });
+
+              case 8:
+              case "end":
+                return _context.stop();
+            }
+          }
+        }, _callee, this);
+      }));
+
+      function read() {
+        return _read.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._reader.cancel(reason);
+    }
+  }, {
+    key: "headersReady",
+    get: function get() {
+      return this._headersReady;
+    }
+  }, {
+    key: "contentLength",
+    get: function get() {
+      return this._contentLength;
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return this._isStreamingSupported;
+    }
+  }, {
+    key: "isRangeSupported",
+    get: function get() {
+      return this._isRangeSupported;
+    }
+  }]);
+
+  return PDFWorkerStreamReader;
+}();
+
+var PDFWorkerStreamRangeReader =
+/*#__PURE__*/
+function () {
+  function PDFWorkerStreamRangeReader(begin, end, msgHandler) {
+    _classCallCheck(this, PDFWorkerStreamRangeReader);
+
+    this._msgHandler = msgHandler;
+    this.onProgress = null;
+
+    var readableStream = this._msgHandler.sendWithStream('GetRangeReader', {
+      begin: begin,
+      end: end
+    });
+
+    this._reader = readableStream.getReader();
+  }
+
+  _createClass(PDFWorkerStreamRangeReader, [{
+    key: "read",
+    value: function () {
+      var _read2 = _asyncToGenerator(
+      /*#__PURE__*/
+      _regenerator["default"].mark(function _callee2() {
+        var _ref2, value, done;
+
+        return _regenerator["default"].wrap(function _callee2$(_context2) {
+          while (1) {
+            switch (_context2.prev = _context2.next) {
+              case 0:
+                _context2.next = 2;
+                return this._reader.read();
+
+              case 2:
+                _ref2 = _context2.sent;
+                value = _ref2.value;
+                done = _ref2.done;
+
+                if (!done) {
+                  _context2.next = 7;
+                  break;
+                }
+
+                return _context2.abrupt("return", {
+                  value: undefined,
+                  done: true
+                });
+
+              case 7:
+                return _context2.abrupt("return", {
+                  value: value.buffer,
+                  done: false
+                });
+
+              case 8:
+              case "end":
+                return _context2.stop();
+            }
+          }
+        }, _callee2, this);
+      }));
+
+      function read() {
+        return _read2.apply(this, arguments);
+      }
+
+      return read;
+    }()
+  }, {
+    key: "cancel",
+    value: function cancel(reason) {
+      this._reader.cancel(reason);
+    }
+  }, {
+    key: "isStreamingSupported",
+    get: function get() {
+      return false;
+    }
+  }]);
+
+  return PDFWorkerStreamRangeReader;
+}();
+
+/***/ })
+/******/ ]);
+});
+//# sourceMappingURL=pdf.worker.js.map
\ No newline at end of file
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/MANIFEST.in b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/MANIFEST.in
new file mode 100644
index 0000000..1925688
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/MANIFEST.in
@@ -0,0 +1,6 @@
+include COPYING
+include MANIFEST.in
+include README
+recursive-include example *.py
+recursive-include mod_pywebsocket *.py
+recursive-include test *.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/README.md b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/README.md
new file mode 100644
index 0000000..8684f2c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/README.md
@@ -0,0 +1,36 @@
+
+# pywebsocket3 #
+
+The pywebsocket project aims to provide a [WebSocket](https://tools.ietf.org/html/rfc6455) standalone server.
+
+pywebsocket is intended for **testing** or **experimental** purposes.
+
+Run this to read the general document:
+```
+$ pydoc mod_pywebsocket
+```
+
+Please see [Wiki](https://github.com/GoogleChromeLabs/pywebsocket3/wiki) for more details.
+
+# INSTALL #
+
+To install this package to the system, run this:
+```
+$ python setup.py build
+$ sudo python setup.py install
+```
+
+To install this package as a normal user, run this instead:
+
+```
+$ python setup.py build
+$ python setup.py install --user
+```
+# LAUNCH #
+
+To use pywebsocket as standalone server, run this to read the document:
+```
+$ pydoc mod_pywebsocket.standalone
+```
+# Disclaimer #
+This is not an officially supported Google product
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/setup.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/setup.py
new file mode 100755
index 0000000..57e9428d
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/third_party/pywebsocket3/setup.py
@@ -0,0 +1,74 @@
+#!/usr/bin/env python
+#
+# Copyright 2012, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+"""Set up script for mod_pywebsocket.
+"""
+
+from __future__ import absolute_import
+from __future__ import print_function
+from setuptools import setup, Extension
+import sys
+
+_PACKAGE_NAME = 'mod_pywebsocket'
+
+# Build and use a C++ extension for faster masking. SWIG is required.
+_USE_FAST_MASKING = False
+
+# This is used since python_requires field is not recognized with
+# pip version 9.0.0 and earlier
+if sys.version < '2.7':
+    print('%s requires Python 2.7 or later.' % _PACKAGE_NAME, file=sys.stderr)
+    sys.exit(1)
+
+if _USE_FAST_MASKING:
+    setup(ext_modules=[
+        Extension('mod_pywebsocket/_fast_masking',
+                  ['mod_pywebsocket/fast_masking.i'],
+                  swig_opts=['-c++'])
+    ])
+
+setup(
+    author='Yuzo Fujishima',
+    author_email='yuzo@chromium.org',
+    description='Standalone WebSocket Server for testing purposes.',
+    long_description=('mod_pywebsocket is a standalone server for '
+                      'the WebSocket Protocol (RFC 6455). '
+                      'See mod_pywebsocket/__init__.py for more detail.'),
+    license='See LICENSE',
+    name=_PACKAGE_NAME,
+    packages=[_PACKAGE_NAME, _PACKAGE_NAME + '.handshake'],
+    python_requires='>=2.7',
+    install_requires=['six'],
+    #TODO(suzukikeita): Update this to new Github URL
+    url='http://code.google.com/p/pywebsocket/',
+    version='3.0.0',
+)
+
+# vi:sts=4 sw=4 et
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/MANIFEST.in b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/MANIFEST.in
new file mode 100644
index 0000000..d36344f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/MANIFEST.in
@@ -0,0 +1,6 @@
+exclude MANIFEST.in
+include requirements.txt
+include wptrunner.default.ini
+include wptrunner/testharness_runner.html
+include wptrunner/*.js
+include wptrunner/executors/*.js
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/README.rst b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/README.rst
new file mode 100644
index 0000000..0adf0a9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/README.rst
@@ -0,0 +1,14 @@
+wptrunner: A web-platform-tests harness
+=======================================
+
+wptrunner is a harness for running the W3C `web-platform-tests testsuite`_.
+
+.. toctree::
+   :maxdepth: 2
+
+   docs/usage
+   docs/expectation
+   docs/design
+   docs/internals
+
+.. _`web-platform-tests testsuite`: https://github.com/web-platform-tests/wpt
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements.txt
new file mode 100644
index 0000000..1dd4174
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements.txt
@@ -0,0 +1,10 @@
+html5lib==1.1
+mozinfo==1.2.1  # https://bugzilla.mozilla.org/show_bug.cgi?id=1621226
+mozlog==7.1.0
+mozdebug==0.2
+# Pillow 7 requires Python 3
+pillow==6.2.2; python_version <= '2.7'  # pyup: <7.0
+pillow==8.1.0; python_version >= '3.0'
+urllib3[secure]==1.26.2
+requests==2.25.1
+six==1.15.0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_android_webview.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_android_webview.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_android_webview.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_android.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_android.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_android.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_ios.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_ios.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_chrome_ios.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge.txt
new file mode 100644
index 0000000..0ef64c2
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge.txt
@@ -0,0 +1,2 @@
+mozprocess==1.2.1
+selenium==3.141.0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge_chromium.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge_chromium.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_edge_chromium.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_epiphany.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_epiphany.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_epiphany.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_firefox.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_firefox.txt
new file mode 100644
index 0000000..43245f9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_firefox.txt
@@ -0,0 +1,10 @@
+marionette_driver==3.1.0
+mozcrash==2.0.0
+mozinstall==2.0.1
+mozleak==0.2
+moznetwork==1.1.0
+mozprocess==1.2.1
+mozprofile==2.5.0
+mozrunner==8.1.0
+mozversion==2.3.0
+psutil==5.8.0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_ie.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_ie.txt
new file mode 100644
index 0000000..0ef64c2
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_ie.txt
@@ -0,0 +1,2 @@
+mozprocess==1.2.1
+selenium==3.141.0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_opera.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_opera.txt
new file mode 100644
index 0000000..0ef64c2
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_opera.txt
@@ -0,0 +1,2 @@
+mozprocess==1.2.1
+selenium==3.141.0
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_safari.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_safari.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_safari.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_sauce.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_sauce.txt
new file mode 100644
index 0000000..eae7ef3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_sauce.txt
@@ -0,0 +1,3 @@
+mozprocess==1.2.1
+selenium==3.141.0
+requests==2.25.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_servo.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_servo.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_servo.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_webkit.txt b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_webkit.txt
new file mode 100644
index 0000000..874980b3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/requirements_webkit.txt
@@ -0,0 +1 @@
+mozprocess==1.2.1
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/setup.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/setup.py
new file mode 100644
index 0000000..a459e2c4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/setup.py
@@ -0,0 +1,72 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+from __future__ import print_function
+
+import glob
+import os
+import sys
+import textwrap
+
+from setuptools import setup, find_packages
+
+here = os.path.dirname(__file__)
+
+PACKAGE_NAME = 'wptrunner'
+PACKAGE_VERSION = '1.14'
+
+# Dependencies
+with open(os.path.join(here, "requirements.txt")) as f:
+    deps = f.read().splitlines()
+
+# Browser-specific requirements
+requirements_files = glob.glob("requirements_*.txt")
+
+profile_dest = None
+dest_exists = False
+
+setup(name=PACKAGE_NAME,
+      version=PACKAGE_VERSION,
+      description="Harness for running the W3C web-platform-tests against various products",
+      author='Mozilla Automation and Testing Team',
+      author_email='tools@lists.mozilla.org',
+      license='MPL 2.0',
+      packages=find_packages(exclude=["tests", "metadata", "prefs"]),
+      entry_points={
+          'console_scripts': [
+              'wptrunner = wptrunner.wptrunner:main',
+              'wptupdate = wptrunner.update:main',
+          ]
+      },
+      zip_safe=False,
+      platforms=['Any'],
+      classifiers=['Development Status :: 4 - Beta',
+                   'Environment :: Console',
+                   'Intended Audience :: Developers',
+                   'License :: OSI Approved :: BSD License',
+                   'Operating System :: OS Independent'],
+      package_data={"wptrunner": ["executors/testharness_marionette.js",
+                                  "executors/testharness_webdriver.js",
+                                  "executors/reftest.js",
+                                  "executors/reftest-wait.js",
+                                  "testharnessreport.js",
+                                  "testharness_runner.html",
+                                  "wptrunner.default.ini",
+                                  "browsers/sauce_setup/*",
+                                  "prefs/*"]},
+      include_package_data=True,
+      data_files=[("requirements", requirements_files)],
+      )
+
+if "install" in sys.argv:
+    path = os.path.relpath(os.path.join(sys.prefix, "requirements"), os.curdir)
+    print(textwrap.fill("""In order to use with one of the built-in browser
+products, you will need to install the extra dependencies. These are provided
+as requirements_[name].txt in the %s directory and can be installed using
+e.g.""" % path, 80))
+
+    print("""
+
+pip install -r %s/requirements_firefox.txt
+""" % path)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/tox.ini b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/tox.ini
new file mode 100644
index 0000000..b39b5eb
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/tox.ini
@@ -0,0 +1,34 @@
+[pytest]
+xfail_strict=true
+
+[tox]
+envlist = py27-{base,chrome,edge,firefox,ie,opera,safari,sauce,servo,webkit,webkitgtk_minibrowser,epiphany},{py35,py36,py37,py38}-base
+skip_missing_interpreters = False
+
+[testenv]
+deps =
+     # Same as tools/third_party/pytest, also the last version that supports Python 2
+     pytest==4.6.11
+     pytest-cov
+     pytest-xdist
+     # mock no longer supports Python 2 since v4
+     mock==3.*
+     -r{toxinidir}/requirements.txt
+     chrome: -r{toxinidir}/requirements_chrome.txt
+     edge: -r{toxinidir}/requirements_edge.txt
+     firefox: -r{toxinidir}/requirements_firefox.txt
+     ie: -r{toxinidir}/requirements_ie.txt
+     opera: -r{toxinidir}/requirements_opera.txt
+     safari: -r{toxinidir}/requirements_safari.txt
+     sauce: -r{toxinidir}/requirements_sauce.txt
+     servo: -r{toxinidir}/requirements_servo.txt
+     webkit: -r{toxinidir}/requirements_webkit.txt
+     webkitgtk_minibrowser: -r{toxinidir}/requirements_webkit.txt
+     epiphany: -r{toxinidir}/requirements_epiphany.txt
+
+commands = pytest {posargs}
+
+setenv = CURRENT_TOX_ENV = {envname}
+
+passenv =
+  TASKCLUSTER_ROOT_URL
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner.default.ini b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner.default.ini
new file mode 100644
index 0000000..19462bc
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner.default.ini
@@ -0,0 +1,11 @@
+[products]
+
+[web-platform-tests]
+remote_url = https://github.com/web-platform-tests/wpt.git
+branch = master
+sync_path = %(pwd)s/sync
+
+[manifest:default]
+tests = %(pwd)s/tests
+metadata = %(pwd)s/meta
+url_base = /
\ No newline at end of file
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/__init__.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/__init__.py
new file mode 100644
index 0000000..da68ddb
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/__init__.py
@@ -0,0 +1,43 @@
+"""Subpackage where each product is defined. Each product is created by adding a
+a .py file containing a __wptrunner__ variable in the global scope. This must be
+a dictionary with the fields
+
+"product": Name of the product, assumed to be unique.
+"browser": String indicating the Browser implementation used to launch that
+           product.
+"executor": Dictionary with keys as supported test types and values as the name
+            of the Executor implementation that will be used to run that test
+            type.
+"browser_kwargs": String naming function that takes product, binary,
+                  prefs_root and the wptrunner.run_tests kwargs dict as arguments
+                  and returns a dictionary of kwargs to use when creating the
+                  Browser class.
+"executor_kwargs": String naming a function that takes http server url and
+                   timeout multiplier and returns kwargs to use when creating
+                   the executor class.
+"env_options": String naming a function of no arguments that returns the
+               arguments passed to the TestEnvironment.
+
+All classes and functions named in the above dict must be imported into the
+module global scope.
+"""
+
+product_list = ["android_weblayer",
+                "android_webview",
+                "chrome",
+                "chrome_android",
+                "chrome_ios",
+                "edgechromium",
+                "edge",
+                "edge_webdriver",
+                "firefox",
+                "firefox_android",
+                "ie",
+                "safari",
+                "sauce",
+                "servo",
+                "servodriver",
+                "opera",
+                "webkit",
+                "webkitgtk_minibrowser",
+                "epiphany"]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py
new file mode 100644
index 0000000..f68312f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_weblayer.py
@@ -0,0 +1,134 @@
+import subprocess
+
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from .chrome import executor_kwargs as chrome_executor_kwargs
+from ..webdriver_server import ChromeDriverServer
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+from ..executors.executorchrome import ChromeDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "android_weblayer",
+                 "check_args": "check_args",
+                 "browser": "WeblayerShell",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "ChromeDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+_wptserve_ports = set()
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "device_serial": kwargs["device_serial"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    # Use update() to modify the global list in place.
+    _wptserve_ports.update(set(
+        server_config['ports']['http'] + server_config['ports']['https'] +
+        server_config['ports']['ws'] + server_config['ports']['wss']
+    ))
+
+    executor_kwargs = chrome_executor_kwargs(logger, test_type, server_config,
+                                             cache_manager, run_info_data,
+                                             **kwargs)
+    del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"]
+    capabilities = executor_kwargs["capabilities"]
+    # Note that for WebLayer, we launch a test shell and have the test shell use
+    # WebLayer.
+    # https://cs.chromium.org/chromium/src/weblayer/shell/android/shell_apk/
+    capabilities["goog:chromeOptions"]["androidPackage"] = \
+        "org.chromium.weblayer.shell"
+    capabilities["goog:chromeOptions"]["androidActivity"] = ".WebLayerShellActivity"
+    if kwargs.get('device_serial'):
+        capabilities["goog:chromeOptions"]["androidDeviceSerial"] = kwargs['device_serial']
+
+    # Workaround: driver.quit() cannot quit WeblayerShell.
+    executor_kwargs["pause_after_test"] = False
+    # Workaround: driver.close() is not supported.
+    executor_kwargs["restart_after_test"] = True
+    executor_kwargs["close_after_done"] = False
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file
+    return {"server_host": "127.0.0.1"}
+
+
+#TODO: refactor common elements of WeblayerShell and ChromeAndroidBrowser
+class WeblayerShell(Browser):
+    """Chrome is backed by chromedriver, which is supplied through
+    ``wptrunner.webdriver.ChromeDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary="chromedriver",
+                 device_serial=None,
+                 webdriver_args=None):
+        """Creates a new representation of Chrome.  The `binary` argument gives
+        the browser binary to use for testing."""
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.device_serial = device_serial
+        self.server = ChromeDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+        self.setup_adb_reverse()
+
+    def _adb_run(self, args):
+        cmd = ['adb']
+        if self.device_serial:
+            cmd.extend(['-s', self.device_serial])
+        cmd.extend(args)
+        self.logger.info(' '.join(cmd))
+        subprocess.check_call(cmd)
+
+    def setup_adb_reverse(self):
+        self._adb_run(['wait-for-device'])
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+        # "adb reverse" basically forwards network connection from device to
+        # host.
+        for port in _wptserve_ports:
+            self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port])
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
new file mode 100644
index 0000000..3cde248b
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/android_webview.py
@@ -0,0 +1,133 @@
+import subprocess
+
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from .chrome import executor_kwargs as chrome_executor_kwargs
+from ..webdriver_server import ChromeDriverServer
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+from ..executors.executorchrome import ChromeDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "android_webview",
+                 "check_args": "check_args",
+                 "browser": "SystemWebViewShell",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "ChromeDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+_wptserve_ports = set()
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "device_serial": kwargs["device_serial"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    # Use update() to modify the global list in place.
+    _wptserve_ports.update(set(
+        server_config['ports']['http'] + server_config['ports']['https'] +
+        server_config['ports']['ws'] + server_config['ports']['wss']
+    ))
+
+    executor_kwargs = chrome_executor_kwargs(logger, test_type, server_config,
+                                             cache_manager, run_info_data,
+                                             **kwargs)
+    del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"]
+    capabilities = executor_kwargs["capabilities"]
+    # Note that for WebView, we launch a test shell and have the test shell use WebView.
+    # https://chromium.googlesource.com/chromium/src/+/HEAD/android_webview/docs/webview-shell.md
+    capabilities["goog:chromeOptions"]["androidPackage"] = \
+        "org.chromium.webview_shell"
+    capabilities["goog:chromeOptions"]["androidActivity"] = ".WebPlatformTestsActivity"
+    if kwargs.get('device_serial'):
+        capabilities["goog:chromeOptions"]["androidDeviceSerial"] = kwargs['device_serial']
+
+    # Workaround: driver.quit() cannot quit SystemWebViewShell.
+    executor_kwargs["pause_after_test"] = False
+    # Workaround: driver.close() is not supported.
+    executor_kwargs["restart_after_test"] = True
+    executor_kwargs["close_after_done"] = False
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file
+    return {"server_host": "127.0.0.1"}
+
+
+#TODO: refactor common elements of SystemWebViewShell and ChromeAndroidBrowser
+class SystemWebViewShell(Browser):
+    """Chrome is backed by chromedriver, which is supplied through
+    ``wptrunner.webdriver.ChromeDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary="chromedriver",
+                 device_serial=None,
+                 webdriver_args=None):
+        """Creates a new representation of Chrome.  The `binary` argument gives
+        the browser binary to use for testing."""
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.device_serial = device_serial
+        self.server = ChromeDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+        self.setup_adb_reverse()
+
+    def _adb_run(self, args):
+        cmd = ['adb']
+        if self.device_serial:
+            cmd.extend(['-s', self.device_serial])
+        cmd.extend(args)
+        self.logger.info(' '.join(cmd))
+        subprocess.check_call(cmd)
+
+    def setup_adb_reverse(self):
+        self._adb_run(['wait-for-device'])
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+        # "adb reverse" basically forwards network connection from device to
+        # host.
+        for port in _wptserve_ports:
+            self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port])
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/base.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/base.py
new file mode 100644
index 0000000..f2205b16
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/base.py
@@ -0,0 +1,206 @@
+import os
+import platform
+import socket
+from abc import ABCMeta, abstractmethod
+from copy import deepcopy
+from six import iteritems
+
+from ..wptcommandline import require_arg  # noqa: F401
+
+here = os.path.dirname(__file__)
+
+
+def inherit(super_module, child_globals, product_name):
+    super_wptrunner = super_module.__wptrunner__
+    child_globals["__wptrunner__"] = child_wptrunner = deepcopy(super_wptrunner)
+
+    child_wptrunner["product"] = product_name
+
+    for k in ("check_args", "browser", "browser_kwargs", "executor_kwargs",
+              "env_extras", "env_options", "timeout_multiplier"):
+        attr = super_wptrunner[k]
+        child_globals[attr] = getattr(super_module, attr)
+
+    for v in super_module.__wptrunner__["executor"].values():
+        child_globals[v] = getattr(super_module, v)
+
+    if "run_info_extras" in super_wptrunner:
+        attr = super_wptrunner["run_info_extras"]
+        child_globals[attr] = getattr(super_module, attr)
+
+
+def cmd_arg(name, value=None):
+    prefix = "-" if platform.system() == "Windows" else "--"
+    rv = prefix + name
+    if value is not None:
+        rv += "=" + value
+    return rv
+
+
+def maybe_add_args(required_args, current_args):
+    for required_arg in required_args:
+        # If the arg is in the form of "variable=value", only add it if
+        # no arg with another value for "variable" is already there.
+        if "=" in required_arg:
+            required_arg_prefix = "%s=" % required_arg.split("=")[0]
+            if not any(item.startswith(required_arg_prefix) for item in current_args):
+                current_args.append(required_arg)
+        else:
+            if required_arg not in current_args:
+                current_args.append(required_arg)
+    return current_args
+
+
+def certificate_domain_list(list_of_domains, certificate_file):
+    """Build a list of domains where certificate_file should be used"""
+    cert_list = []
+    for domain in list_of_domains:
+        cert_list.append({"host": domain, "certificateFile": certificate_file})
+    return cert_list
+
+
+def get_free_port():
+    """Get a random unbound port"""
+    while True:
+        s = socket.socket()
+        try:
+            s.bind(("127.0.0.1", 0))
+        except socket.error:
+            continue
+        else:
+            return s.getsockname()[1]
+        finally:
+            s.close()
+
+
+def get_timeout_multiplier(test_type, run_info_data, **kwargs):
+    if kwargs["timeout_multiplier"] is not None:
+        return kwargs["timeout_multiplier"]
+    return 1
+
+
+def browser_command(binary, args, debug_info):
+    if debug_info:
+        if debug_info.requiresEscapedArgs:
+            args = [item.replace("&", "\\&") for item in args]
+        debug_args = [debug_info.path] + debug_info.args
+    else:
+        debug_args = []
+
+    command = [binary] + args
+
+    return debug_args, command
+
+
+class BrowserError(Exception):
+    pass
+
+
+class Browser(object):
+    """Abstract class serving as the basis for Browser implementations.
+
+    The Browser is used in the TestRunnerManager to start and stop the browser
+    process, and to check the state of that process. This class also acts as a
+    context manager, enabling it to do browser-specific setup at the start of
+    the testrun and cleanup after the run is complete.
+
+    :param logger: Structured logger to use for output.
+    """
+    __metaclass__ = ABCMeta
+
+    process_cls = None
+    init_timeout = 30
+
+    def __init__(self, logger):
+        self.logger = logger
+
+    def __enter__(self):
+        self.setup()
+        return self
+
+    def __exit__(self, *args, **kwargs):
+        self.cleanup()
+
+    def setup(self):
+        """Used for browser-specific setup that happens at the start of a test run"""
+        pass
+
+    def settings(self, test):
+        """Dictionary of metadata that is constant for a specific launch of a browser.
+
+        This is used to determine when the browser instance configuration changes, requiring
+        a relaunch of the browser. The test runner calls this method for each test, and if the
+        returned value differs from that for the previous test, the browser is relaunched.
+        """
+        return {}
+
+    @abstractmethod
+    def start(self, group_metadata, **kwargs):
+        """Launch the browser object and get it into a state where is is ready to run tests"""
+        pass
+
+    @abstractmethod
+    def stop(self, force=False):
+        """Stop the running browser process."""
+        pass
+
+    @abstractmethod
+    def pid(self):
+        """pid of the browser process or None if there is no pid"""
+        pass
+
+    @abstractmethod
+    def is_alive(self):
+        """Boolean indicating whether the browser process is still running"""
+        pass
+
+    def cleanup(self):
+        """Browser-specific cleanup that is run after the testrun is finished"""
+        pass
+
+    def executor_browser(self):
+        """Returns the ExecutorBrowser subclass for this Browser subclass and the keyword arguments
+        with which it should be instantiated"""
+        return ExecutorBrowser, {}
+
+    def check_crash(self, process, test):
+        """Check if a crash occured and output any useful information to the
+        log. Returns a boolean indicating whether a crash occured."""
+        return False
+
+
+class NullBrowser(Browser):
+    def __init__(self, logger, **kwargs):
+        super(NullBrowser, self).__init__(logger)
+
+    def start(self, **kwargs):
+        """No-op browser to use in scenarios where the TestRunnerManager shouldn't
+        actually own the browser process (e.g. Servo where we start one browser
+        per test)"""
+        pass
+
+    def stop(self, force=False):
+        pass
+
+    def pid(self):
+        return None
+
+    def is_alive(self):
+        return True
+
+    def on_output(self, line):
+        raise NotImplementedError
+
+
+class ExecutorBrowser(object):
+    """View of the Browser used by the Executor object.
+    This is needed because the Executor runs in a child process and
+    we can't ship Browser instances between processes on Windows.
+
+    Typically this will have a few product-specific properties set,
+    but in some cases it may have more elaborate methods for setting
+    up the browser from the runner process.
+    """
+    def __init__(self, **kwargs):
+        for k, v in iteritems(kwargs):
+            setattr(self, k, v)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
new file mode 100644
index 0000000..d3e27a9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome.py
@@ -0,0 +1,144 @@
+from . import chrome_spki_certs
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import ChromeDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
+from ..executors.executorchrome import (ChromeDriverWdspecExecutor,  # noqa: F401
+                                        ChromeDriverPrintRefTestExecutor)  # noqa: F401
+
+
+__wptrunner__ = {"product": "chrome",
+                 "check_args": "check_args",
+                 "browser": "ChromeBrowser",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "print-reftest": "ChromeDriverPrintRefTestExecutor",
+                              "wdspec": "ChromeDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier",}
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data,
+                                           **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["supports_eager_pageload"] = False
+
+    capabilities = {
+        "goog:chromeOptions": {
+            "prefs": {
+                "profile": {
+                    "default_content_setting_values": {
+                        "popups": 1
+                    }
+                }
+            },
+            "excludeSwitches": ["enable-automation"],
+            "w3c": True
+        }
+    }
+
+    if test_type == "testharness":
+        capabilities["pageLoadStrategy"] = "none"
+
+    chrome_options = capabilities["goog:chromeOptions"]
+    if kwargs["binary"] is not None:
+        chrome_options["binary"] = kwargs["binary"]
+
+    # Here we set a few Chrome flags that are always passed.
+    # ChromeDriver's "acceptInsecureCerts" capability only controls the current
+    # browsing context, whereas the CLI flag works for workers, too.
+    chrome_options["args"] = []
+
+    chrome_options["args"].append("--ignore-certificate-errors-spki-list=%s" %
+                                  ','.join(chrome_spki_certs.IGNORE_CERTIFICATE_ERRORS_SPKI_LIST))
+
+    # Allow audio autoplay without a user gesture.
+    chrome_options["args"].append("--autoplay-policy=no-user-gesture-required")
+    # Allow WebRTC tests to call getUserMedia.
+    chrome_options["args"].append("--use-fake-ui-for-media-stream")
+    chrome_options["args"].append("--use-fake-device-for-media-stream")
+    # Shorten delay for Reporting <https://w3c.github.io/reporting/>.
+    chrome_options["args"].append("--short-reporting-delay")
+    # Point all .test domains to localhost for Chrome
+    chrome_options["args"].append("--host-resolver-rules=MAP nonexistent.*.test ~NOTFOUND, MAP *.test 127.0.0.1")
+
+    if kwargs["enable_mojojs"]:
+        chrome_options["args"].append("--enable-blink-features=MojoJS,MojoJSTest")
+
+    # Copy over any other flags that were passed in via --binary_args
+    if kwargs["binary_args"] is not None:
+        chrome_options["args"].extend(kwargs["binary_args"])
+
+    # Pass the --headless flag to Chrome if WPT's own --headless flag was set
+    # or if we're running print reftests because of crbug.com/753118
+    if ((kwargs["headless"] or test_type == "print-reftest") and
+        "--headless" not in chrome_options["args"]):
+        chrome_options["args"].append("--headless")
+
+    executor_kwargs["capabilities"] = capabilities
+
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {"server_host": "127.0.0.1"}
+
+
+class ChromeBrowser(Browser):
+    """Chrome is backed by chromedriver, which is supplied through
+    ``wptrunner.webdriver.ChromeDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary="chromedriver",
+                 webdriver_args=None):
+        """Creates a new representation of Chrome.  The `binary` argument gives
+        the browser binary to use for testing."""
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.server = ChromeDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py
new file mode 100644
index 0000000..d7e3e210
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_android.py
@@ -0,0 +1,124 @@
+import subprocess
+
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from .chrome import executor_kwargs as chrome_executor_kwargs
+from ..webdriver_server import ChromeDriverServer
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+from ..executors.executorchrome import ChromeDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "chrome_android",
+                 "check_args": "check_args",
+                 "browser": "ChromeAndroidBrowser",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "ChromeDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+_wptserve_ports = set()
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "package_name")
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"package_name": kwargs["package_name"],
+            "device_serial": kwargs["device_serial"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    # Use update() to modify the global list in place.
+    _wptserve_ports.update(set(
+        server_config['ports']['http'] + server_config['ports']['https'] +
+        server_config['ports']['ws'] + server_config['ports']['wss']
+    ))
+
+    executor_kwargs = chrome_executor_kwargs(logger, test_type, server_config,
+                                             cache_manager, run_info_data,
+                                             **kwargs)
+    # Remove unsupported options on mobile.
+    del executor_kwargs["capabilities"]["goog:chromeOptions"]["prefs"]
+
+    assert kwargs["package_name"], "missing --package-name"
+    executor_kwargs["capabilities"]["goog:chromeOptions"]["androidPackage"] = \
+        kwargs["package_name"]
+    if kwargs.get("device_serial"):
+        executor_kwargs["capabilities"]["goog:chromeOptions"]["androidDeviceSerial"] = \
+            kwargs["device_serial"]
+
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    # allow the use of host-resolver-rules in lieu of modifying /etc/hosts file
+    return {"server_host": "127.0.0.1"}
+
+
+class ChromeAndroidBrowser(Browser):
+    """Chrome is backed by chromedriver, which is supplied through
+    ``wptrunner.webdriver.ChromeDriverServer``.
+    """
+
+    def __init__(self, logger, package_name, webdriver_binary="chromedriver",
+                 device_serial=None, webdriver_args=None):
+        Browser.__init__(self, logger)
+        self.package_name = package_name
+        self.device_serial = device_serial
+        self.server = ChromeDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+        self.setup_adb_reverse()
+
+    def _adb_run(self, args):
+        cmd = ['adb']
+        if self.device_serial:
+            cmd.extend(['-s', self.device_serial])
+        cmd.extend(args)
+        self.logger.info(' '.join(cmd))
+        subprocess.check_call(cmd)
+
+    def setup_adb_reverse(self):
+        self._adb_run(['wait-for-device'])
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+        # "adb reverse" forwards network connection from device to host.
+        for port in _wptserve_ports:
+            self._adb_run(['reverse', 'tcp:%d' % port, 'tcp:%d' % port])
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+        self._adb_run(['forward', '--remove-all'])
+        self._adb_run(['reverse', '--remove-all'])
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
new file mode 100644
index 0000000..ecdbc3a
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_ios.py
@@ -0,0 +1,80 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import CWTChromeDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+from ..executors.executorchrome import ChromeDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "chrome_ios",
+                 "check_args": "check_args",
+                 "browser": "ChromeiOSBrowser",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config, cache_manager, run_info_data,
+                                           **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = {}
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+class ChromeiOSBrowser(Browser):
+    """ChromeiOS is backed by CWTChromeDriver, which is supplied through
+    ``wptrunner.webdriver.CWTChromeDriverServer``.
+    """
+
+    init_timeout = 120
+
+    def __init__(self, logger, webdriver_binary, webdriver_args=None):
+        """Creates a new representation of Chrome."""
+        Browser.__init__(self, logger)
+        self.server = CWTChromeDriverServer(self.logger,
+                                            binary=webdriver_binary,
+                                            args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
new file mode 100644
index 0000000..ef67c0c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/chrome_spki_certs.py
@@ -0,0 +1,13 @@
+# This file is automatically generated by 'wpt regen-certs'
+# DO NOT EDIT MANUALLY.
+
+# tools/certs/web-platform.test.pem
+WPT_FINGERPRINT = 'jLyENXJPaWkMd5jvkdeZNBCDxmlrsaejX6b9sUNA6Kc='
+
+# signed-exchange/resources/127.0.0.1.sxg.pem
+SXG_WPT_FINGERPRINT = '0Rt4mT6SJXojEMHTnKnlJ/hBKMBcI4kteBlhR1eTTdk='
+
+IGNORE_CERTIFICATE_ERRORS_SPKI_LIST = [
+    WPT_FINGERPRINT,
+    SXG_WPT_FINGERPRINT
+]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge.py
new file mode 100644
index 0000000..b908684
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge.py
@@ -0,0 +1,131 @@
+from __future__ import print_function
+import time
+import subprocess
+from .base import Browser, ExecutorBrowser, require_arg
+from ..webdriver_server import EdgeDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorselenium import (SeleniumTestharnessExecutor,  # noqa: F401
+                                          SeleniumRefTestExecutor)  # noqa: F401
+from ..executors.executoredge import EdgeDriverWdspecExecutor  # noqa: F401
+
+__wptrunner__ = {"product": "edge",
+                 "check_args": "check_args",
+                 "browser": "EdgeBrowser",
+                 "executor": {"testharness": "SeleniumTestharnessExecutor",
+                              "reftest": "SeleniumRefTestExecutor",
+                              "wdspec": "EdgeDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def get_timeout_multiplier(test_type, run_info_data, **kwargs):
+    if kwargs["timeout_multiplier"] is not None:
+        return kwargs["timeout_multiplier"]
+    if test_type == "wdspec":
+        return 10
+    return 1
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args"),
+            "timeout_multiplier": get_timeout_multiplier(test_type,
+                                                         run_info_data,
+                                                         **kwargs)}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["timeout_multiplier"] = get_timeout_multiplier(test_type,
+                                                                   run_info_data,
+                                                                   **kwargs)
+    executor_kwargs["capabilities"] = {}
+    if test_type == "testharness":
+        executor_kwargs["capabilities"]["pageLoadStrategy"] = "eager"
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {"supports_debugger": False}
+
+
+class EdgeBrowser(Browser):
+    used_ports = set()
+    init_timeout = 60
+
+    def __init__(self, logger, webdriver_binary, timeout_multiplier=None, webdriver_args=None):
+        Browser.__init__(self, logger)
+        self.server = EdgeDriverServer(self.logger,
+                                       binary=webdriver_binary,
+                                       args=webdriver_args)
+        self.webdriver_host = "localhost"
+        self.webdriver_port = self.server.port
+        if timeout_multiplier:
+            self.init_timeout = self.init_timeout * timeout_multiplier
+
+
+    def start(self, **kwargs):
+        print(self.server.url)
+        self.server.start()
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+        # Wait for Edge browser process to exit if driver process is found
+        edge_proc_name = 'MicrosoftEdge.exe'
+        for i in range(0,5):
+            procs = subprocess.check_output(['tasklist', '/fi', 'ImageName eq ' + edge_proc_name])
+            if b'MicrosoftWebDriver.exe' not in procs:
+                # Edge driver process already exited, don't wait for browser process to exit
+                break
+            elif edge_proc_name.encode() in procs:
+                time.sleep(0.5)
+            else:
+                break
+
+        if edge_proc_name.encode() in procs:
+            # close Edge process if it is still running
+            subprocess.call(['taskkill.exe', '/f', '/im', 'microsoftedge*'])
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the server is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
+
+
+def run_info_extras(**kwargs):
+    osReleaseCommand = r"(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').ReleaseId"
+    osBuildCommand = r"(Get-ItemProperty 'HKLM:\Software\Microsoft\Windows NT\CurrentVersion').BuildLabEx"
+    try:
+        os_release = subprocess.check_output(["powershell.exe", osReleaseCommand]).strip()
+        os_build = subprocess.check_output(["powershell.exe", osBuildCommand]).strip()
+    except (subprocess.CalledProcessError, OSError):
+        return {}
+
+    rv = {"os_build": os_build,
+          "os_release": os_release}
+    return rv
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge_webdriver.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge_webdriver.py
new file mode 100644
index 0000000..c2545de4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edge_webdriver.py
@@ -0,0 +1,12 @@
+from .base import inherit
+from . import edge
+
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+
+
+inherit(edge, globals(), "edge_webdriver")
+
+# __wptrunner__ magically appears from inherit, F821 is undefined name
+__wptrunner__["executor"]["testharness"] = "WebDriverTestharnessExecutor"  # noqa: F821
+__wptrunner__["executor"]["reftest"] = "WebDriverRefTestExecutor"  # noqa: F821
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py
new file mode 100644
index 0000000..1d45983
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/edgechromium.py
@@ -0,0 +1,116 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import EdgeChromiumDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor)  # noqa: F401
+from ..executors.executoredgechromium import EdgeChromiumDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "edgechromium",
+                 "check_args": "check_args",
+                 "browser": "EdgeChromiumBrowser",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "EdgeChromiumDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier",}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data,
+                                           **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["supports_eager_pageload"] = False
+
+    capabilities = {
+        "ms:edgeOptions": {
+            "prefs": {
+                "profile": {
+                    "default_content_setting_values": {
+                        "popups": 1
+                    }
+                }
+            },
+            "useAutomationExtension": False,
+            "excludeSwitches": ["enable-automation"],
+            "w3c": True
+        }
+    }
+
+    if test_type == "testharness":
+        capabilities["pageLoadStrategy"] = "none"
+
+    for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
+        if kwargs[kwarg] is not None:
+            capabilities["ms:edgeOptions"][capability] = kwargs[kwarg]
+
+    if kwargs["headless"]:
+        if "args" not in capabilities["ms:edgeOptions"]:
+            capabilities["ms:edgeOptions"]["args"] = []
+        if "--headless" not in capabilities["ms:edgeOptions"]["args"]:
+            capabilities["ms:edgeOptions"]["args"].append("--headless")
+
+    executor_kwargs["capabilities"] = capabilities
+
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+class EdgeChromiumBrowser(Browser):
+    """MicrosoftEdge is backed by MSEdgeDriver, which is supplied through
+    ``wptrunner.webdriver.EdgeChromiumDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary="msedgedriver",
+                 webdriver_args=None):
+        """Creates a new representation of MicrosoftEdge.  The `binary` argument gives
+        the browser binary to use for testing."""
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.server = EdgeChromiumDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py
new file mode 100644
index 0000000..a338443
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/epiphany.py
@@ -0,0 +1,77 @@
+from .base import get_timeout_multiplier, maybe_add_args, certificate_domain_list  # noqa: F401
+from .webkit import WebKitBrowser
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
+from ..executors.executorwebkit import WebKitDriverWdspecExecutor  # noqa: F401
+
+__wptrunner__ = {"product": "epiphany",
+                 "check_args": "check_args",
+                 "browser": "EpiphanyBrowser",
+                 "browser_kwargs": "browser_kwargs",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "WebKitDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    pass
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172
+    webdriver_required_args = ["--host=127.0.0.1"]
+    webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args"))
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": webdriver_args}
+
+
+def capabilities(server_config, **kwargs):
+    args = kwargs.get("binary_args", [])
+    if "--automation-mode" not in args:
+        args.append("--automation-mode")
+
+    return {
+        "browserName": "Epiphany",
+        "browserVersion": "3.31.4",  # First version to support automation
+        "platformName": "ANY",
+        "webkitgtk:browserOptions": {
+            "binary": kwargs["binary"],
+            "args": args,
+            "certificates": certificate_domain_list(server_config.domains_set, kwargs["host_cert_path"])}}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = capabilities(server_config, **kwargs)
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+def run_info_extras(**kwargs):
+    return {"webkit_port": "gtk"}
+
+
+class EpiphanyBrowser(WebKitBrowser):
+    def __init__(self, logger, binary=None, webdriver_binary=None,
+                 webdriver_args=None):
+        WebKitBrowser.__init__(self, logger, binary, webdriver_binary,
+                               webdriver_args)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
new file mode 100644
index 0000000..b8f1c7d8
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox.py
@@ -0,0 +1,810 @@
+import json
+import os
+import platform
+import signal
+import subprocess
+import sys
+from abc import ABCMeta, abstractmethod
+
+import mozinfo
+import mozleak
+import mozversion
+from mozprocess import ProcessHandler
+from mozprofile import FirefoxProfile, Preferences
+from mozrunner import FirefoxRunner
+from mozrunner.utils import test_environment, get_stack_fixer_function
+from mozcrash import mozcrash
+
+from .base import (get_free_port,
+                   Browser,
+                   ExecutorBrowser,
+                   require_arg,
+                   cmd_arg,
+                   browser_command)
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executormarionette import (MarionetteTestharnessExecutor,  # noqa: F401
+                                            MarionetteRefTestExecutor,  # noqa: F401
+                                            MarionettePrintRefTestExecutor,  # noqa: F401
+                                            MarionetteWdspecExecutor,  # noqa: F401
+                                            MarionetteCrashtestExecutor)  # noqa: F401
+from ..process import cast_env
+
+
+here = os.path.dirname(__file__)
+
+__wptrunner__ = {"product": "firefox",
+                 "check_args": "check_args",
+                 "browser": "FirefoxBrowser",
+                 "executor": {"crashtest": "MarionetteCrashtestExecutor",
+                              "testharness": "MarionetteTestharnessExecutor",
+                              "reftest": "MarionetteRefTestExecutor",
+                              "print-reftest": "MarionettePrintRefTestExecutor",
+                              "wdspec": "MarionetteWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "update_properties": "update_properties",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def get_timeout_multiplier(test_type, run_info_data, **kwargs):
+    if kwargs["timeout_multiplier"] is not None:
+        return kwargs["timeout_multiplier"]
+    if test_type == "reftest":
+        if run_info_data["debug"] or run_info_data.get("asan"):
+            return 4
+        else:
+            return 2
+    elif run_info_data["debug"] or run_info_data.get("asan"):
+        if run_info_data.get("ccov"):
+            return 4
+        else:
+            return 3
+    elif run_info_data["os"] == "android":
+        return 4
+    # https://bugzilla.mozilla.org/show_bug.cgi?id=1538725
+    elif run_info_data["os"] == "win" and run_info_data["processor"] == "aarch64":
+        return 4
+    elif run_info_data.get("ccov"):
+        return 2
+    return 1
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "prefs_root": kwargs["prefs_root"],
+            "extra_prefs": kwargs["extra_prefs"],
+            "test_type": test_type,
+            "debug_info": kwargs["debug_info"],
+            "symbols_path": kwargs["symbols_path"],
+            "stackwalk_binary": kwargs["stackwalk_binary"],
+            "certutil_binary": kwargs["certutil_binary"],
+            "ca_certificate_path": config.ssl_config["ca_cert_path"],
+            "e10s": kwargs["gecko_e10s"],
+            "enable_webrender": kwargs["enable_webrender"],
+            "enable_fission": kwargs["enable_fission"],
+            "stackfix_dir": kwargs["stackfix_dir"],
+            "binary_args": kwargs["binary_args"],
+            "timeout_multiplier": get_timeout_multiplier(test_type,
+                                                         run_info_data,
+                                                         **kwargs),
+            "leak_check": run_info_data["debug"] and (kwargs["leak_check"] is not False),
+            "asan": run_info_data.get("asan"),
+            "stylo_threads": kwargs["stylo_threads"],
+            "chaos_mode_flags": kwargs["chaos_mode_flags"],
+            "config": config,
+            "browser_channel": kwargs["browser_channel"],
+            "headless": kwargs["headless"],
+            "preload_browser": kwargs["preload_browser"],
+            "specialpowers_path": kwargs["specialpowers_path"]}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data,
+                                           **kwargs)
+    executor_kwargs["close_after_done"] = test_type != "reftest"
+    executor_kwargs["timeout_multiplier"] = get_timeout_multiplier(test_type,
+                                                                   run_info_data,
+                                                                   **kwargs)
+    executor_kwargs["e10s"] = run_info_data["e10s"]
+    capabilities = {}
+    if test_type == "testharness":
+        capabilities["pageLoadStrategy"] = "eager"
+    if test_type in ("reftest", "print-reftest"):
+        executor_kwargs["reftest_internal"] = kwargs["reftest_internal"]
+        executor_kwargs["reftest_screenshot"] = kwargs["reftest_screenshot"]
+    if test_type == "wdspec":
+        options = {}
+        if kwargs["binary"]:
+            options["binary"] = kwargs["binary"]
+        if kwargs["binary_args"]:
+            options["args"] = kwargs["binary_args"]
+        if kwargs["headless"]:
+            if "args" not in options:
+                options["args"] = []
+            if "--headless" not in options["args"]:
+                options["args"].append("--headless")
+        options["prefs"] = {
+            "network.dns.localDomains": ",".join(server_config.domains_set)
+        }
+        for pref, value in kwargs["extra_prefs"]:
+            options["prefs"].update({pref: Preferences.cast(value)})
+        capabilities["moz:firefoxOptions"] = options
+
+        # This gets reused for firefox_android, but the environment setup
+        # isn't required in that case
+        if kwargs["binary"]:
+            environ = get_environ(logger,
+                                  kwargs["binary"],
+                                  kwargs["debug_info"],
+                                  kwargs["stylo_threads"],
+                                  kwargs["headless"],
+                                  kwargs["enable_webrender"],
+                                  kwargs["chaos_mode_flags"])
+
+            executor_kwargs["environ"] = environ
+    if kwargs["certutil_binary"] is None:
+        capabilities["acceptInsecureCerts"] = True
+    if capabilities:
+        executor_kwargs["capabilities"] = capabilities
+    executor_kwargs["debug"] = run_info_data["debug"]
+    executor_kwargs["ccov"] = run_info_data.get("ccov", False)
+    executor_kwargs["browser_version"] = run_info_data.get("browser_version")
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    # The server host is set to 127.0.0.1 as Firefox is configured (through the
+    # network.dns.localDomains preference set below) to resolve the test
+    # domains to localhost without relying on the network stack.
+    #
+    # https://github.com/web-platform-tests/wpt/pull/9480
+    return {"server_host": "127.0.0.1",
+            "supports_debugger": True}
+
+
+def run_info_extras(**kwargs):
+
+    def get_bool_pref_if_exists(pref):
+        for key, value in kwargs.get('extra_prefs', []):
+            if pref == key:
+                return value.lower() in ('true', '1')
+        return None
+
+    def get_bool_pref(pref):
+        pref_value = get_bool_pref_if_exists(pref)
+        return pref_value if pref_value is not None else False
+
+    rv = {"e10s": kwargs["gecko_e10s"],
+          "wasm": kwargs.get("wasm", True),
+          "verify": kwargs["verify"],
+          "headless": kwargs.get("headless", False) or "MOZ_HEADLESS" in os.environ,
+          "sw-e10s": True,
+          "fission": kwargs.get("enable_fission") or get_bool_pref("fission.autostart"),
+          "sessionHistoryInParent": (kwargs.get("enable_fission") or
+                                     get_bool_pref("fission.autostart") or
+                                     get_bool_pref("fission.sessionHistoryInParent"))}
+
+    # The value of `sw-e10s` defaults to whether the "parent_intercept"
+    # implementation is enabled for the current build. This value, however,
+    # can be overridden by explicitly setting the pref with the `--setpref` CLI
+    # flag, which is checked here.
+    sw_e10s_override = get_bool_pref_if_exists("dom.serviceWorkers.parent_intercept")
+    if sw_e10s_override is not None:
+        rv["sw-e10s"] = sw_e10s_override
+
+    rv.update(run_info_browser_version(**kwargs))
+
+    return rv
+
+
+def run_info_browser_version(**kwargs):
+    try:
+        version_info = mozversion.get_version(kwargs["binary"])
+    except mozversion.errors.VersionError:
+        version_info = None
+    if version_info:
+        rv = {"browser_build_id": version_info.get("application_buildid", None),
+              "browser_changeset": version_info.get("application_changeset", None)}
+        if "browser_version" not in kwargs:
+            rv["browser_version"] = version_info.get("application_version")
+        return rv
+    return {}
+
+
+def update_properties():
+    return (["os", "debug", "webrender", "fission", "e10s", "sw-e10s", "processor"],
+            {"os": ["version"], "processor": ["bits"]})
+
+
+def get_environ(logger, binary, debug_info, stylo_threads, headless, enable_webrender,
+                chaos_mode_flags=None):
+    env = test_environment(xrePath=os.path.abspath(os.path.dirname(binary)),
+                           debugger=debug_info is not None,
+                           useLSan=True,
+                           log=logger)
+
+    env["STYLO_THREADS"] = str(stylo_threads)
+    if chaos_mode_flags is not None:
+        env["MOZ_CHAOSMODE"] = str(chaos_mode_flags)
+    if headless:
+        env["MOZ_HEADLESS"] = "1"
+    if enable_webrender:
+        env["MOZ_WEBRENDER"] = "1"
+        env["MOZ_ACCELERATED"] = "1"
+    else:
+        env["MOZ_WEBRENDER"] = "0"
+    return env
+
+
+class FirefoxInstanceManager(object):
+    __metaclass__ = ABCMeta
+
+    def __init__(self, logger, binary, binary_args, profile_creator, debug_info,
+                 chaos_mode_flags, headless, enable_webrender, stylo_threads,
+                 leak_check, stackfix_dir, symbols_path, asan):
+        """Object that manages starting and stopping instances of Firefox."""
+        self.logger = logger
+        self.binary = binary
+        self.binary_args = binary_args
+        self.base_profile = profile_creator.create()
+        self.debug_info = debug_info
+        self.chaos_mode_flags = chaos_mode_flags
+        self.headless = headless
+        self.enable_webrender = enable_webrender
+        self.stylo_threads = stylo_threads
+        self.leak_check = leak_check
+        self.stackfix_dir = stackfix_dir
+        self.symbols_path = symbols_path
+        self.asan = asan
+
+        self.previous = None
+        self.current = None
+
+    @abstractmethod
+    def teardown(self, force=False):
+        pass
+
+    @abstractmethod
+    def get(self):
+        """Get a BrowserInstance for a running Firefox.
+
+        This can only be called once per instance, and between calls stop_current()
+        must be called."""
+        pass
+
+    def stop_current(self, force=False):
+        """Shutdown the current instance of Firefox.
+
+        The BrowserInstance remains available through self.previous, since some
+        operations happen after shutdown."""
+        if not self.current:
+            return
+
+        self.current.stop(force)
+        self.previous = self.current
+        self.current = None
+
+    def start(self):
+        """Start an instance of Firefox, returning a BrowserInstance handle"""
+        profile = self.base_profile.clone(self.base_profile.profile)
+
+        marionette_port = get_free_port()
+        profile.set_preferences({"marionette.port": marionette_port})
+
+        env = get_environ(self.logger, self.binary, self.debug_info, self.stylo_threads,
+                          self.headless, self.enable_webrender, self.chaos_mode_flags)
+
+        args = self.binary_args[:] if self.binary_args else []
+        args += [cmd_arg("marionette"), "about:blank"]
+
+        debug_args, cmd = browser_command(self.binary,
+                                          args,
+                                          self.debug_info)
+
+        if self.leak_check:
+            leak_report_file = os.path.join(profile.profile, "runtests_leaks_%s.log" % os.getpid())
+            if os.path.exists(leak_report_file):
+                os.remove(leak_report_file)
+            env["XPCOM_MEM_BLOAT_LOG"] = leak_report_file
+        else:
+            leak_report_file = None
+
+        output_handler = OutputHandler(self.logger, self.stackfix_dir, self.symbols_path, self.asan)
+        runner = FirefoxRunner(profile=profile,
+                               binary=cmd[0],
+                               cmdargs=cmd[1:],
+                               env=cast_env(env),
+                               process_class=ProcessHandler,
+                               process_args={"processOutputLine": [output_handler]})
+        instance = BrowserInstance(self.logger, runner, marionette_port,
+                                   output_handler, leak_report_file)
+
+        self.logger.debug("Starting Firefox")
+        runner.start(debug_args=debug_args, interactive=self.debug_info and self.debug_info.interactive)
+        self.logger.debug("Firefox Started")
+
+        return instance
+
+
+class SingleInstanceManager(FirefoxInstanceManager):
+    """FirefoxInstanceManager that manages a single Firefox instance"""
+    def get(self):
+        assert not self.current, ("Tried to call get() on InstanceManager that has "
+                                  "an existing instance")
+        if self.previous:
+            self.previous.cleanup()
+            self.previous = None
+        self.current = self.start()
+        return self.current
+
+    def teardown(self, force=False):
+        for instance in [self.previous, self.current]:
+            if instance:
+                instance.stop(force)
+                instance.cleanup()
+
+
+class PreloadInstanceManager(FirefoxInstanceManager):
+    def __init__(self, *args, **kwargs):
+        """FirefoxInstanceManager that keeps once Firefox instance preloaded
+        to allow rapid resumption after an instance shuts down."""
+        super(PreloadInstanceManager, self).__init__(*args, **kwargs)
+        self.pending = None
+
+    def get(self):
+        assert not self.current, ("Tried to call get() on InstanceManager that has "
+                                  "an existing instance")
+        if self.previous:
+            self.previous.cleanup()
+            self.previous = None
+        if not self.pending:
+            self.pending = self.start()
+        self.current = self.pending
+        self.pending = self.start()
+        return self.current
+
+    def teardown(self, force=False):
+        for instance, skip_marionette in [(self.previous, False),
+                                          (self.current, False),
+                                          (self.pending, True)]:
+            if instance:
+                instance.stop(force, skip_marionette=skip_marionette)
+                instance.cleanup()
+
+
+class BrowserInstance(object):
+    shutdown_timeout = 70
+
+    def __init__(self, logger, runner, marionette_port, output_handler, leak_report_file):
+        """Handle to a running Firefox instance"""
+        self.logger = logger
+        self.runner = runner
+        self.marionette_port = marionette_port
+        self.output_handler = output_handler
+        self.leak_report_file = leak_report_file
+
+    def stop(self, force=False, skip_marionette=False):
+        """Stop Firefox"""
+        is_running = self.runner is not None and self.runner.is_running()
+        if is_running:
+            self.logger.debug("Stopping Firefox %s" % self.pid())
+            shutdown_methods = [(True, lambda: self.runner.wait(self.shutdown_timeout)),
+                                (False, lambda: self.runner.stop(signal.SIGTERM)),
+                                (False, lambda: self.runner.stop(signal.SIGKILL))]
+            if skip_marionette:
+                shutdown_methods = shutdown_methods[1:]
+            try:
+                # For Firefox we assume that stopping the runner prompts the
+                # browser to shut down. This allows the leak log to be written
+                for clean, stop_f in shutdown_methods:
+                    if not force or not clean:
+                        retcode = stop_f()
+                        if retcode is not None:
+                            self.logger.info("Browser exited with return code %s" % retcode)
+                            break
+            except OSError:
+                # This can happen on Windows if the process is already dead
+                pass
+        elif self.runner:
+            # The browser was already stopped, which we assume was a crash
+            # TODO: Should we check the exit code here?
+            clean = False
+        if not skip_marionette:
+            self.output_handler.after_stop(clean_shutdown=clean)
+
+    def pid(self):
+        if self.runner.process_handler is None:
+            return None
+
+        try:
+            return self.runner.process_handler.pid
+        except AttributeError:
+            return None
+
+    def is_alive(self):
+        if self.runner:
+            return self.runner.is_running()
+        return False
+
+    def cleanup(self):
+        # mozprofile handles deleting the profile when the refcount reaches 0
+        self.runner = None
+
+
+class OutputHandler(object):
+    def __init__(self, logger, stackfix_dir, symbols_path, asan):
+        """Filter for handling Firefox process output.
+
+        This receives Firefox process output in the __call__ function, does
+        any additional processing that's required, and decides whether to log
+        the output. Because the Firefox process can be started before we know
+        which filters are going to be required, we buffer all output until
+        setup() is called. This is responsible for doing the final configuration
+        of the output handlers.
+        """
+
+        self.logger = logger
+        # These are filled in after setup() is called
+        self.instance = None
+
+        self.symbols_path = symbols_path
+        if stackfix_dir:
+            # We hide errors because they cause disconcerting `CRITICAL`
+            # warnings in web platform test output.
+            self.stack_fixer = get_stack_fixer_function(stackfix_dir,
+                                                        self.symbols_path,
+                                                        hideErrors=True)
+        else:
+            self.stack_fixer = None
+        self.asan = asan
+
+        self.lsan_handler = None
+        self.mozleak_allowed = None
+        self.mozleak_thresholds = None
+        self.group_metadata = {}
+
+        self.line_buffer = []
+        self.setup_ran = False
+
+    def setup(self, instance=None, group_metadata=None, lsan_disabled=False,
+              lsan_allowed=None, lsan_max_stack_depth=None, mozleak_allowed=None,
+              mozleak_thresholds=None, **kwargs):
+        """Configure the output handler"""
+        self.instance = instance
+
+        if group_metadata is None:
+            group_metadata = {}
+        self.group_metadata = group_metadata
+
+        self.mozleak_allowed = mozleak_allowed
+        self.mozleak_thresholds = mozleak_thresholds
+
+        if self.asan:
+            self.lsan_handler = mozleak.LSANLeaks(self.logger,
+                                                  scope=group_metadata.get("scope", "/"),
+                                                  allowed=lsan_allowed,
+                                                  maxNumRecordedFrames=lsan_max_stack_depth,
+                                                  allowAll=lsan_disabled)
+        else:
+            self.lsan_handler = None
+
+        self.setup_ran = True
+
+        for line in self.line_buffer:
+            self.__call__(line)
+        self.line_buffer = []
+
+    def after_stop(self, clean_shutdown=True):
+        self.logger.info("PROCESS LEAKS %s" % self.instance.leak_report_file)
+        if self.lsan_handler:
+            self.lsan_handler.process()
+        if self.instance.leak_report_file is not None:
+            if not clean_shutdown:
+                # If we didn't get a clean shutdown there probably isn't a leak report file
+                self.logger.warning("Firefox didn't exit cleanly, not processing leak logs")
+            else:
+                # We have to ignore missing leaks in the tab because it can happen that the
+                # content process crashed and in that case we don't want the test to fail.
+                # Ideally we would record which content process crashed and just skip those.
+                mozleak.process_leak_log(
+                    self.instance.leak_report_file,
+                    leak_thresholds=self.mozleak_thresholds,
+                    ignore_missing_leaks=["tab", "gmplugin"],
+                    log=self.logger,
+                    stack_fixer=self.stack_fixer,
+                    scope=self.group_metadata.get("scope"),
+                    allowed=self.mozleak_allowed)
+
+    def __call__(self, line):
+        """Write a line of output from the firefox process to the log"""
+        if b"GLib-GObject-CRITICAL" in line:
+            return
+        if line:
+            if not self.setup_ran:
+                self.line_buffer.append(line)
+                return
+            data = line.decode("utf8", "replace")
+            if self.stack_fixer:
+                data = self.stack_fixer(data)
+            if self.lsan_handler:
+                data = self.lsan_handler.log(data)
+            if data is not None:
+                self.logger.process_output(self.instance and
+                                           self.instance.runner.process_handler and
+                                           self.instance.runner.process_handler.pid,
+                                           data,
+                                           command=" ".join(self.instance.runner.command))
+
+
+class ProfileCreator(object):
+    def __init__(self, logger, prefs_root, config, test_type, extra_prefs, e10s,
+                 enable_fission, browser_channel, binary, certutil_binary, ca_certificate_path):
+        self.logger = logger
+        self.prefs_root = prefs_root
+        self.config = config
+        self.test_type = test_type
+        self.extra_prefs = extra_prefs
+        self.e10s = e10s
+        self.enable_fission = enable_fission
+        self.browser_channel = browser_channel
+        self.ca_certificate_path = ca_certificate_path
+        self.binary = binary
+        self.certutil_binary = certutil_binary
+        self.ca_certificate_path = ca_certificate_path
+
+    def create(self, **kwargs):
+        """Create a Firefox profile and return the mozprofile Profile object pointing at that
+        profile
+
+        :param kwargs: Additional arguments to pass into the profile constructor
+        """
+        preferences = self._load_prefs()
+
+        profile = FirefoxProfile(preferences=preferences,
+                                 **kwargs)
+        self._set_required_prefs(profile)
+        if self.ca_certificate_path is not None:
+            self._setup_ssl(profile)
+
+        return profile
+
+    def _load_prefs(self):
+        prefs = Preferences()
+
+        pref_paths = []
+
+        profiles = os.path.join(self.prefs_root, 'profiles.json')
+        if os.path.isfile(profiles):
+            with open(profiles, 'r') as fh:
+                for name in json.load(fh)['web-platform-tests']:
+                    if self.browser_channel in (None, 'nightly'):
+                        pref_paths.append(os.path.join(self.prefs_root, name, 'user.js'))
+                    elif name != 'unittest-features':
+                        pref_paths.append(os.path.join(self.prefs_root, name, 'user.js'))
+        else:
+            # Old preference files used before the creation of profiles.json (remove when no longer supported)
+            legacy_pref_paths = (
+                os.path.join(self.prefs_root, 'prefs_general.js'),   # Used in Firefox 60 and below
+                os.path.join(self.prefs_root, 'common', 'user.js'),  # Used in Firefox 61
+            )
+            for path in legacy_pref_paths:
+                if os.path.isfile(path):
+                    pref_paths.append(path)
+
+        for path in pref_paths:
+            if os.path.exists(path):
+                prefs.add(Preferences.read_prefs(path))
+            else:
+                self.logger.warning("Failed to find base prefs file in %s" % path)
+
+        # Add any custom preferences
+        prefs.add(self.extra_prefs, cast=True)
+
+        return prefs()
+
+    def _set_required_prefs(self, profile):
+        """Set preferences required for wptrunner to function.
+
+        Note that this doesn't set the marionette port, since we don't always
+        know that at profile creation time. So the caller is responisble for
+        setting that once it's available."""
+        profile.set_preferences({
+            "network.dns.localDomains": ",".join(self.config.domains_set),
+            "dom.file.createInChild": True,
+            # TODO: Remove preferences once Firefox 64 is stable (Bug 905404)
+            "network.proxy.type": 0,
+            "places.history.enabled": False,
+            "network.preload": True,
+        })
+        if self.e10s:
+            profile.set_preferences({"browser.tabs.remote.autostart": True})
+
+        if self.enable_fission:
+            profile.set_preferences({"fission.autostart": True})
+
+        if self.test_type in ("reftest", "print-reftest"):
+            profile.set_preferences({"layout.interruptible-reflow.enabled": False})
+
+        if self.test_type == "print-reftest":
+            profile.set_preferences({"print.always_print_silent": True})
+
+        # Bug 1262954: winxp + e10s, disable hwaccel
+        if (self.e10s and platform.system() in ("Windows", "Microsoft") and
+            "5.1" in platform.version()):
+            self.profile.set_preferences({"layers.acceleration.disabled": True})
+
+    def _setup_ssl(self, profile):
+        """Create a certificate database to use in the test profile. This is configured
+        to trust the CA Certificate that has signed the web-platform.test server
+        certificate."""
+        if self.certutil_binary is None:
+            self.logger.info("--certutil-binary not supplied; Firefox will not check certificates")
+            return
+
+        self.logger.info("Setting up ssl")
+
+        # Make sure the certutil libraries from the source tree are loaded when using a
+        # local copy of certutil
+        # TODO: Maybe only set this if certutil won't launch?
+        env = os.environ.copy()
+        certutil_dir = os.path.dirname(self.binary or self.certutil_binary)
+        if mozinfo.isMac:
+            env_var = "DYLD_LIBRARY_PATH"
+        elif mozinfo.isUnix:
+            env_var = "LD_LIBRARY_PATH"
+        else:
+            env_var = "PATH"
+
+
+        env[env_var] = (os.path.pathsep.join([certutil_dir, env[env_var]])
+                        if env_var in env else certutil_dir).encode(
+                            sys.getfilesystemencoding() or 'utf-8', 'replace')
+
+        def certutil(*args):
+            cmd = [self.certutil_binary] + list(args)
+            self.logger.process_output("certutil",
+                                       subprocess.check_output(cmd,
+                                                               env=cast_env(env),
+                                                               stderr=subprocess.STDOUT),
+                                       " ".join(cmd))
+
+        pw_path = os.path.join(profile.profile, ".crtdbpw")
+        with open(pw_path, "w") as f:
+            # Use empty password for certificate db
+            f.write("\n")
+
+        cert_db_path = profile.profile
+
+        # Create a new certificate db
+        certutil("-N", "-d", cert_db_path, "-f", pw_path)
+
+        # Add the CA certificate to the database and mark as trusted to issue server certs
+        certutil("-A", "-d", cert_db_path, "-f", pw_path, "-t", "CT,,",
+                 "-n", "web-platform-tests", "-i", self.ca_certificate_path)
+
+        # List all certs in the database
+        certutil("-L", "-d", cert_db_path)
+
+
+class FirefoxBrowser(Browser):
+    init_timeout = 70
+
+    def __init__(self, logger, binary, prefs_root, test_type, extra_prefs=None, debug_info=None,
+                 symbols_path=None, stackwalk_binary=None, certutil_binary=None,
+                 ca_certificate_path=None, e10s=False, enable_webrender=False, enable_fission=False,
+                 stackfix_dir=None, binary_args=None, timeout_multiplier=None, leak_check=False,
+                 asan=False, stylo_threads=1, chaos_mode_flags=None, config=None,
+                 browser_channel="nightly", headless=None, preload_browser=False,
+                 specialpowers_path=None, **kwargs):
+        Browser.__init__(self, logger)
+
+        self.logger = logger
+
+        if timeout_multiplier:
+            self.init_timeout = self.init_timeout * timeout_multiplier
+
+        self.instance = None
+        self._settings = None
+
+        self.stackfix_dir = stackfix_dir
+        self.symbols_path = symbols_path
+        self.stackwalk_binary = stackwalk_binary
+
+        self.asan = asan
+        self.leak_check = leak_check
+
+        self.specialpowers_path = specialpowers_path
+
+        profile_creator = ProfileCreator(logger,
+                                         prefs_root,
+                                         config,
+                                         test_type,
+                                         extra_prefs,
+                                         e10s,
+                                         enable_fission,
+                                         browser_channel,
+                                         binary,
+                                         certutil_binary,
+                                         ca_certificate_path)
+
+        if preload_browser:
+            instance_manager_cls = PreloadInstanceManager
+        else:
+            instance_manager_cls = SingleInstanceManager
+        self.instance_manager = instance_manager_cls(logger,
+                                                     binary,
+                                                     binary_args,
+                                                     profile_creator,
+                                                     debug_info,
+                                                     chaos_mode_flags,
+                                                     headless,
+                                                     enable_webrender,
+                                                     stylo_threads,
+                                                     leak_check,
+                                                     stackfix_dir,
+                                                     symbols_path,
+                                                     asan)
+
+    def settings(self, test):
+        self._settings = {"check_leaks": self.leak_check and not test.leaks,
+                          "lsan_disabled": test.lsan_disabled,
+                          "lsan_allowed": test.lsan_allowed,
+                          "lsan_max_stack_depth": test.lsan_max_stack_depth,
+                          "mozleak_allowed": self.leak_check and test.mozleak_allowed,
+                          "mozleak_thresholds": self.leak_check and test.mozleak_threshold,
+                          "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/"}
+        return self._settings
+
+    def start(self, group_metadata=None, **kwargs):
+        self.instance = self.instance_manager.get()
+        self.instance.output_handler.setup(self.instance,
+                                           group_metadata,
+                                           **kwargs)
+
+    def stop(self, force=False):
+        self.instance_manager.stop_current(force)
+        self.logger.debug("stopped")
+
+    def pid(self):
+        return self.instance.pid()
+
+    def is_alive(self):
+        return self.instance and self.instance.is_alive()
+
+    def cleanup(self, force=False):
+        self.instance_manager.teardown(force)
+
+    def executor_browser(self):
+        assert self.instance is not None
+        extensions = []
+        if self._settings.get("special_powers", False):
+            extensions.append(self.specialpowers_path)
+        return ExecutorBrowser, {"marionette_port": self.instance.marionette_port,
+                                 "extensions": extensions}
+
+    def check_crash(self, process, test):
+        dump_dir = os.path.join(self.instance.runner.profile.profile, "minidumps")
+
+        try:
+            return bool(mozcrash.log_crashes(self.logger,
+                                             dump_dir,
+                                             symbols_path=self.symbols_path,
+                                             stackwalk_binary=self.stackwalk_binary,
+                                             process=process,
+                                             test=test))
+        except IOError:
+            self.logger.warning("Looking for crash dump files failed")
+            return False
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
new file mode 100644
index 0000000..5e9de56
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/firefox_android.py
@@ -0,0 +1,291 @@
+import os
+
+import moznetwork
+from mozrunner import FennecEmulatorRunner
+
+from .base import (get_free_port,
+                   cmd_arg,
+                   browser_command)
+from ..executors.executormarionette import (MarionetteTestharnessExecutor,  # noqa: F401
+                                            MarionetteRefTestExecutor,  # noqa: F401
+                                            MarionetteCrashtestExecutor)  # noqa: F401
+from ..process import cast_env
+from .base import (Browser,
+                   ExecutorBrowser)
+from .firefox import (get_timeout_multiplier,  # noqa: F401
+                      run_info_extras as fx_run_info_extras,
+                      update_properties,  # noqa: F401
+                      executor_kwargs,  # noqa: F401
+                      ProfileCreator as FirefoxProfileCreator)
+
+
+__wptrunner__ = {"product": "firefox_android",
+                 "check_args": "check_args",
+                 "browser": "FirefoxAndroidBrowser",
+                 "executor": {"testharness": "MarionetteTestharnessExecutor",
+                              "reftest": "MarionetteRefTestExecutor",
+                              "crashtest": "MarionetteCrashtestExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "update_properties": "update_properties",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    pass
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"adb_binary": kwargs["adb_binary"],
+            "package_name": kwargs["package_name"],
+            "device_serial": kwargs["device_serial"],
+            "prefs_root": kwargs["prefs_root"],
+            "extra_prefs": kwargs["extra_prefs"],
+            "test_type": test_type,
+            "debug_info": kwargs["debug_info"],
+            "symbols_path": kwargs["symbols_path"],
+            "stackwalk_binary": kwargs["stackwalk_binary"],
+            "certutil_binary": kwargs["certutil_binary"],
+            "ca_certificate_path": config.ssl_config["ca_cert_path"],
+            "enable_webrender": kwargs["enable_webrender"],
+            "stackfix_dir": kwargs["stackfix_dir"],
+            "binary_args": kwargs["binary_args"],
+            "timeout_multiplier": get_timeout_multiplier(test_type,
+                                                         run_info_data,
+                                                         **kwargs),
+            "e10s": run_info_data["e10s"],
+            # desktop only
+            "leak_check": False,
+            "stylo_threads": kwargs["stylo_threads"],
+            "chaos_mode_flags": kwargs["chaos_mode_flags"],
+            "config": config,
+            "install_fonts": kwargs["install_fonts"],
+            "tests_root": config.doc_root,
+            "specialpowers_path": kwargs["specialpowers_path"]}
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def run_info_extras(**kwargs):
+    rv = fx_run_info_extras(**kwargs)
+    package = kwargs["package_name"]
+    rv.update({"e10s": True if package is not None and "geckoview" in package else False,
+               "headless": False})
+    return rv
+
+
+def env_options():
+    # The server host is set to public localhost IP so that resources can be accessed
+    # from Android emulator
+    return {"server_host": moznetwork.get_ip(),
+            "bind_address": False,
+            "supports_debugger": True}
+
+
+class ProfileCreator(FirefoxProfileCreator):
+    def __init__(self, logger, prefs_root, config, test_type, extra_prefs,
+                 enable_fission, browser_channel, certutil_binary, ca_certificate_path):
+        super(ProfileCreator, self).__init__(logger, prefs_root, config, test_type, extra_prefs,
+                                             True, enable_fission, browser_channel, None,
+                                             certutil_binary, ca_certificate_path)
+
+    def _set_required_prefs(self, profile):
+        profile.set_preferences({
+            "network.dns.localDomains": ",".join(self.config.domains_set),
+            "dom.disable_open_during_load": False,
+            "places.history.enabled": False,
+            "dom.send_after_paint_to_content": True,
+            "network.preload": True,
+            "browser.tabs.remote.autostart": True,
+        })
+
+        if self.test_type == "reftest":
+            self.logger.info("Setting android reftest preferences")
+            profile.set_preferences({
+                "browser.viewport.desktopWidth": 800,
+                # Disable high DPI
+                "layout.css.devPixelsPerPx": "1.0",
+                # Ensure that the full browser element
+                # appears in the screenshot
+                "apz.allow_zooming": False,
+                "android.widget_paints_background": False,
+                # Ensure that scrollbars are always painted
+                "layout.testing.overlay-scrollbars.always-visible": True,
+            })
+
+
+class FirefoxAndroidBrowser(Browser):
+    init_timeout = 300
+    shutdown_timeout = 60
+
+    def __init__(self, logger, prefs_root, test_type, package_name="org.mozilla.geckoview.test",
+                 device_serial="emulator-5444", extra_prefs=None, debug_info=None,
+                 symbols_path=None, stackwalk_binary=None, certutil_binary=None,
+                 ca_certificate_path=None, e10s=False, enable_webrender=False, stackfix_dir=None,
+                 binary_args=None, timeout_multiplier=None, leak_check=False, asan=False,
+                 stylo_threads=1, chaos_mode_flags=None, config=None, browser_channel="nightly",
+                 install_fonts=False, tests_root=None, specialpowers_path=None, adb_binary=None,
+                 **kwargs):
+
+        super(FirefoxAndroidBrowser, self).__init__(logger)
+        self.prefs_root = prefs_root
+        self.test_type = test_type
+        self.package_name = package_name
+        self.device_serial = device_serial
+        self.debug_info = debug_info
+        self.symbols_path = symbols_path
+        self.stackwalk_binary = stackwalk_binary
+        self.certutil_binary = certutil_binary
+        self.ca_certificate_path = ca_certificate_path
+        self.e10s = True
+        self.enable_webrender = enable_webrender
+        self.stackfix_dir = stackfix_dir
+        self.binary_args = binary_args
+        self.timeout_multiplier = timeout_multiplier
+        self.leak_check = leak_check
+        self.asan = asan
+        self.stylo_threads = stylo_threads
+        self.chaos_mode_flags = chaos_mode_flags
+        self.config = config
+        self.browser_channel = browser_channel
+        self.install_fonts = install_fonts
+        self.tests_root = tests_root
+        self.specialpowers_path = specialpowers_path
+        self.adb_binary = adb_binary
+
+        self.profile_creator = ProfileCreator(logger,
+                                              prefs_root,
+                                              config,
+                                              test_type,
+                                              extra_prefs,
+                                              False,
+                                              browser_channel,
+                                              certutil_binary,
+                                              ca_certificate_path)
+
+        self.marionette_port = None
+        self.profile = None
+        self.runner = None
+        self._settings = {}
+
+    def settings(self, test):
+        self._settings = {"check_leaks": self.leak_check and not test.leaks,
+                          "lsan_allowed": test.lsan_allowed,
+                          "lsan_max_stack_depth": test.lsan_max_stack_depth,
+                          "mozleak_allowed": self.leak_check and test.mozleak_allowed,
+                          "mozleak_thresholds": self.leak_check and test.mozleak_threshold,
+                          "special_powers": self.specialpowers_path and test.url_base == "/_mozilla/"}
+        return self._settings
+
+    def start(self, **kwargs):
+        if self.marionette_port is None:
+            self.marionette_port = get_free_port()
+
+        addons = [self.specialpowers_path] if self._settings.get("special_powers") else None
+        self.profile = self.profile_creator.create(addons=addons)
+        self.profile.set_preferences({"marionette.port": self.marionette_port})
+
+        if self.install_fonts:
+            self.logger.debug("Copying Ahem font to profile")
+            font_dir = os.path.join(self.profile.profile, "fonts")
+            if not os.path.exists(font_dir):
+                os.makedirs(font_dir)
+            with open(os.path.join(self.tests_root, "fonts", "Ahem.ttf"), "rb") as src:
+                with open(os.path.join(font_dir, "Ahem.ttf"), "wb") as dest:
+                    dest.write(src.read())
+
+        self.leak_report_file = None
+
+        debug_args, cmd = browser_command(self.package_name,
+                                          self.binary_args if self.binary_args else [] +
+                                          [cmd_arg("marionette"), "about:blank"],
+                                          self.debug_info)
+
+        env = {}
+        env["MOZ_CRASHREPORTER"] = "1"
+        env["MOZ_CRASHREPORTER_SHUTDOWN"] = "1"
+        env["MOZ_DISABLE_NONLOCAL_CONNECTIONS"] = "1"
+        env["STYLO_THREADS"] = str(self.stylo_threads)
+        if self.chaos_mode_flags is not None:
+            env["MOZ_CHAOSMODE"] = str(self.chaos_mode_flags)
+        if self.enable_webrender:
+            env["MOZ_WEBRENDER"] = "1"
+        else:
+            env["MOZ_WEBRENDER"] = "0"
+
+        self.runner = FennecEmulatorRunner(app=self.package_name,
+                                           profile=self.profile,
+                                           cmdargs=cmd[1:],
+                                           env=cast_env(env),
+                                           symbols_path=self.symbols_path,
+                                           serial=self.device_serial,
+                                           # TODO - choose appropriate log dir
+                                           logdir=os.getcwd(),
+                                           adb_path=self.adb_binary,
+                                           explicit_cleanup=True)
+
+        self.logger.debug("Starting %s" % self.package_name)
+        # connect to a running emulator
+        self.runner.device.connect()
+
+        self.runner.stop()
+        self.runner.start(debug_args=debug_args,
+                          interactive=self.debug_info and self.debug_info.interactive)
+
+        self.runner.device.device.forward(
+            local="tcp:{}".format(self.marionette_port),
+            remote="tcp:{}".format(self.marionette_port))
+
+        for ports in self.config.ports.values():
+            for port in ports:
+                self.runner.device.device.reverse(
+                    local="tcp:{}".format(port),
+                    remote="tcp:{}".format(port))
+
+        self.logger.debug("%s Started" % self.package_name)
+
+    def stop(self, force=False):
+        if self.runner is not None:
+            if self.runner.device.connected:
+                try:
+                    self.runner.device.device.remove_forwards()
+                    self.runner.device.device.remove_reverses()
+                except Exception as e:
+                    self.logger.warning("Failed to remove forwarded or reversed ports: %s" % e)
+            # We assume that stopping the runner prompts the
+            # browser to shut down.
+            self.runner.cleanup()
+        self.logger.debug("stopped")
+
+    def pid(self):
+        if self.runner.process_handler is None:
+            return None
+
+        try:
+            return self.runner.process_handler.pid
+        except AttributeError:
+            return None
+
+    def is_alive(self):
+        if self.runner:
+            return self.runner.is_running()
+        return False
+
+    def cleanup(self, force=False):
+        self.stop(force)
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"marionette_port": self.marionette_port,
+                                 # We never want marionette to install extensions because
+                                 # that doesn't work on Android; instead they are in the profile
+                                 "extensions": []}
+
+    def check_crash(self, process, test):
+        if not os.environ.get("MINIDUMP_STACKWALK", "") and self.stackwalk_binary:
+            os.environ["MINIDUMP_STACKWALK"] = self.stackwalk_binary
+        return bool(self.runner.check_for_crashes(test_name=test))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/ie.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/ie.py
new file mode 100644
index 0000000..3a86c1b6
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/ie.py
@@ -0,0 +1,73 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import InternetExplorerDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorinternetexplorer import InternetExplorerDriverWdspecExecutor  # noqa: F401
+
+__wptrunner__ = {"product": "ie",
+                 "check_args": "check_args",
+                 "browser": "InternetExplorerBrowser",
+                 "executor": {"wdspec": "InternetExplorerDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    options = {}
+    options["requireWindowFocus"] = True
+    capabilities = {}
+    capabilities["se:ieOptions"] = options
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = capabilities
+    return executor_kwargs
+
+def env_extras(**kwargs):
+    return []
+
+def env_options():
+    return {"supports_debugger": False}
+
+class InternetExplorerBrowser(Browser):
+    used_ports = set()
+
+    def __init__(self, logger, webdriver_binary, webdriver_args=None):
+        Browser.__init__(self, logger)
+        self.server = InternetExplorerDriverServer(self.logger,
+                                                   binary=webdriver_binary,
+                                                   args=webdriver_args)
+        self.webdriver_host = "localhost"
+        self.webdriver_port = self.server.port
+
+    def start(self, **kwargs):
+        self.server.start()
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the server is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/opera.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/opera.py
new file mode 100644
index 0000000..a34f419
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/opera.py
@@ -0,0 +1,102 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import OperaDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorselenium import (SeleniumTestharnessExecutor,  # noqa: F401
+                                          SeleniumRefTestExecutor)  # noqa: F401
+from ..executors.executoropera import OperaDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "opera",
+                 "check_args": "check_args",
+                 "browser": "OperaBrowser",
+                 "executor": {"testharness": "SeleniumTestharnessExecutor",
+                              "reftest": "SeleniumRefTestExecutor",
+                              "wdspec": "OperaDriverWdspecExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    from selenium.webdriver import DesiredCapabilities
+
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    capabilities = dict(DesiredCapabilities.OPERA.items())
+    capabilities.setdefault("operaOptions", {})["prefs"] = {
+        "profile": {
+            "default_content_setting_values": {
+                "popups": 1
+            }
+        }
+    }
+    for (kwarg, capability) in [("binary", "binary"), ("binary_args", "args")]:
+        if kwargs[kwarg] is not None:
+            capabilities["operaOptions"][capability] = kwargs[kwarg]
+    if test_type == "testharness":
+        capabilities["operaOptions"]["useAutomationExtension"] = False
+        capabilities["operaOptions"]["excludeSwitches"] = ["enable-automation"]
+    if test_type == "wdspec":
+        capabilities["operaOptions"]["w3c"] = True
+    executor_kwargs["capabilities"] = capabilities
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+class OperaBrowser(Browser):
+    """Opera is backed by operadriver, which is supplied through
+    ``wptrunner.webdriver.OperaDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary="operadriver",
+                 webdriver_args=None):
+        """Creates a new representation of Opera.  The `binary` argument gives
+        the browser binary to use for testing."""
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.server = OperaDriverServer(self.logger,
+                                        binary=webdriver_binary,
+                                        args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/safari.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/safari.py
new file mode 100644
index 0000000..312d4db9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/safari.py
@@ -0,0 +1,90 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..webdriver_server import SafariDriverServer
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
+from ..executors.executorsafari import SafariDriverWdspecExecutor  # noqa: F401
+
+
+__wptrunner__ = {"product": "safari",
+                 "check_args": "check_args",
+                 "browser": "SafariBrowser",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "SafariDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "webdriver_binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = {}
+    if test_type == "testharness":
+        executor_kwargs["capabilities"]["pageLoadStrategy"] = "eager"
+    if kwargs["binary"] is not None:
+        raise ValueError("Safari doesn't support setting executable location")
+
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+class SafariBrowser(Browser):
+    """Safari is backed by safaridriver, which is supplied through
+    ``wptrunner.webdriver.SafariDriverServer``.
+    """
+
+    def __init__(self, logger, webdriver_binary, webdriver_args=None):
+        """Creates a new representation of Safari.  The `webdriver_binary`
+        argument gives the WebDriver binary to use for testing. (The browser
+        binary location cannot be specified, as Safari and SafariDriver are
+        coupled.)"""
+        Browser.__init__(self, logger)
+        self.server = SafariDriverServer(self.logger,
+                                         binary=webdriver_binary,
+                                         args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/sauce.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/sauce.py
new file mode 100644
index 0000000..3497c5c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/sauce.py
@@ -0,0 +1,252 @@
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this file,
+# You can obtain one at http://mozilla.org/MPL/2.0/.
+
+import glob
+import os
+import shutil
+import subprocess
+import tarfile
+import tempfile
+import time
+
+import requests
+
+from six.moves import cStringIO as StringIO
+
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorselenium import (SeleniumTestharnessExecutor,  # noqa: F401
+                                          SeleniumRefTestExecutor)  # noqa: F401
+
+here = os.path.dirname(__file__)
+# Number of seconds to wait between polling operations when detecting status of
+# Sauce Connect sub-process.
+sc_poll_period = 1
+
+
+__wptrunner__ = {"product": "sauce",
+                 "check_args": "check_args",
+                 "browser": "SauceBrowser",
+                 "executor": {"testharness": "SeleniumTestharnessExecutor",
+                              "reftest": "SeleniumRefTestExecutor"},
+                 "browser_kwargs": "browser_kwargs",
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def get_capabilities(**kwargs):
+    browser_name = kwargs["sauce_browser"]
+    platform = kwargs["sauce_platform"]
+    version = kwargs["sauce_version"]
+    build = kwargs["sauce_build"]
+    tags = kwargs["sauce_tags"]
+    tunnel_id = kwargs["sauce_tunnel_id"]
+    prerun_script = {
+        "MicrosoftEdge": {
+            "executable": "sauce-storage:edge-prerun.bat",
+            "background": False,
+        },
+        "safari": {
+            "executable": "sauce-storage:safari-prerun.sh",
+            "background": False,
+        }
+    }
+    capabilities = {
+        "browserName": browser_name,
+        "build": build,
+        "disablePopupHandler": True,
+        "name": "%s %s on %s" % (browser_name, version, platform),
+        "platform": platform,
+        "public": "public",
+        "selenium-version": "3.3.1",
+        "tags": tags,
+        "tunnel-identifier": tunnel_id,
+        "version": version,
+        "prerun": prerun_script.get(browser_name)
+    }
+
+    return capabilities
+
+
+def get_sauce_config(**kwargs):
+    browser_name = kwargs["sauce_browser"]
+    sauce_user = kwargs["sauce_user"]
+    sauce_key = kwargs["sauce_key"]
+
+    hub_url = "%s:%s@localhost:4445" % (sauce_user, sauce_key)
+    data = {
+        "url": "http://%s/wd/hub" % hub_url,
+        "browserName": browser_name,
+        "capabilities": get_capabilities(**kwargs)
+    }
+
+    return data
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "sauce_browser")
+    require_arg(kwargs, "sauce_platform")
+    require_arg(kwargs, "sauce_version")
+    require_arg(kwargs, "sauce_user")
+    require_arg(kwargs, "sauce_key")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    sauce_config = get_sauce_config(**kwargs)
+
+    return {"sauce_config": sauce_config}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+
+    executor_kwargs["capabilities"] = get_capabilities(**kwargs)
+
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return [SauceConnect(**kwargs)]
+
+
+def env_options():
+    return {"supports_debugger": False}
+
+
+def get_tar(url, dest):
+    resp = requests.get(url, stream=True)
+    resp.raise_for_status()
+    with tarfile.open(fileobj=StringIO(resp.raw.read())) as f:
+        f.extractall(path=dest)
+
+
+class SauceConnect():
+
+    def __init__(self, **kwargs):
+        self.sauce_user = kwargs["sauce_user"]
+        self.sauce_key = kwargs["sauce_key"]
+        self.sauce_tunnel_id = kwargs["sauce_tunnel_id"]
+        self.sauce_connect_binary = kwargs.get("sauce_connect_binary")
+        self.sauce_connect_args = kwargs.get("sauce_connect_args")
+        self.sauce_init_timeout = kwargs.get("sauce_init_timeout")
+        self.sc_process = None
+        self.temp_dir = None
+        self.env_config = None
+
+    def __call__(self, env_options, env_config):
+        self.env_config = env_config
+
+        return self
+
+    def __enter__(self):
+        # Because this class implements the context manager protocol, it is
+        # possible for instances to be provided to the `with` statement
+        # directly. This class implements the callable protocol so that data
+        # which is not available during object initialization can be provided
+        # prior to this moment. Instances must be invoked in preparation for
+        # the context manager protocol, but this additional constraint is not
+        # itself part of the protocol.
+        assert self.env_config is not None, 'The instance has been invoked.'
+
+        if not self.sauce_connect_binary:
+            self.temp_dir = tempfile.mkdtemp()
+            get_tar("https://saucelabs.com/downloads/sc-4.4.9-linux.tar.gz", self.temp_dir)
+            self.sauce_connect_binary = glob.glob(os.path.join(self.temp_dir, "sc-*-linux/bin/sc"))[0]
+
+        self.upload_prerun_exec('edge-prerun.bat')
+        self.upload_prerun_exec('safari-prerun.sh')
+
+        self.sc_process = subprocess.Popen([
+            self.sauce_connect_binary,
+            "--user=%s" % self.sauce_user,
+            "--api-key=%s" % self.sauce_key,
+            "--no-remove-colliding-tunnels",
+            "--tunnel-identifier=%s" % self.sauce_tunnel_id,
+            "--metrics-address=0.0.0.0:9876",
+            "--readyfile=./sauce_is_ready",
+            "--tunnel-domains",
+            ",".join(self.env_config.domains_set)
+        ] + self.sauce_connect_args)
+
+        tot_wait = 0
+        while not os.path.exists('./sauce_is_ready') and self.sc_process.poll() is None:
+            if not self.sauce_init_timeout or (tot_wait >= self.sauce_init_timeout):
+                self.quit()
+
+                raise SauceException("Sauce Connect Proxy was not ready after %d seconds" % tot_wait)
+
+            time.sleep(sc_poll_period)
+            tot_wait += sc_poll_period
+
+        if self.sc_process.returncode is not None:
+            raise SauceException("Unable to start Sauce Connect Proxy. Process exited with code %s", self.sc_process.returncode)
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.env_config = None
+        self.quit()
+        if self.temp_dir and os.path.exists(self.temp_dir):
+            try:
+                shutil.rmtree(self.temp_dir)
+            except OSError:
+                pass
+
+    def upload_prerun_exec(self, file_name):
+        auth = (self.sauce_user, self.sauce_key)
+        url = "https://saucelabs.com/rest/v1/storage/%s/%s?overwrite=true" % (self.sauce_user, file_name)
+
+        with open(os.path.join(here, 'sauce_setup', file_name), 'rb') as f:
+            requests.post(url, data=f, auth=auth)
+
+    def quit(self):
+        """The Sauce Connect process may be managing an active "tunnel" to the
+        Sauce Labs service. Issue a request to the process to close any tunnels
+        and exit. If this does not occur within 5 seconds, force the process to
+        close."""
+        kill_wait = 5
+        tot_wait = 0
+        self.sc_process.terminate()
+
+        while self.sc_process.poll() is None:
+            time.sleep(sc_poll_period)
+            tot_wait += sc_poll_period
+
+            if tot_wait >= kill_wait:
+                self.sc_process.kill()
+                break
+
+
+class SauceException(Exception):
+    pass
+
+
+class SauceBrowser(Browser):
+    init_timeout = 300
+
+    def __init__(self, logger, sauce_config):
+        Browser.__init__(self, logger)
+        self.sauce_config = sauce_config
+
+    def start(self, **kwargs):
+        pass
+
+    def stop(self, force=False):
+        pass
+
+    def pid(self):
+        return None
+
+    def is_alive(self):
+        # TODO: Should this check something about the connection?
+        return True
+
+    def cleanup(self):
+        pass
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.sauce_config["url"]}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servo.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servo.py
new file mode 100644
index 0000000..a65ed5e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servo.py
@@ -0,0 +1,89 @@
+import os
+
+from .base import NullBrowser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier   # noqa: F401
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorservo import (ServoCrashtestExecutor,  # noqa: F401
+                                       ServoTestharnessExecutor,  # noqa: F401
+                                       ServoRefTestExecutor,  # noqa: F401
+                                       ServoWdspecExecutor)  # noqa: F401
+
+here = os.path.dirname(__file__)
+
+__wptrunner__ = {
+    "product": "servo",
+    "check_args": "check_args",
+    "browser": "ServoBrowser",
+    "executor": {
+        "crashtest": "ServoCrashtestExecutor",
+        "testharness": "ServoTestharnessExecutor",
+        "reftest": "ServoRefTestExecutor",
+        "wdspec": "ServoWdspecExecutor",
+    },
+    "browser_kwargs": "browser_kwargs",
+    "executor_kwargs": "executor_kwargs",
+    "env_extras": "env_extras",
+    "env_options": "env_options",
+    "timeout_multiplier": "get_timeout_multiplier",
+    "update_properties": "update_properties",
+}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {
+        "binary": kwargs["binary"],
+        "debug_info": kwargs["debug_info"],
+        "binary_args": kwargs["binary_args"],
+        "user_stylesheets": kwargs.get("user_stylesheets"),
+        "ca_certificate_path": config.ssl_config["ca_cert_path"],
+    }
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    rv = base_executor_kwargs(test_type, server_config,
+                              cache_manager, run_info_data, **kwargs)
+    rv["pause_after_test"] = kwargs["pause_after_test"]
+    if test_type == "wdspec":
+        rv["capabilities"] = {}
+        rv["webdriver_binary"] = kwargs["binary"]
+    return rv
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {"server_host": "127.0.0.1",
+            "bind_address": False,
+            "testharnessreport": "testharnessreport-servo.js",
+            "supports_debugger": True}
+
+
+def update_properties():
+    return ["debug", "os", "processor"], {"os": ["version"], "processor": ["bits"]}
+
+
+class ServoBrowser(NullBrowser):
+    def __init__(self, logger, binary, debug_info=None, binary_args=None,
+                 user_stylesheets=None, ca_certificate_path=None):
+        NullBrowser.__init__(self, logger)
+        self.binary = binary
+        self.debug_info = debug_info
+        self.binary_args = binary_args or []
+        self.user_stylesheets = user_stylesheets or []
+        self.ca_certificate_path = ca_certificate_path
+
+    def executor_browser(self):
+        return ExecutorBrowser, {
+            "binary": self.binary,
+            "debug_info": self.debug_info,
+            "binary_args": self.binary_args,
+            "user_stylesheets": self.user_stylesheets,
+            "ca_certificate_path": self.ca_certificate_path,
+        }
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py
new file mode 100644
index 0000000..ed85cbf
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/servodriver.py
@@ -0,0 +1,177 @@
+import os
+import subprocess
+import tempfile
+
+from mozprocess import ProcessHandler
+
+from tools.serve.serve import make_hosts_file
+
+from .base import Browser, require_arg, get_free_port, browser_command, ExecutorBrowser
+from .base import get_timeout_multiplier   # noqa: F401
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorservodriver import (ServoWebDriverTestharnessExecutor,  # noqa: F401
+                                             ServoWebDriverRefTestExecutor)  # noqa: F401
+from ..process import cast_env
+
+here = os.path.dirname(__file__)
+
+__wptrunner__ = {
+    "product": "servodriver",
+    "check_args": "check_args",
+    "browser": "ServoWebDriverBrowser",
+    "executor": {
+        "testharness": "ServoWebDriverTestharnessExecutor",
+        "reftest": "ServoWebDriverRefTestExecutor",
+    },
+    "browser_kwargs": "browser_kwargs",
+    "executor_kwargs": "executor_kwargs",
+    "env_extras": "env_extras",
+    "env_options": "env_options",
+    "timeout_multiplier": "get_timeout_multiplier",
+    "update_properties": "update_properties",
+}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "binary")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {
+        "binary": kwargs["binary"],
+        "binary_args": kwargs["binary_args"],
+        "debug_info": kwargs["debug_info"],
+        "server_config": config,
+        "user_stylesheets": kwargs.get("user_stylesheets"),
+        "headless": kwargs.get("headless"),
+    }
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data, **kwargs):
+    rv = base_executor_kwargs(test_type, server_config,
+                              cache_manager, run_info_data, **kwargs)
+    return rv
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {"server_host": "127.0.0.1",
+            "testharnessreport": "testharnessreport-servodriver.js",
+            "supports_debugger": True}
+
+
+def update_properties():
+    return (["debug", "os", "processor"], {"os": ["version"], "processor": ["bits"]})
+
+
+def write_hosts_file(config):
+    hosts_fd, hosts_path = tempfile.mkstemp()
+    with os.fdopen(hosts_fd, "w") as f:
+        f.write(make_hosts_file(config, "127.0.0.1"))
+    return hosts_path
+
+class ServoWebDriverBrowser(Browser):
+    init_timeout = 300  # Large timeout for cases where we're booting an Android emulator
+
+    def __init__(self, logger, binary, debug_info=None, webdriver_host="127.0.0.1",
+                 server_config=None, binary_args=None, user_stylesheets=None, headless=None):
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.binary_args = binary_args or []
+        self.webdriver_host = webdriver_host
+        self.webdriver_port = None
+        self.proc = None
+        self.debug_info = debug_info
+        self.hosts_path = write_hosts_file(server_config)
+        self.server_ports = server_config.ports if server_config else {}
+        self.command = None
+        self.user_stylesheets = user_stylesheets if user_stylesheets else []
+        self.headless = headless if headless else False
+        self.ca_certificate_path = server_config.ssl_config["ca_cert_path"]
+
+    def start(self, **kwargs):
+        self.webdriver_port = get_free_port()
+
+        env = os.environ.copy()
+        env["HOST_FILE"] = self.hosts_path
+        env["RUST_BACKTRACE"] = "1"
+        env["EMULATOR_REVERSE_FORWARD_PORTS"] = ",".join(
+            str(port)
+            for _protocol, ports in self.server_ports.items()
+            for port in ports
+            if port
+        )
+
+        debug_args, command = browser_command(
+            self.binary,
+            self.binary_args + [
+                "--hard-fail",
+                "--webdriver=%s" % self.webdriver_port,
+                "about:blank",
+            ],
+            self.debug_info
+        )
+
+        if self.headless:
+            command += ["--headless"]
+
+        if self.ca_certificate_path:
+            command += ["--certificate-path", self.ca_certificate_path]
+
+        for stylesheet in self.user_stylesheets:
+            command += ["--user-stylesheet", stylesheet]
+
+        self.command = command
+
+        self.command = debug_args + self.command
+
+        if not self.debug_info or not self.debug_info.interactive:
+            self.proc = ProcessHandler(self.command,
+                                       processOutputLine=[self.on_output],
+                                       env=cast_env(env),
+                                       storeOutput=False)
+            self.proc.run()
+        else:
+            self.proc = subprocess.Popen(self.command, env=cast_env(env))
+
+        self.logger.debug("Servo Started")
+
+    def stop(self, force=False):
+        self.logger.debug("Stopping browser")
+        if self.proc is not None:
+            try:
+                self.proc.kill()
+            except OSError:
+                # This can happen on Windows if the process is already dead
+                pass
+
+    def pid(self):
+        if self.proc is None:
+            return None
+
+        try:
+            return self.proc.pid
+        except AttributeError:
+            return None
+
+    def on_output(self, line):
+        """Write a line of output from the process to the log"""
+        self.logger.process_output(self.pid(),
+                                   line.decode("utf8", "replace"),
+                                   command=" ".join(self.command))
+
+    def is_alive(self):
+        return self.proc.poll() is None
+
+    def cleanup(self):
+        self.stop()
+        os.remove(self.hosts_path)
+
+    def executor_browser(self):
+        assert self.webdriver_port is not None
+        return ExecutorBrowser, {"webdriver_host": self.webdriver_host,
+                                 "webdriver_port": self.webdriver_port,
+                                 "init_timeout": self.init_timeout}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkit.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkit.py
new file mode 100644
index 0000000..590e472
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkit.py
@@ -0,0 +1,110 @@
+from .base import Browser, ExecutorBrowser, require_arg
+from .base import get_timeout_multiplier, certificate_domain_list  # noqa: F401
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
+from ..executors.executorwebkit import WebKitDriverWdspecExecutor  # noqa: F401
+from ..webdriver_server import WebKitDriverServer
+
+
+__wptrunner__ = {"product": "webkit",
+                 "check_args": "check_args",
+                 "browser": "WebKitBrowser",
+                 "browser_kwargs": "browser_kwargs",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "WebKitDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    require_arg(kwargs, "binary")
+    require_arg(kwargs, "webdriver_binary")
+    require_arg(kwargs, "webkit_port")
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": kwargs.get("webdriver_args")}
+
+
+def capabilities_for_port(server_config, **kwargs):
+    port_name = kwargs["webkit_port"]
+    if port_name in ["gtk", "wpe"]:
+        port_key_map = {"gtk": "webkitgtk"}
+        browser_options_port = port_key_map.get(port_name, port_name)
+        browser_options_key = "%s:browserOptions" % browser_options_port
+
+        return {
+            "browserName": "MiniBrowser",
+            "browserVersion": "2.20",
+            "platformName": "ANY",
+            browser_options_key: {
+                "binary": kwargs["binary"],
+                "args": kwargs.get("binary_args", []),
+                "certificates": certificate_domain_list(server_config.domains_set, kwargs["host_cert_path"])}}
+
+    return {}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = capabilities_for_port(server_config,
+                                                            **kwargs)
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+def run_info_extras(**kwargs):
+    return {"webkit_port": kwargs["webkit_port"]}
+
+
+class WebKitBrowser(Browser):
+    """Generic WebKit browser is backed by WebKit's WebDriver implementation,
+    which is supplied through ``wptrunner.webdriver.WebKitDriverServer``.
+    """
+
+    def __init__(self, logger, binary, webdriver_binary=None,
+                 webdriver_args=None):
+        Browser.__init__(self, logger)
+        self.binary = binary
+        self.server = WebKitDriverServer(self.logger, binary=webdriver_binary,
+                                         args=webdriver_args)
+
+    def start(self, **kwargs):
+        self.server.start(block=False)
+
+    def stop(self, force=False):
+        self.server.stop(force=force)
+
+    def pid(self):
+        return self.server.pid
+
+    def is_alive(self):
+        # TODO(ato): This only indicates the driver is alive,
+        # and doesn't say anything about whether a browser session
+        # is active.
+        return self.server.is_alive()
+
+    def cleanup(self):
+        self.stop()
+
+    def executor_browser(self):
+        return ExecutorBrowser, {"webdriver_url": self.server.url}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
new file mode 100644
index 0000000..5b7a360f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/browsers/webkitgtk_minibrowser.py
@@ -0,0 +1,81 @@
+from .base import get_timeout_multiplier, maybe_add_args, certificate_domain_list  # noqa: F401
+from .webkit import WebKitBrowser
+from ..executors import executor_kwargs as base_executor_kwargs
+from ..executors.executorwebdriver import (WebDriverTestharnessExecutor,  # noqa: F401
+                                           WebDriverRefTestExecutor,  # noqa: F401
+                                           WebDriverCrashtestExecutor)  # noqa: F401
+from ..executors.executorwebkit import WebKitDriverWdspecExecutor  # noqa: F401
+
+__wptrunner__ = {"product": "webkitgtk_minibrowser",
+                 "check_args": "check_args",
+                 "browser": "WebKitGTKMiniBrowser",
+                 "browser_kwargs": "browser_kwargs",
+                 "executor": {"testharness": "WebDriverTestharnessExecutor",
+                              "reftest": "WebDriverRefTestExecutor",
+                              "wdspec": "WebKitDriverWdspecExecutor",
+                              "crashtest": "WebDriverCrashtestExecutor"},
+                 "executor_kwargs": "executor_kwargs",
+                 "env_extras": "env_extras",
+                 "env_options": "env_options",
+                 "run_info_extras": "run_info_extras",
+                 "timeout_multiplier": "get_timeout_multiplier"}
+
+
+def check_args(**kwargs):
+    pass
+
+
+def browser_kwargs(logger, test_type, run_info_data, config, **kwargs):
+    # Workaround for https://gitlab.gnome.org/GNOME/libsoup/issues/172
+    webdriver_required_args = ["--host=127.0.0.1"]
+    webdriver_args = maybe_add_args(webdriver_required_args, kwargs.get("webdriver_args"))
+    return {"binary": kwargs["binary"],
+            "webdriver_binary": kwargs["webdriver_binary"],
+            "webdriver_args": webdriver_args}
+
+
+def capabilities(server_config, **kwargs):
+    browser_required_args = ["--automation",
+                            "--javascript-can-open-windows-automatically=true",
+                            "--enable-xss-auditor=false",
+                            "--enable-media-capabilities=true",
+                            "--enable-encrypted-media=true",
+                            "--enable-media-stream=true",
+                            "--enable-mock-capture-devices=true",
+                            "--enable-webaudio=true"]
+    args = kwargs.get("binary_args", [])
+    args = maybe_add_args(browser_required_args, args)
+    return {
+        "browserName": "MiniBrowser",
+        "webkitgtk:browserOptions": {
+            "binary": kwargs["binary"],
+            "args": args,
+            "certificates": certificate_domain_list(server_config.domains_set, kwargs["host_cert_path"])}}
+
+
+def executor_kwargs(logger, test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    executor_kwargs = base_executor_kwargs(test_type, server_config,
+                                           cache_manager, run_info_data, **kwargs)
+    executor_kwargs["close_after_done"] = True
+    executor_kwargs["capabilities"] = capabilities(server_config, **kwargs)
+    return executor_kwargs
+
+
+def env_extras(**kwargs):
+    return []
+
+
+def env_options():
+    return {}
+
+
+def run_info_extras(**kwargs):
+    return {"webkit_port": "gtk"}
+
+
+class WebKitGTKMiniBrowser(WebKitBrowser):
+    def __init__(self, logger, binary=None, webdriver_binary=None,
+                 webdriver_args=None):
+        WebKitBrowser.__init__(self, logger, binary, webdriver_binary,
+                               webdriver_args)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/config.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/config.py
new file mode 100644
index 0000000..d46beb8e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/config.py
@@ -0,0 +1,60 @@
+from six.moves.configparser import SafeConfigParser
+import os
+import sys
+from collections import OrderedDict
+
+here = os.path.dirname(__file__)
+
+class ConfigDict(dict):
+    def __init__(self, base_path, *args, **kwargs):
+        self.base_path = base_path
+        dict.__init__(self, *args, **kwargs)
+
+    def get_path(self, key, default=None):
+        if key not in self:
+            return default
+        path = self[key]
+        os.path.expanduser(path)
+        return os.path.abspath(os.path.join(self.base_path, path))
+
+def read(config_path):
+    config_path = os.path.abspath(config_path)
+    config_root = os.path.dirname(config_path)
+    parser = SafeConfigParser()
+    success = parser.read(config_path)
+    assert config_path in success, success
+
+    subns = {"pwd": os.path.abspath(os.path.curdir)}
+
+    rv = OrderedDict()
+    for section in parser.sections():
+        rv[section] = ConfigDict(config_root)
+        for key in parser.options(section):
+            rv[section][key] = parser.get(section, key, raw=False, vars=subns)
+
+    return rv
+
+def path(argv=None):
+    if argv is None:
+        argv = []
+    path = None
+
+    for i, arg in enumerate(argv):
+        if arg == "--config":
+            if i + 1 < len(argv):
+                path = argv[i + 1]
+        elif arg.startswith("--config="):
+            path = arg.split("=", 1)[1]
+        if path is not None:
+            break
+
+    if path is None:
+        if os.path.exists("wptrunner.ini"):
+            path = os.path.abspath("wptrunner.ini")
+        else:
+            path = os.path.join(here, "..", "wptrunner.default.ini")
+
+    return os.path.abspath(path)
+
+def load():
+    return read(path(sys.argv))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/environment.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/environment.py
new file mode 100644
index 0000000..d98e120
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/environment.py
@@ -0,0 +1,268 @@
+import json
+import os
+
+import signal
+import socket
+import sys
+import time
+from six import iteritems
+
+from mozlog import get_default_logger, handlers, proxy
+
+from . import mpcontext
+from .wptlogging import LogLevelRewriter
+
+here = os.path.dirname(__file__)
+repo_root = os.path.abspath(os.path.join(here, os.pardir, os.pardir, os.pardir))
+
+sys.path.insert(0, repo_root)
+from tools import localpaths  # noqa: F401
+
+from wptserve.handlers import StringHandler
+
+serve = None
+
+
+def do_delayed_imports(logger, test_paths):
+    global serve
+
+    serve_root = serve_path(test_paths)
+    sys.path.insert(0, serve_root)
+
+    failed = []
+
+    try:
+        from tools.serve import serve
+    except ImportError:
+        failed.append("serve")
+
+    if failed:
+        logger.critical(
+            "Failed to import %s. Ensure that tests path %s contains web-platform-tests" %
+            (", ".join(failed), serve_root))
+        sys.exit(1)
+
+
+def serve_path(test_paths):
+    return test_paths["/"]["tests_path"]
+
+
+class TestEnvironmentError(Exception):
+    pass
+
+
+class TestEnvironment(object):
+    """Context manager that owns the test environment i.e. the http and
+    websockets servers"""
+    def __init__(self, test_paths, testharness_timeout_multipler,
+                 pause_after_test, debug_info, options, ssl_config, env_extras,
+                 enable_quic=False, mojojs_path=None):
+        self.test_paths = test_paths
+        self.server = None
+        self.config_ctx = None
+        self.config = None
+        self.testharness_timeout_multipler = testharness_timeout_multipler
+        self.pause_after_test = pause_after_test
+        self.test_server_port = options.pop("test_server_port", True)
+        self.debug_info = debug_info
+        self.options = options if options is not None else {}
+
+        mp_context = mpcontext.get_context()
+        self.cache_manager = mp_context.Manager()
+        self.stash = serve.stash.StashServer(mp_context=mp_context)
+        self.env_extras = env_extras
+        self.env_extras_cms = None
+        self.ssl_config = ssl_config
+        self.enable_quic = enable_quic
+        self.mojojs_path = mojojs_path
+
+    def __enter__(self):
+        self.config_ctx = self.build_config()
+
+        self.config = self.config_ctx.__enter__()
+
+        self.stash.__enter__()
+        self.cache_manager.__enter__()
+
+        self.setup_server_logging()
+
+        assert self.env_extras_cms is None, (
+            "A TestEnvironment object cannot be nested")
+
+        self.env_extras_cms = []
+
+        for env in self.env_extras:
+            cm = env(self.options, self.config)
+            cm.__enter__()
+            self.env_extras_cms.append(cm)
+
+        self.servers = serve.start(self.config,
+                                   self.get_routes(),
+                                   mp_context=mpcontext.get_context())
+
+        if self.options.get("supports_debugger") and self.debug_info and self.debug_info.interactive:
+            self.ignore_interrupts()
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.process_interrupts()
+
+        for scheme, servers in iteritems(self.servers):
+            for port, server in servers:
+                server.kill()
+        for cm in self.env_extras_cms:
+            cm.__exit__(exc_type, exc_val, exc_tb)
+
+        self.env_extras_cms = None
+
+        self.cache_manager.__exit__(exc_type, exc_val, exc_tb)
+        self.stash.__exit__()
+        self.config_ctx.__exit__(exc_type, exc_val, exc_tb)
+
+    def ignore_interrupts(self):
+        signal.signal(signal.SIGINT, signal.SIG_IGN)
+
+    def process_interrupts(self):
+        signal.signal(signal.SIGINT, signal.SIG_DFL)
+
+    def build_config(self):
+        override_path = os.path.join(serve_path(self.test_paths), "config.json")
+
+        config = serve.ConfigBuilder()
+
+        ports = {
+            "http": [8000, 8001],
+            "https": [8443, 8444],
+            "ws": [8888],
+            "wss": [8889],
+            "h2": [9000],
+        }
+        if self.enable_quic:
+            ports["quic-transport"] = [10000]
+        config.ports = ports
+
+        if os.path.exists(override_path):
+            with open(override_path) as f:
+                override_obj = json.load(f)
+            config.update(override_obj)
+
+        config.check_subdomains = False
+
+        ssl_config = self.ssl_config.copy()
+        ssl_config["encrypt_after_connect"] = self.options.get("encrypt_after_connect", False)
+        config.ssl = ssl_config
+
+        if "browser_host" in self.options:
+            config.browser_host = self.options["browser_host"]
+
+        if "bind_address" in self.options:
+            config.bind_address = self.options["bind_address"]
+
+        config.server_host = self.options.get("server_host", None)
+        config.doc_root = serve_path(self.test_paths)
+
+        return config
+
+    def setup_server_logging(self):
+        server_logger = get_default_logger(component="wptserve")
+        assert server_logger is not None
+        log_filter = handlers.LogLevelFilter(lambda x: x, "info")
+        # Downgrade errors to warnings for the server
+        log_filter = LogLevelRewriter(log_filter, ["error"], "warning")
+        server_logger.component_filter = log_filter
+
+        server_logger = proxy.QueuedProxyLogger(server_logger,
+                                                mpcontext.get_context())
+
+        try:
+            # Set as the default logger for wptserve
+            serve.set_logger(server_logger)
+            serve.logger = server_logger
+        except Exception:
+            # This happens if logging has already been set up for wptserve
+            pass
+
+    def get_routes(self):
+        route_builder = serve.RoutesBuilder()
+
+        for path, format_args, content_type, route in [
+                ("testharness_runner.html", {}, "text/html", "/testharness_runner.html"),
+                ("print_reftest_runner.html", {}, "text/html", "/print_reftest_runner.html"),
+                (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.js"), None,
+                 "text/javascript", "/_pdf_js/pdf.js"),
+                (os.path.join(here, "..", "..", "third_party", "pdf_js", "pdf.worker.js"), None,
+                 "text/javascript", "/_pdf_js/pdf.worker.js"),
+                (self.options.get("testharnessreport", "testharnessreport.js"),
+                 {"output": self.pause_after_test,
+                  "timeout_multiplier": self.testharness_timeout_multipler,
+                  "explicit_timeout": "true" if self.debug_info is not None else "false"},
+                 "text/javascript;charset=utf8",
+                 "/resources/testharnessreport.js")]:
+            path = os.path.normpath(os.path.join(here, path))
+            # Note that .headers. files don't apply to static routes, so we need to
+            # readd any static headers here.
+            headers = {"Cache-Control": "max-age=3600"}
+            route_builder.add_static(path, format_args, content_type, route,
+                                     headers=headers)
+
+        data = b""
+        with open(os.path.join(repo_root, "resources", "testdriver.js"), "rb") as fp:
+            data += fp.read()
+        with open(os.path.join(here, "testdriver-extra.js"), "rb") as fp:
+            data += fp.read()
+        route_builder.add_handler("GET", "/resources/testdriver.js",
+                                  StringHandler(data, "text/javascript"))
+
+        for url_base, paths in iteritems(self.test_paths):
+            if url_base == "/":
+                continue
+            route_builder.add_mount_point(url_base, paths["tests_path"])
+
+        if "/" not in self.test_paths:
+            del route_builder.mountpoint_routes["/"]
+
+        if self.mojojs_path:
+            route_builder.add_mount_point("/gen/", self.mojojs_path)
+
+        return route_builder.get_routes()
+
+    def ensure_started(self):
+        # Pause for a while to ensure that the server has a chance to start
+        total_sleep_secs = 30
+        each_sleep_secs = 0.5
+        end_time = time.time() + total_sleep_secs
+        while time.time() < end_time:
+            failed, pending = self.test_servers()
+            if failed:
+                break
+            if not pending:
+                return
+            time.sleep(each_sleep_secs)
+        raise EnvironmentError("Servers failed to start: %s" %
+                               ", ".join("%s:%s" % item for item in failed))
+
+    def test_servers(self):
+        failed = []
+        pending = []
+        host = self.config["server_host"]
+        for scheme, servers in iteritems(self.servers):
+            for port, server in servers:
+                if not server.is_alive():
+                    failed.append((scheme, port))
+
+        if not failed and self.test_server_port:
+            for scheme, servers in iteritems(self.servers):
+                # TODO(Hexcles): Find a way to test QUIC's UDP port.
+                if scheme == "quic-transport":
+                    continue
+                for port, server in servers:
+                    s = socket.socket()
+                    s.settimeout(0.1)
+                    try:
+                        s.connect((host, port))
+                    except socket.error:
+                        pending.append((host, port))
+                    finally:
+                        s.close()
+
+        return failed, pending
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/__init__.py
new file mode 100644
index 0000000..bf829d9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/__init__.py
@@ -0,0 +1,5 @@
+# flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!)
+from .base import (executor_kwargs,
+                   testharness_result_converter,
+                   reftest_result_converter,
+                   TestExecutor)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/actions.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/actions.py
new file mode 100644
index 0000000..963ed337
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/actions.py
@@ -0,0 +1,197 @@
+
+class ClickAction(object):
+    name = "click"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        selector = payload["selector"]
+        element = self.protocol.select.element_by_selector(selector)
+        self.logger.debug("Clicking element: %s" % selector)
+        self.protocol.click.element(element)
+
+
+class DeleteAllCookiesAction(object):
+    name = "delete_all_cookies"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        self.logger.debug("Deleting all cookies")
+        self.protocol.cookies.delete_all_cookies()
+
+
+class SendKeysAction(object):
+    name = "send_keys"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        selector = payload["selector"]
+        keys = payload["keys"]
+        element = self.protocol.select.element_by_selector(selector)
+        self.logger.debug("Sending keys to element: %s" % selector)
+        self.protocol.send_keys.send_keys(element, keys)
+
+
+class ActionSequenceAction(object):
+    name = "action_sequence"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        # TODO: some sort of shallow error checking
+        actions = payload["actions"]
+        for actionSequence in actions:
+            if actionSequence["type"] == "pointer":
+                for action in actionSequence["actions"]:
+                    if (action["type"] == "pointerMove" and
+                        isinstance(action["origin"], dict)):
+                        action["origin"] = self.get_element(action["origin"]["selector"])
+        self.protocol.action_sequence.send_actions({"actions": actions})
+
+    def get_element(self, element_selector):
+        return self.protocol.select.element_by_selector(element_selector)
+
+
+class GenerateTestReportAction(object):
+    name = "generate_test_report"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        message = payload["message"]
+        self.logger.debug("Generating test report: %s" % message)
+        self.protocol.generate_test_report.generate_test_report(message)
+
+class SetPermissionAction(object):
+    name = "set_permission"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        permission_params = payload["permission_params"]
+        descriptor = permission_params["descriptor"]
+        name = descriptor["name"]
+        state = permission_params["state"]
+        one_realm = permission_params.get("oneRealm", False)
+        self.logger.debug("Setting permission %s to %s, oneRealm=%s" % (name, state, one_realm))
+        self.protocol.set_permission.set_permission(descriptor, state, one_realm)
+
+class AddVirtualAuthenticatorAction(object):
+    name = "add_virtual_authenticator"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        self.logger.debug("Adding virtual authenticator")
+        config = payload["config"]
+        authenticator_id = self.protocol.virtual_authenticator.add_virtual_authenticator(config)
+        self.logger.debug("Authenticator created with ID %s" % authenticator_id)
+        return authenticator_id
+
+class RemoveVirtualAuthenticatorAction(object):
+    name = "remove_virtual_authenticator"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        self.logger.debug("Removing virtual authenticator %s" % authenticator_id)
+        return self.protocol.virtual_authenticator.remove_virtual_authenticator(authenticator_id)
+
+
+class AddCredentialAction(object):
+    name = "add_credential"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        credential = payload["credential"]
+        self.logger.debug("Adding credential to virtual authenticator %s " % authenticator_id)
+        return self.protocol.virtual_authenticator.add_credential(authenticator_id, credential)
+
+class GetCredentialsAction(object):
+    name = "get_credentials"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        self.logger.debug("Getting credentials from virtual authenticator %s " % authenticator_id)
+        return self.protocol.virtual_authenticator.get_credentials(authenticator_id)
+
+class RemoveCredentialAction(object):
+    name = "remove_credential"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        credential_id = payload["credential_id"]
+        self.logger.debug("Removing credential %s from authenticator %s" % (credential_id, authenticator_id))
+        return self.protocol.virtual_authenticator.remove_credential(authenticator_id, credential_id)
+
+class RemoveAllCredentialsAction(object):
+    name = "remove_all_credentials"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        self.logger.debug("Removing all credentials from authenticator %s" % authenticator_id)
+        return self.protocol.virtual_authenticator.remove_all_credentials(authenticator_id)
+
+class SetUserVerifiedAction(object):
+    name = "set_user_verified"
+
+    def __init__(self, logger, protocol):
+        self.logger = logger
+        self.protocol = protocol
+
+    def __call__(self, payload):
+        authenticator_id = payload["authenticator_id"]
+        uv = payload["uv"]
+        self.logger.debug(
+            "Setting user verified flag on authenticator %s to %s" % (authenticator_id, uv["isUserVerified"]))
+        return self.protocol.virtual_authenticator.set_user_verified(authenticator_id, uv)
+
+
+actions = [ClickAction,
+           DeleteAllCookiesAction,
+           SendKeysAction,
+           ActionSequenceAction,
+           GenerateTestReportAction,
+           SetPermissionAction,
+           AddVirtualAuthenticatorAction,
+           RemoveVirtualAuthenticatorAction,
+           AddCredentialAction,
+           GetCredentialsAction,
+           RemoveCredentialAction,
+           RemoveAllCredentialsAction,
+           SetUserVerifiedAction]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/base.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/base.py
new file mode 100644
index 0000000..539c791f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/base.py
@@ -0,0 +1,846 @@
+import base64
+import hashlib
+import io
+import json
+import os
+import threading
+import traceback
+import socket
+import sys
+from abc import ABCMeta, abstractmethod
+from six import text_type
+from six.moves.http_client import HTTPConnection
+from six.moves.urllib.parse import urljoin, urlsplit, urlunsplit
+
+from .actions import actions
+from .protocol import Protocol, BaseProtocolPart
+
+here = os.path.dirname(__file__)
+
+
+
+def executor_kwargs(test_type, server_config, cache_manager, run_info_data,
+                    **kwargs):
+    timeout_multiplier = kwargs["timeout_multiplier"]
+    if timeout_multiplier is None:
+        timeout_multiplier = 1
+
+    executor_kwargs = {"server_config": server_config,
+                       "timeout_multiplier": timeout_multiplier,
+                       "debug_info": kwargs["debug_info"]}
+
+    if test_type in ("reftest", "print-reftest"):
+        executor_kwargs["screenshot_cache"] = cache_manager.dict()
+
+    if test_type == "wdspec":
+        executor_kwargs["binary"] = kwargs.get("binary")
+        executor_kwargs["webdriver_binary"] = kwargs.get("webdriver_binary")
+        executor_kwargs["webdriver_args"] = kwargs.get("webdriver_args")
+
+    # By default the executor may try to cleanup windows after a test (to best
+    # associate any problems with the test causing them). If the user might
+    # want to view the results, however, the executor has to skip that cleanup.
+    if kwargs["pause_after_test"] or kwargs["pause_on_unexpected"]:
+        executor_kwargs["cleanup_after_test"] = False
+
+    return executor_kwargs
+
+
+def strip_server(url):
+    """Remove the scheme and netloc from a url, leaving only the path and any query
+    or fragment.
+
+    url - the url to strip
+
+    e.g. http://example.org:8000/tests?id=1#2 becomes /tests?id=1#2"""
+
+    url_parts = list(urlsplit(url))
+    url_parts[0] = ""
+    url_parts[1] = ""
+    return urlunsplit(url_parts)
+
+
+class TestharnessResultConverter(object):
+    harness_codes = {0: "OK",
+                     1: "ERROR",
+                     2: "TIMEOUT",
+                     3: "PRECONDITION_FAILED"}
+
+    test_codes = {0: "PASS",
+                  1: "FAIL",
+                  2: "TIMEOUT",
+                  3: "NOTRUN",
+                  4: "PRECONDITION_FAILED"}
+
+    def __call__(self, test, result, extra=None):
+        """Convert a JSON result into a (TestResult, [SubtestResult]) tuple"""
+        result_url, status, message, stack, subtest_results = result
+        assert result_url == test.url, ("Got results from %s, expected %s" %
+                                        (result_url, test.url))
+        harness_result = test.result_cls(self.harness_codes[status], message, extra=extra, stack=stack)
+        return (harness_result,
+                [test.subtest_result_cls(st_name, self.test_codes[st_status], st_message, st_stack)
+                 for st_name, st_status, st_message, st_stack in subtest_results])
+
+
+testharness_result_converter = TestharnessResultConverter()
+
+
+def hash_screenshots(screenshots):
+    """Computes the sha1 checksum of a list of base64-encoded screenshots."""
+    return [hashlib.sha1(base64.b64decode(screenshot)).hexdigest()
+            for screenshot in screenshots]
+
+
+def _ensure_hash_in_reftest_screenshots(extra):
+    """Make sure reftest_screenshots have hashes.
+
+    Marionette internal reftest runner does not produce hashes.
+    """
+    log_data = extra.get("reftest_screenshots")
+    if not log_data:
+        return
+    for item in log_data:
+        if type(item) != dict:
+            # Skip relation strings.
+            continue
+        if "hash" not in item:
+            item["hash"] = hash_screenshots([item["screenshot"]])[0]
+
+
+def get_pages(ranges_value, total_pages):
+    """Get a set of page numbers to include in a print reftest.
+
+    :param ranges_value: Parsed page ranges as a list e.g. [[1,2], [4], [6,None]]
+    :param total_pages: Integer total number of pages in the paginated output.
+    :retval: Set containing integer page numbers to include in the comparison e.g.
+             for the example ranges value and 10 total pages this would be
+             {1,2,4,6,7,8,9,10}"""
+    if not ranges_value:
+        return set(range(1, total_pages + 1))
+
+    rv = set()
+
+    for range_limits in ranges_value:
+        if len(range_limits) == 1:
+            range_limits = [range_limits[0], range_limits[0]]
+
+        if range_limits[0] is None:
+            range_limits[0] = 1
+        if range_limits[1] is None:
+            range_limits[1] = total_pages
+
+        if range_limits[0] > total_pages:
+            continue
+        rv |= set(range(range_limits[0], range_limits[1] + 1))
+    return rv
+
+
+def reftest_result_converter(self, test, result):
+    extra = result.get("extra", {})
+    _ensure_hash_in_reftest_screenshots(extra)
+    return (test.result_cls(
+        result["status"],
+        result["message"],
+        extra=extra,
+        stack=result.get("stack")), [])
+
+
+def pytest_result_converter(self, test, data):
+    harness_data, subtest_data = data
+
+    if subtest_data is None:
+        subtest_data = []
+
+    harness_result = test.result_cls(*harness_data)
+    subtest_results = [test.subtest_result_cls(*item) for item in subtest_data]
+
+    return (harness_result, subtest_results)
+
+
+def crashtest_result_converter(self, test, result):
+    return test.result_cls(**result), []
+
+
+class ExecutorException(Exception):
+    def __init__(self, status, message):
+        self.status = status
+        self.message = message
+
+
+class TimedRunner(object):
+    def __init__(self, logger, func, protocol, url, timeout, extra_timeout):
+        self.func = func
+        self.logger = logger
+        self.result = None
+        self.protocol = protocol
+        self.url = url
+        self.timeout = timeout
+        self.extra_timeout = extra_timeout
+        self.result_flag = threading.Event()
+
+    def run(self):
+        for setup_fn in [self.set_timeout, self.before_run]:
+            err = setup_fn()
+            if err:
+                self.result = (False, err)
+                return self.result
+
+        executor = threading.Thread(target=self.run_func)
+        executor.start()
+
+        # Add twice the extra timeout since the called function is expected to
+        # wait at least self.timeout + self.extra_timeout and this gives some leeway
+        timeout = self.timeout + 2 * self.extra_timeout if self.timeout else None
+        finished = self.result_flag.wait(timeout)
+        if self.result is None:
+            if finished:
+                # flag is True unless we timeout; this *shouldn't* happen, but
+                # it can if self.run_func fails to set self.result due to raising
+                self.result = False, ("INTERNAL-ERROR", "%s.run_func didn't set a result" %
+                                      self.__class__.__name__)
+            else:
+                if self.protocol.is_alive():
+                    message = "Executor hit external timeout (this may indicate a hang)\n"
+                    # get a traceback for the current stack of the executor thread
+                    message += "".join(traceback.format_stack(sys._current_frames()[executor.ident]))
+                    self.result = False, ("EXTERNAL-TIMEOUT", message)
+                else:
+                    self.logger.info("Browser not responding, setting status to CRASH")
+                    self.result = False, ("CRASH", None)
+        elif self.result[1] is None:
+            # We didn't get any data back from the test, so check if the
+            # browser is still responsive
+            if self.protocol.is_alive():
+                self.result = False, ("INTERNAL-ERROR", None)
+            else:
+                self.logger.info("Browser not responding, setting status to CRASH")
+                self.result = False, ("CRASH", None)
+
+        return self.result
+
+    def set_timeout(self):
+        raise NotImplementedError
+
+    def before_run(self):
+        pass
+
+    def run_func(self):
+        raise NotImplementedError
+
+
+class TestExecutor(object):
+    """Abstract Base class for object that actually executes the tests in a
+    specific browser. Typically there will be a different TestExecutor
+    subclass for each test type and method of executing tests.
+
+    :param browser: ExecutorBrowser instance providing properties of the
+                    browser that will be tested.
+    :param server_config: Dictionary of wptserve server configuration of the
+                          form stored in TestEnvironment.config
+    :param timeout_multiplier: Multiplier relative to base timeout to use
+                               when setting test timeout.
+    """
+    __metaclass__ = ABCMeta
+
+    test_type = None
+    convert_result = None
+    supports_testdriver = False
+    supports_jsshell = False
+    # Extra timeout to use after internal test timeout at which the harness
+    # should force a timeout
+    extra_timeout = 5  # seconds
+
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 debug_info=None, **kwargs):
+        self.logger = logger
+        self.runner = None
+        self.browser = browser
+        self.server_config = server_config
+        self.timeout_multiplier = timeout_multiplier
+        self.debug_info = debug_info
+        self.last_environment = {"protocol": "http",
+                                 "prefs": {}}
+        self.protocol = None  # This must be set in subclasses
+
+    def setup(self, runner):
+        """Run steps needed before tests can be started e.g. connecting to
+        browser instance
+
+        :param runner: TestRunner instance that is going to run the tests"""
+        self.runner = runner
+        if self.protocol is not None:
+            self.protocol.setup(runner)
+
+    def teardown(self):
+        """Run cleanup steps after tests have finished"""
+        if self.protocol is not None:
+            self.protocol.teardown()
+
+    def reset(self):
+        """Re-initialize internal state to facilitate repeated test execution
+        as implemented by the `--rerun` command-line argument."""
+        pass
+
+    def run_test(self, test):
+        """Run a particular test.
+
+        :param test: The test to run"""
+        if test.environment != self.last_environment:
+            self.on_environment_change(test.environment)
+        try:
+            result = self.do_test(test)
+        except Exception as e:
+            exception_string = traceback.format_exc()
+            self.logger.warning(exception_string)
+            result = self.result_from_exception(test, e, exception_string)
+
+        # log result of parent test
+        if result[0].status == "ERROR":
+            self.logger.debug(result[0].message)
+
+        self.last_environment = test.environment
+
+        self.runner.send_message("test_ended", test, result)
+
+    def server_url(self, protocol, subdomain=False):
+        scheme = "https" if protocol == "h2" else protocol
+        host = self.server_config["browser_host"]
+        if subdomain:
+            # The only supported subdomain filename flag is "www".
+            host = "{subdomain}.{host}".format(subdomain="www", host=host)
+        return "{scheme}://{host}:{port}".format(scheme=scheme, host=host,
+            port=self.server_config["ports"][protocol][0])
+
+    def test_url(self, test):
+        return urljoin(self.server_url(test.environment["protocol"],
+                                       test.subdomain), test.url)
+
+    @abstractmethod
+    def do_test(self, test):
+        """Test-type and protocol specific implementation of running a
+        specific test.
+
+        :param test: The test to run."""
+        pass
+
+    def on_environment_change(self, new_environment):
+        pass
+
+    def result_from_exception(self, test, e, exception_string):
+        if hasattr(e, "status") and e.status in test.result_cls.statuses:
+            status = e.status
+        else:
+            status = "INTERNAL-ERROR"
+        message = text_type(getattr(e, "message", ""))
+        if message:
+            message += "\n"
+        message += exception_string
+        return test.result_cls(status, message), []
+
+    def wait(self):
+        self.protocol.base.wait()
+
+
+class TestharnessExecutor(TestExecutor):
+    convert_result = testharness_result_converter
+
+
+class RefTestExecutor(TestExecutor):
+    convert_result = reftest_result_converter
+    is_print = False
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1, screenshot_cache=None,
+                 debug_info=None, **kwargs):
+        TestExecutor.__init__(self, logger, browser, server_config,
+                              timeout_multiplier=timeout_multiplier,
+                              debug_info=debug_info)
+
+        self.screenshot_cache = screenshot_cache
+
+
+class CrashtestExecutor(TestExecutor):
+    convert_result = crashtest_result_converter
+
+
+class PrintRefTestExecutor(TestExecutor):
+    convert_result = reftest_result_converter
+    is_print = True
+
+
+class RefTestImplementation(object):
+    def __init__(self, executor):
+        self.timeout_multiplier = executor.timeout_multiplier
+        self.executor = executor
+        # Cache of url:(screenshot hash, screenshot). Typically the
+        # screenshot is None, but we set this value if a test fails
+        # and the screenshot was taken from the cache so that we may
+        # retrieve the screenshot from the cache directly in the future
+        self.screenshot_cache = self.executor.screenshot_cache
+        self.message = None
+
+    def setup(self):
+        pass
+
+    def teardown(self):
+        pass
+
+    @property
+    def logger(self):
+        return self.executor.logger
+
+    def get_hash(self, test, viewport_size, dpi, page_ranges):
+        key = (test.url, viewport_size, dpi)
+
+        if key not in self.screenshot_cache:
+            success, data = self.get_screenshot_list(test, viewport_size, dpi, page_ranges)
+
+            if not success:
+                return False, data
+
+            screenshots = data
+            hash_values = hash_screenshots(data)
+            self.screenshot_cache[key] = (hash_values, screenshots)
+
+            rv = (hash_values, screenshots)
+        else:
+            rv = self.screenshot_cache[key]
+
+        self.message.append("%s %s" % (test.url, rv[0]))
+        return True, rv
+
+    def reset(self):
+        self.screenshot_cache.clear()
+
+    def check_pass(self, hashes, screenshots, urls, relation, fuzzy):
+        """Check if a test passes, and return a tuple of (pass, page_idx),
+        where page_idx is the zero-based index of the first page on which a
+        difference occurs if any, or None if there are no differences"""
+
+        assert relation in ("==", "!=")
+        lhs_hashes, rhs_hashes = hashes
+        lhs_screenshots, rhs_screenshots = screenshots
+
+        if len(lhs_hashes) != len(rhs_hashes):
+            self.logger.info("Got different number of pages")
+            return False
+
+        assert len(lhs_screenshots) == len(lhs_hashes) == len(rhs_screenshots) == len(rhs_hashes)
+
+        for (page_idx, (lhs_hash,
+                        rhs_hash,
+                        lhs_screenshot,
+                        rhs_screenshot)) in enumerate(zip(lhs_hashes,
+                                                          rhs_hashes,
+                                                          lhs_screenshots,
+                                                          rhs_screenshots)):
+            comparison_screenshots = (lhs_screenshot, rhs_screenshot)
+            if not fuzzy or fuzzy == ((0, 0), (0, 0)):
+                equal = lhs_hash == rhs_hash
+                # sometimes images can have different hashes, but pixels can be identical.
+                if not equal:
+                    self.logger.info("Image hashes didn't match%s, checking pixel differences" %
+                                     ("" if len(hashes) == 1 else " on page %i" % (page_idx + 1)))
+                    max_per_channel, pixels_different = self.get_differences(comparison_screenshots,
+                                                                             urls)
+                    equal = pixels_different == 0 and max_per_channel == 0
+            else:
+                max_per_channel, pixels_different = self.get_differences(comparison_screenshots,
+                                                                         urls,
+                                                                         page_idx if len(hashes) > 1 else None)
+                allowed_per_channel, allowed_different = fuzzy
+                self.logger.info("Allowed %s pixels different, maximum difference per channel %s" %
+                                 ("-".join(str(item) for item in allowed_different),
+                                  "-".join(str(item) for item in allowed_per_channel)))
+                equal = ((pixels_different == 0 and allowed_different[0] == 0) or
+                         (max_per_channel == 0 and allowed_per_channel[0] == 0) or
+                         (allowed_per_channel[0] <= max_per_channel <= allowed_per_channel[1] and
+                          allowed_different[0] <= pixels_different <= allowed_different[1]))
+            if not equal:
+                return (False if relation == "==" else True, page_idx)
+        # All screenshots were equal within the fuzziness
+        return (True if relation == "==" else False, None)
+
+    def get_differences(self, screenshots, urls, page_idx=None):
+        from PIL import Image, ImageChops, ImageStat
+
+        lhs = Image.open(io.BytesIO(base64.b64decode(screenshots[0]))).convert("RGB")
+        rhs = Image.open(io.BytesIO(base64.b64decode(screenshots[1]))).convert("RGB")
+        self.check_if_solid_color(lhs, urls[0])
+        self.check_if_solid_color(rhs, urls[1])
+        diff = ImageChops.difference(lhs, rhs)
+        minimal_diff = diff.crop(diff.getbbox())
+        mask = minimal_diff.convert("L", dither=None)
+        stat = ImageStat.Stat(minimal_diff, mask)
+        per_channel = max(item[1] for item in stat.extrema)
+        count = stat.count[0]
+        self.logger.info("Found %s pixels different, maximum difference per channel %s%s" %
+                         (count,
+                          per_channel,
+                          "" if page_idx is None else " on page %i" % (page_idx + 1)))
+        return per_channel, count
+
+    def check_if_solid_color(self, image, url):
+        extrema = image.getextrema()
+        if all(min == max for min, max in extrema):
+            color = ''.join('%02X' % value for value, _ in extrema)
+            self.message.append("Screenshot is solid color 0x%s for %s\n" % (color, url))
+
+    def run_test(self, test):
+        viewport_size = test.viewport_size
+        dpi = test.dpi
+        page_ranges = test.page_ranges
+        self.message = []
+
+
+        # Depth-first search of reference tree, with the goal
+        # of reachings a leaf node with only pass results
+
+        stack = list(((test, item[0]), item[1]) for item in reversed(test.references))
+        page_idx = None
+        while stack:
+            hashes = [None, None]
+            screenshots = [None, None]
+            urls = [None, None]
+
+            nodes, relation = stack.pop()
+            fuzzy = self.get_fuzzy(test, nodes, relation)
+
+            for i, node in enumerate(nodes):
+                success, data = self.get_hash(node, viewport_size, dpi, page_ranges)
+                if success is False:
+                    return {"status": data[0], "message": data[1]}
+
+                hashes[i], screenshots[i] = data
+                urls[i] = node.url
+
+            is_pass, page_idx = self.check_pass(hashes, screenshots, urls, relation, fuzzy)
+            if is_pass:
+                fuzzy = self.get_fuzzy(test, nodes, relation)
+                if nodes[1].references:
+                    stack.extend(list(((nodes[1], item[0]), item[1])
+                                      for item in reversed(nodes[1].references)))
+                else:
+                    # We passed
+                    return {"status": "PASS", "message": None}
+
+        # We failed, so construct a failure message
+
+        if page_idx is None:
+            # default to outputting the last page
+            page_idx = -1
+        for i, (node, screenshot) in enumerate(zip(nodes, screenshots)):
+            if screenshot is None:
+                success, screenshot = self.retake_screenshot(node, viewport_size, dpi, page_ranges)
+                if success:
+                    screenshots[i] = screenshot
+
+        log_data = [
+            {"url": nodes[0].url,
+             "screenshot": screenshots[0][page_idx],
+             "hash": hashes[0][page_idx]},
+            relation,
+            {"url": nodes[1].url,
+             "screenshot": screenshots[1][page_idx],
+             "hash": hashes[1][page_idx]},
+        ]
+
+        return {"status": "FAIL",
+                "message": "\n".join(self.message),
+                "extra": {"reftest_screenshots": log_data}}
+
+    def get_fuzzy(self, root_test, test_nodes, relation):
+        full_key = tuple([item.url for item in test_nodes] + [relation])
+        ref_only_key = test_nodes[1].url
+
+        fuzzy_override = root_test.fuzzy_override
+        fuzzy = test_nodes[0].fuzzy
+
+        sources = [fuzzy_override, fuzzy]
+        keys = [full_key, ref_only_key, None]
+        value = None
+        for source in sources:
+            for key in keys:
+                if key in source:
+                    value = source[key]
+                    break
+            if value:
+                break
+        return value
+
+    def retake_screenshot(self, node, viewport_size, dpi, page_ranges):
+        success, data = self.get_screenshot_list(node,
+                                                 viewport_size,
+                                                 dpi,
+                                                 page_ranges)
+        if not success:
+            return False, data
+
+        key = (node.url, viewport_size, dpi)
+        hash_val, _ = self.screenshot_cache[key]
+        self.screenshot_cache[key] = hash_val, data
+        return True, data
+
+    def get_screenshot_list(self, node, viewport_size, dpi, page_ranges):
+        success, data = self.executor.screenshot(node, viewport_size, dpi, page_ranges)
+        if success and not isinstance(data, list):
+            return success, [data]
+        return success, data
+
+
+class WdspecExecutor(TestExecutor):
+    convert_result = pytest_result_converter
+    protocol_cls = None
+
+    def __init__(self, logger, browser, server_config, webdriver_binary,
+                 webdriver_args, timeout_multiplier=1, capabilities=None,
+                 debug_info=None, environ=None, **kwargs):
+        self.do_delayed_imports()
+        TestExecutor.__init__(self, logger, browser, server_config,
+                              timeout_multiplier=timeout_multiplier,
+                              debug_info=debug_info)
+        self.webdriver_binary = webdriver_binary
+        self.webdriver_args = webdriver_args
+        self.timeout_multiplier = timeout_multiplier
+        self.capabilities = capabilities
+        self.environ = environ if environ is not None else {}
+        self.protocol = self.protocol_cls(self, browser)
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        pass
+
+    def do_test(self, test):
+        timeout = test.timeout * self.timeout_multiplier + self.extra_timeout
+
+        success, data = WdspecRun(self.do_wdspec,
+                                  self.protocol.session_config,
+                                  test.abs_path,
+                                  timeout).run()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_wdspec(self, session_config, path, timeout):
+        return pytestrunner.run(path,
+                                self.server_config,
+                                session_config,
+                                timeout=timeout,
+                                environ=self.environ)
+
+    def do_delayed_imports(self):
+        global pytestrunner
+        from . import pytestrunner
+
+
+class WdspecRun(object):
+    def __init__(self, func, session, path, timeout):
+        self.func = func
+        self.result = (None, None)
+        self.session = session
+        self.path = path
+        self.timeout = timeout
+        self.result_flag = threading.Event()
+
+    def run(self):
+        """Runs function in a thread and interrupts it if it exceeds the
+        given timeout.  Returns (True, (Result, [SubtestResult ...])) in
+        case of success, or (False, (status, extra information)) in the
+        event of failure.
+        """
+
+        executor = threading.Thread(target=self._run)
+        executor.start()
+
+        self.result_flag.wait(self.timeout)
+        if self.result[1] is None:
+            self.result = False, ("EXTERNAL-TIMEOUT", None)
+
+        return self.result
+
+    def _run(self):
+        try:
+            self.result = True, self.func(self.session, self.path, self.timeout)
+        except (socket.timeout, IOError):
+            self.result = False, ("CRASH", None)
+        except Exception as e:
+            message = getattr(e, "message")
+            if message:
+                message += "\n"
+            message += traceback.format_exc()
+            self.result = False, ("INTERNAL-ERROR", message)
+        finally:
+            self.result_flag.set()
+
+
+class ConnectionlessBaseProtocolPart(BaseProtocolPart):
+    def load(self, url):
+        pass
+
+    def execute_script(self, script, asynchronous=False):
+        pass
+
+    def set_timeout(self, timeout):
+        pass
+
+    def wait(self):
+        pass
+
+    def set_window(self, handle):
+        pass
+
+    def window_handles(self):
+        return []
+
+
+class ConnectionlessProtocol(Protocol):
+    implements = [ConnectionlessBaseProtocolPart]
+
+    def connect(self):
+        pass
+
+    def after_connect(self):
+        pass
+
+
+class WdspecProtocol(Protocol):
+    server_cls = None
+
+    implements = [ConnectionlessBaseProtocolPart]
+
+    def __init__(self, executor, browser):
+        Protocol.__init__(self, executor, browser)
+        self.webdriver_binary = executor.webdriver_binary
+        self.webdriver_args = executor.webdriver_args
+        self.capabilities = self.executor.capabilities
+        self.session_config = None
+        self.server = None
+
+    def connect(self):
+        """Connect to browser via the HTTP server."""
+        self.server = self.server_cls(
+            self.logger,
+            binary=self.webdriver_binary,
+            args=self.webdriver_args)
+        self.server.start(block=False)
+        self.logger.info(
+            "WebDriver HTTP server listening at %s" % self.server.url)
+        self.session_config = {"host": self.server.host,
+                               "port": self.server.port,
+                               "capabilities": self.capabilities}
+
+    def after_connect(self):
+        pass
+
+    def teardown(self):
+        if self.server is not None and self.server.is_alive():
+            self.server.stop()
+
+    def is_alive(self):
+        """Test that the connection is still alive.
+
+        Because the remote communication happens over HTTP we need to
+        make an explicit request to the remote.  It is allowed for
+        WebDriver spec tests to not have a WebDriver session, since this
+        may be what is tested.
+
+        An HTTP request to an invalid path that results in a 404 is
+        proof enough to us that the server is alive and kicking.
+        """
+        conn = HTTPConnection(self.server.host, self.server.port)
+        conn.request("HEAD", self.server.base_path + "invalid")
+        res = conn.getresponse()
+        return res.status == 404
+
+
+class CallbackHandler(object):
+    """Handle callbacks from testdriver-using tests.
+
+    The default implementation here makes sense for things that are roughly like
+    WebDriver. Things that are more different to WebDriver may need to create a
+    fully custom implementation."""
+
+    unimplemented_exc = (NotImplementedError,)
+
+    def __init__(self, logger, protocol, test_window):
+        self.protocol = protocol
+        self.test_window = test_window
+        self.logger = logger
+        self.callbacks = {
+            "action": self.process_action,
+            "complete": self.process_complete
+        }
+
+        self.actions = {cls.name: cls(self.logger, self.protocol) for cls in actions}
+
+    def __call__(self, result):
+        url, command, payload = result
+        self.logger.debug("Got async callback: %s" % result[1])
+        try:
+            callback = self.callbacks[command]
+        except KeyError:
+            raise ValueError("Unknown callback type %r" % result[1])
+        return callback(url, payload)
+
+    def process_complete(self, url, payload):
+        rv = [strip_server(url)] + payload
+        return True, rv
+
+    def process_action(self, url, payload):
+        action = payload["action"]
+        cmd_id = payload["id"]
+        self.logger.debug("Got action: %s" % action)
+        try:
+            action_handler = self.actions[action]
+        except KeyError:
+            raise ValueError("Unknown action %s" % action)
+        try:
+            with ActionContext(self.logger, self.protocol, payload.get("context")):
+                result = action_handler(payload)
+        except self.unimplemented_exc:
+            self.logger.warning("Action %s not implemented" % action)
+            self._send_message(cmd_id, "complete", "error", "Action %s not implemented" % action)
+        except Exception:
+            self.logger.warning("Action %s failed" % action)
+            self.logger.warning(traceback.format_exc())
+            self._send_message(cmd_id, "complete", "error")
+            raise
+        else:
+            self.logger.debug("Action %s completed with result %s" % (action, result))
+            return_message = {"result": result}
+            self._send_message(cmd_id, "complete", "success", json.dumps(return_message))
+
+        return False, None
+
+    def _send_message(self, cmd_id, message_type, status, message=None):
+        self.protocol.testdriver.send_message(cmd_id, message_type, status, message=message)
+
+
+class ActionContext(object):
+    def __init__(self, logger, protocol, context):
+        self.logger = logger
+        self.protocol = protocol
+        self.context = context
+        self.initial_window = None
+
+    def __enter__(self):
+        if self.context is None:
+            return
+
+        self.initial_window = self.protocol.base.current_window
+        self.logger.debug("Switching to window %s" % self.context)
+        self.protocol.testdriver.switch_to_window(self.context)
+
+    def __exit__(self, *args):
+        if self.context is None:
+            return
+
+        self.logger.debug("Switching back to initial window")
+        self.protocol.base.set_window(self.initial_window)
+        self.protocol.testdriver._switch_to_frame(None)
+        self.initial_window = None
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py
new file mode 100644
index 0000000..3a70475
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorchrome.py
@@ -0,0 +1,121 @@
+import os
+import traceback
+
+from six.moves.urllib.parse import urljoin
+
+from .base import WdspecProtocol, WdspecExecutor, get_pages
+from .executorwebdriver import WebDriverProtocol, WebDriverRefTestExecutor, WebDriverRun
+from .protocol import PrintProtocolPart
+from ..webdriver_server import ChromeDriverServer
+
+here = os.path.dirname(__file__)
+
+
+class ChromeDriverPrintProtocolPart(PrintProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+        self.runner_handle = None
+
+    def load_runner(self):
+        url = urljoin(self.parent.executor.server_url("http"), "/print_reftest_runner.html")
+        self.logger.debug("Loading %s" % url)
+        try:
+            self.webdriver.url = url
+        except Exception as e:
+            self.logger.critical(
+                "Loading initial page %s failed. Ensure that the "
+                "there are no other programs bound to this port and "
+                "that your firewall rules or network setup does not "
+                "prevent access.\n%s" % (url, traceback.format_exc(e)))
+            raise
+        self.runner_handle = self.webdriver.window_handle
+
+    def render_as_pdf(self, width, height):
+        margin = 0.5
+        body = {
+            "cmd": "Page.printToPDF",
+            "params": {
+                # Chrome accepts dimensions in inches; we are using cm
+                "paperWidth": width / 2.54,
+                "paperHeight": height / 2.54,
+                "marginLeft": margin,
+                "marginRight": margin,
+                "marginTop": margin,
+                "marginBottom": margin,
+                "shrinkToFit": False,
+                "printBackground": True,
+            }
+        }
+        return self.webdriver.send_session_command("POST", "goog/cdp/execute", body=body)["data"]
+
+    def pdf_to_png(self, pdf_base64, ranges):
+        handle = self.webdriver.window_handle
+        self.webdriver.window_handle = self.runner_handle
+        try:
+            rv = self.webdriver.execute_async_script("""
+let callback = arguments[arguments.length - 1];
+render('%s').then(result => callback(result))""" % pdf_base64)
+            page_numbers = get_pages(ranges, len(rv))
+            rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
+            return rv
+        finally:
+            self.webdriver.window_handle = handle
+
+
+class ChromeDriverProtocol(WebDriverProtocol):
+    implements = WebDriverProtocol.implements + [ChromeDriverPrintProtocolPart]
+
+
+class ChromeDriverPrintRefTestExecutor(WebDriverRefTestExecutor):
+    protocol_cls = ChromeDriverProtocol
+
+    def setup(self, runner):
+        super(ChromeDriverPrintRefTestExecutor, self).setup(runner)
+        self.protocol.pdf_print.load_runner()
+        self.has_window = False
+        with open(os.path.join(here, "reftest.js")) as f:
+            self.script = f.read()
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7140
+        assert dpi is None
+
+        if not self.has_window:
+            self.protocol.base.execute_script(self.script)
+            self.protocol.base.set_window(self.protocol.webdriver.handles[-1])
+            self.has_window = True
+
+        self.viewport_size = viewport_size
+        self.page_ranges = page_ranges.get(test.url)
+        timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
+
+        test_url = self.test_url(test)
+
+        return WebDriverRun(self.logger,
+                            self._render,
+                            self.protocol,
+                            test_url,
+                            timeout,
+                            self.extra_timeout).run()
+
+    def _render(self, protocol, url, timeout):
+        protocol.webdriver.url = url
+
+        protocol.base.execute_script(self.wait_script, asynchronous=True)
+
+        pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
+        screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
+        for i, screenshot in enumerate(screenshots):
+            # strip off the data:img/png, part of the url
+            if screenshot.startswith("data:image/png;base64,"):
+                screenshots[i] = screenshot.split(",", 1)[1]
+
+        return screenshots
+
+
+class ChromeDriverWdspecProtocol(WdspecProtocol):
+    server_cls = ChromeDriverServer
+
+
+class ChromeDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = ChromeDriverWdspecProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredge.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredge.py
new file mode 100644
index 0000000..a43d9cf
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredge.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import EdgeDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class EdgeDriverProtocol(WdspecProtocol):
+    server_cls = EdgeDriverServer
+
+
+class EdgeDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = EdgeDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredgechromium.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredgechromium.py
new file mode 100644
index 0000000..ebba06a
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoredgechromium.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import EdgeChromiumDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class EdgeChromiumDriverProtocol(WdspecProtocol):
+    server_cls = EdgeChromiumDriverServer
+
+
+class EdgeChromiumDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = EdgeChromiumDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorinternetexplorer.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorinternetexplorer.py
new file mode 100644
index 0000000..9f6a16e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorinternetexplorer.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import InternetExplorerDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class InternetExplorerDriverProtocol(WdspecProtocol):
+    server_cls = InternetExplorerDriverServer
+
+
+class InternetExplorerDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = InternetExplorerDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
new file mode 100644
index 0000000..e5d7683
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executormarionette.py
@@ -0,0 +1,1208 @@
+import json
+import os
+import threading
+import time
+import traceback
+import uuid
+
+from six import iteritems, iterkeys
+from six.moves.urllib.parse import urljoin
+
+errors = None
+marionette = None
+pytestrunner = None
+
+here = os.path.dirname(__file__)
+
+from .base import (CallbackHandler,
+                   CrashtestExecutor,
+                   RefTestExecutor,
+                   RefTestImplementation,
+                   TestharnessExecutor,
+                   TimedRunner,
+                   WdspecExecutor,
+                   WdspecProtocol,
+                   get_pages,
+                   strip_server)
+from .protocol import (ActionSequenceProtocolPart,
+                       AssertsProtocolPart,
+                       BaseProtocolPart,
+                       TestharnessProtocolPart,
+                       PrefsProtocolPart,
+                       Protocol,
+                       StorageProtocolPart,
+                       SelectorProtocolPart,
+                       ClickProtocolPart,
+                       CookiesProtocolPart,
+                       SendKeysProtocolPart,
+                       TestDriverProtocolPart,
+                       CoverageProtocolPart,
+                       GenerateTestReportProtocolPart,
+                       VirtualAuthenticatorProtocolPart,
+                       SetPermissionProtocolPart,
+                       PrintProtocolPart)
+from ..webdriver_server import GeckoDriverServer
+
+
+def do_delayed_imports():
+    global errors, marionette, Addons
+
+    from marionette_driver import marionette, errors
+    from marionette_driver.addons import Addons
+
+
+def _switch_to_window(marionette, handle):
+    """Switch to the specified window; subsequent commands will be
+    directed at the new window.
+
+    This is a workaround for issue 24924[0]; marionettedriver 3.1.0 dropped the
+    'name' parameter from its switch_to_window command, but it is still needed
+    for at least Firefox 79.
+
+    [0]: https://github.com/web-platform-tests/wpt/issues/24924
+
+    :param marionette: The Marionette instance
+    :param handle: The id of the window to switch to.
+    """
+    marionette._send_message("WebDriver:SwitchToWindow",
+                             {"handle": handle, "name": handle, "focus": True})
+    marionette.window = handle
+
+
+class MarionetteBaseProtocolPart(BaseProtocolPart):
+    def __init__(self, parent):
+        super(MarionetteBaseProtocolPart, self).__init__(parent)
+        self.timeout = None
+
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def execute_script(self, script, asynchronous=False):
+        method = self.marionette.execute_async_script if asynchronous else self.marionette.execute_script
+        return method(script, new_sandbox=False, sandbox=None)
+
+    def set_timeout(self, timeout):
+        """Set the Marionette script timeout.
+
+        :param timeout: Script timeout in seconds
+
+        """
+        if timeout != self.timeout:
+            self.marionette.timeout.script = timeout
+            self.timeout = timeout
+
+    @property
+    def current_window(self):
+        return self.marionette.current_window_handle
+
+    def set_window(self, handle):
+        _switch_to_window(self.marionette, handle)
+
+    def window_handles(self):
+        return self.marionette.window_handles
+
+    def load(self, url):
+        self.marionette.navigate(url)
+
+    def wait(self):
+        try:
+            socket_timeout = self.marionette.client.socket_timeout
+        except AttributeError:
+            # This can happen if there was a crash
+            return
+        if socket_timeout:
+            try:
+                self.marionette.timeout.script = socket_timeout / 2
+            except IOError:
+                self.logger.debug("Socket closed")
+                return
+
+        while True:
+            try:
+                self.marionette.execute_async_script("")
+            except errors.NoSuchWindowException:
+                # The window closed
+                break
+            except errors.ScriptTimeoutException:
+                self.logger.debug("Script timed out")
+                pass
+            except errors.JavascriptException as e:
+                # This can happen if we navigate, but just keep going
+                self.logger.debug(e.message)
+                pass
+            except IOError:
+                self.logger.debug("Socket closed")
+                break
+            except Exception:
+                self.logger.warning(traceback.format_exc())
+                break
+
+
+class MarionetteTestharnessProtocolPart(TestharnessProtocolPart):
+    def __init__(self, parent):
+        super(MarionetteTestharnessProtocolPart, self).__init__(parent)
+        self.runner_handle = None
+        with open(os.path.join(here, "runner.js")) as f:
+            self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
+
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def load_runner(self, url_protocol):
+        # Check if we previously had a test window open, and if we did make sure it's closed
+        if self.runner_handle:
+            self._close_windows()
+        url = urljoin(self.parent.executor.server_url(url_protocol), "/testharness_runner.html")
+        self.logger.debug("Loading %s" % url)
+        try:
+            self.dismiss_alert(lambda: self.marionette.navigate(url))
+        except Exception:
+            self.logger.critical(
+                "Loading initial page %s failed. Ensure that the "
+                "there are no other programs bound to this port and "
+                "that your firewall rules or network setup does not "
+                "prevent access.\n%s" % (url, traceback.format_exc()))
+            raise
+        self.runner_handle = self.marionette.current_window_handle
+        format_map = {"title": threading.current_thread().name.replace("'", '"')}
+        self.parent.base.execute_script(self.runner_script % format_map)
+
+    def _close_windows(self):
+        handles = self.marionette.window_handles
+        runner_handle = None
+        try:
+            handles.remove(self.runner_handle)
+            runner_handle = self.runner_handle
+        except ValueError:
+            # The runner window probably changed id but we can restore it
+            # This isn't supposed to happen, but marionette ids are not yet stable
+            # We assume that the first handle returned corresponds to the runner,
+            # but it hopefully doesn't matter too much if that assumption is
+            # wrong since we reload the runner in that tab anyway.
+            runner_handle = handles.pop(0)
+            self.logger.info("Changing harness_window to %s" % runner_handle)
+
+        for handle in handles:
+            try:
+                self.logger.info("Closing window %s" % handle)
+                _switch_to_window(self.marionette, handle)
+                self.dismiss_alert(lambda: self.marionette.close())
+            except errors.NoSuchWindowException:
+                # We might have raced with the previous test to close this
+                # window, skip it.
+                pass
+        _switch_to_window(self.marionette, runner_handle)
+        return runner_handle
+
+    def close_old_windows(self, url_protocol):
+        runner_handle = self._close_windows()
+        if runner_handle != self.runner_handle:
+            self.load_runner(url_protocol)
+        return self.runner_handle
+
+    def dismiss_alert(self, f):
+        while True:
+            try:
+                f()
+            except errors.UnexpectedAlertOpen:
+                alert = self.marionette.switch_to_alert()
+                try:
+                    alert.dismiss()
+                except errors.NoAlertPresentException:
+                    pass
+            else:
+                break
+
+    def get_test_window(self, window_id, parent, timeout=5):
+        """Find the test window amongst all the open windows.
+        This is assumed to be either the named window or the one after the parent in the list of
+        window handles
+
+        :param window_id: The DOM name of the Window
+        :param parent: The handle of the runner window
+        :param timeout: The time in seconds to wait for the window to appear. This is because in
+                        some implementations there's a race between calling window.open and the
+                        window being added to the list of WebDriver accessible windows."""
+        test_window = None
+        end_time = time.time() + timeout
+        while time.time() < end_time:
+            if window_id:
+                try:
+                    # Try this, it's in Level 1 but nothing supports it yet
+                    win_s = self.parent.base.execute_script("return window['%s'];" % self.window_id)
+                    win_obj = json.loads(win_s)
+                    test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
+                except Exception:
+                    pass
+
+            if test_window is None:
+                handles = self.marionette.window_handles
+                if len(handles) == 2:
+                    test_window = next(iter(set(handles) - {parent}))
+                elif len(handles) > 2 and handles[0] == parent:
+                    # Hope the first one here is the test window
+                    test_window = handles[1]
+
+            if test_window is not None:
+                assert test_window != parent
+                return test_window
+
+            time.sleep(0.1)
+
+        raise Exception("unable to find test window")
+
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.parent.base.execute_script(self.window_loaded_script, asynchronous=True)
+                break
+            except errors.JavascriptException:
+                pass
+
+
+class MarionettePrefsProtocolPart(PrefsProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def set(self, name, value):
+        if value.lower() not in ("true", "false"):
+            try:
+                int(value)
+            except ValueError:
+                value = "'%s'" % value
+        else:
+            value = value.lower()
+
+        self.logger.info("Setting pref %s (%s)" % (name, value))
+
+        script = """
+            let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
+                                          .getService(Components.interfaces.nsIPrefBranch);
+            let pref = '%s';
+            let type = prefInterface.getPrefType(pref);
+            let value = %s;
+            switch(type) {
+                case prefInterface.PREF_STRING:
+                    prefInterface.setCharPref(pref, value);
+                    break;
+                case prefInterface.PREF_BOOL:
+                    prefInterface.setBoolPref(pref, value);
+                    break;
+                case prefInterface.PREF_INT:
+                    prefInterface.setIntPref(pref, value);
+                    break;
+                case prefInterface.PREF_INVALID:
+                    // Pref doesn't seem to be defined already; guess at the
+                    // right way to set it based on the type of value we have.
+                    switch (typeof value) {
+                        case "boolean":
+                            prefInterface.setBoolPref(pref, value);
+                            break;
+                        case "string":
+                            prefInterface.setCharPref(pref, value);
+                            break;
+                        case "number":
+                            prefInterface.setIntPref(pref, value);
+                            break;
+                        default:
+                            throw new Error("Unknown pref value type: " + (typeof value));
+                    }
+                    break;
+                default:
+                    throw new Error("Unknown pref type " + type);
+            }
+            """ % (name, value)
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script(script)
+
+    def clear(self, name):
+        self.logger.info("Clearing pref %s" % (name))
+        script = """
+            let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
+                                          .getService(Components.interfaces.nsIPrefBranch);
+            let pref = '%s';
+            prefInterface.clearUserPref(pref);
+            """ % name
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script(script)
+
+    def get(self, name):
+        script = """
+            let prefInterface = Components.classes["@mozilla.org/preferences-service;1"]
+                                          .getService(Components.interfaces.nsIPrefBranch);
+            let pref = '%s';
+            let type = prefInterface.getPrefType(pref);
+            switch(type) {
+                case prefInterface.PREF_STRING:
+                    return prefInterface.getCharPref(pref);
+                case prefInterface.PREF_BOOL:
+                    return prefInterface.getBoolPref(pref);
+                case prefInterface.PREF_INT:
+                    return prefInterface.getIntPref(pref);
+                case prefInterface.PREF_INVALID:
+                    return null;
+            }
+            """ % name
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script(script)
+
+
+class MarionetteStorageProtocolPart(StorageProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def clear_origin(self, url):
+        self.logger.info("Clearing origin %s" % (url))
+        script = """
+            let url = '%s';
+            let uri = Components.classes["@mozilla.org/network/io-service;1"]
+                                .getService(Ci.nsIIOService)
+                                .newURI(url);
+            let ssm = Components.classes["@mozilla.org/scriptsecuritymanager;1"]
+                                .getService(Ci.nsIScriptSecurityManager);
+            let principal = ssm.createContentPrincipal(uri, {});
+            let qms = Components.classes["@mozilla.org/dom/quota-manager-service;1"]
+                                .getService(Components.interfaces.nsIQuotaManagerService);
+            qms.clearStoragesForPrincipal(principal, "default", null, true);
+            """ % url
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.marionette.execute_script(script)
+
+
+class MarionetteAssertsProtocolPart(AssertsProtocolPart):
+    def setup(self):
+        self.assert_count = {"chrome": 0, "content": 0}
+        self.chrome_assert_count = 0
+        self.marionette = self.parent.marionette
+
+    def get(self):
+        script = """
+        debug = Cc["@mozilla.org/xpcom/debug;1"].getService(Ci.nsIDebug2);
+        if (debug.isDebugBuild) {
+          return debug.assertionCount;
+        }
+        return 0;
+        """
+
+        def get_count(context, **kwargs):
+            try:
+                context_count = self.marionette.execute_script(script, **kwargs)
+                if context_count:
+                    self.parent.logger.info("Got %s assert count %s" % (context, context_count))
+                    test_count = context_count - self.assert_count[context]
+                    self.assert_count[context] = context_count
+                    return test_count
+            except errors.NoSuchWindowException:
+                # If the window was already closed
+                self.parent.logger.warning("Failed to get assertion count; window was closed")
+            except (errors.MarionetteException, IOError):
+                # This usually happens if the process crashed
+                pass
+
+        counts = []
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            counts.append(get_count("chrome"))
+        if self.parent.e10s:
+            counts.append(get_count("content", sandbox="system"))
+
+        counts = [item for item in counts if item is not None]
+
+        if not counts:
+            return None
+
+        return sum(counts)
+
+
+class MarionetteSelectorProtocolPart(SelectorProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def elements_by_selector(self, selector):
+        return self.marionette.find_elements("css selector", selector)
+
+
+class MarionetteClickProtocolPart(ClickProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def element(self, element):
+        return element.click()
+
+
+class MarionetteCookiesProtocolPart(CookiesProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def delete_all_cookies(self):
+        self.logger.info("Deleting all cookies")
+        return self.marionette.delete_all_cookies()
+
+
+class MarionetteSendKeysProtocolPart(SendKeysProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def send_keys(self, element, keys):
+        return element.send_keys(keys)
+
+
+class MarionetteActionSequenceProtocolPart(ActionSequenceProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def send_actions(self, actions):
+        actions = self.marionette._to_json(actions)
+        self.logger.info(actions)
+        self.marionette._send_message("WebDriver:PerformActions", actions)
+
+
+class MarionetteTestDriverProtocolPart(TestDriverProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def send_message(self, cmd_id, message_type, status, message=None):
+        obj = {
+            "cmd_id": cmd_id,
+            "type": "testdriver-%s" % str(message_type),
+            "status": str(status)
+        }
+        if message:
+            obj["message"] = str(message)
+        self.parent.base.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
+
+    def _switch_to_frame(self, frame_number):
+        self.marionette.switch_to_frame(frame_number)
+
+    def _switch_to_parent_frame(self):
+        self.marionette.switch_to_parent_frame()
+
+
+class MarionetteCoverageProtocolPart(CoverageProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+        if not self.parent.ccov:
+            self.is_enabled = False
+            return
+
+        script = """
+            const {PerTestCoverageUtils} = ChromeUtils.import("chrome://marionette/content/PerTestCoverageUtils.jsm");
+            return PerTestCoverageUtils.enabled;
+            """
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            self.is_enabled = self.marionette.execute_script(script)
+
+    def reset(self):
+        script = """
+            var callback = arguments[arguments.length - 1];
+
+            const {PerTestCoverageUtils} = ChromeUtils.import("chrome://marionette/content/PerTestCoverageUtils.jsm");
+            PerTestCoverageUtils.beforeTest().then(callback, callback);
+            """
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            try:
+                error = self.marionette.execute_async_script(script)
+                if error is not None:
+                    raise Exception('Failure while resetting counters: %s' % json.dumps(error))
+            except (errors.MarionetteException, IOError):
+                # This usually happens if the process crashed
+                pass
+
+    def dump(self):
+        if len(self.marionette.window_handles):
+            handle = self.marionette.window_handles[0]
+            _switch_to_window(self.marionette, handle)
+
+        script = """
+            var callback = arguments[arguments.length - 1];
+
+            const {PerTestCoverageUtils} = ChromeUtils.import("chrome://marionette/content/PerTestCoverageUtils.jsm");
+            PerTestCoverageUtils.afterTest().then(callback, callback);
+            """
+        with self.marionette.using_context(self.marionette.CONTEXT_CHROME):
+            try:
+                error = self.marionette.execute_async_script(script)
+                if error is not None:
+                    raise Exception('Failure while dumping counters: %s' % json.dumps(error))
+            except (errors.MarionetteException, IOError):
+                # This usually happens if the process crashed
+                pass
+
+class MarionetteGenerateTestReportProtocolPart(GenerateTestReportProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def generate_test_report(self, config):
+        raise NotImplementedError("generate_test_report not yet implemented")
+
+class MarionetteVirtualAuthenticatorProtocolPart(VirtualAuthenticatorProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def add_virtual_authenticator(self, config):
+        raise NotImplementedError("add_virtual_authenticator not yet implemented")
+
+    def remove_virtual_authenticator(self, authenticator_id):
+        raise NotImplementedError("remove_virtual_authenticator not yet implemented")
+
+    def add_credential(self, authenticator_id, credential):
+        raise NotImplementedError("add_credential not yet implemented")
+
+    def get_credentials(self, authenticator_id):
+        raise NotImplementedError("get_credentials not yet implemented")
+
+    def remove_credential(self, authenticator_id, credential_id):
+        raise NotImplementedError("remove_credential not yet implemented")
+
+    def remove_all_credentials(self, authenticator_id):
+        raise NotImplementedError("remove_all_credentials not yet implemented")
+
+    def set_user_verified(self, authenticator_id, uv):
+        raise NotImplementedError("set_user_verified not yet implemented")
+
+class MarionetteSetPermissionProtocolPart(SetPermissionProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+
+    def set_permission(self, name, state, one_realm):
+        raise NotImplementedError("set_permission not yet implemented")
+
+
+class MarionettePrintProtocolPart(PrintProtocolPart):
+    def setup(self):
+        self.marionette = self.parent.marionette
+        self.runner_handle = None
+
+    def load_runner(self):
+        url = urljoin(self.parent.executor.server_url("http"), "/print_reftest_runner.html")
+        self.logger.debug("Loading %s" % url)
+        try:
+            self.marionette.navigate(url)
+        except Exception as e:
+            self.logger.critical(
+                "Loading initial page %s failed. Ensure that the "
+                "there are no other programs bound to this port and "
+                "that your firewall rules or network setup does not "
+                "prevent access.\n%s" % (url, traceback.format_exc(e)))
+            raise
+        self.runner_handle = self.marionette.current_window_handle
+
+    def render_as_pdf(self, width, height):
+        margin = 0.5 * 2.54
+        body = {
+            "page": {
+                "width": width,
+                "height": height
+            },
+            "margin": {
+                "left": margin,
+                "right": margin,
+                "top": margin,
+                "bottom": margin,
+            },
+            "shrinkToFit": False,
+            "printBackground": True,
+        }
+        return self.marionette._send_message("WebDriver:Print", body, key="value")
+
+    def pdf_to_png(self, pdf_base64, page_ranges):
+        handle = self.marionette.current_window_handle
+        _switch_to_window(self.marionette, self.runner_handle)
+        try:
+            rv = self.marionette.execute_async_script("""
+let callback = arguments[arguments.length - 1];
+render('%s').then(result => callback(result))""" % pdf_base64, new_sandbox=False, sandbox=None)
+            page_numbers = get_pages(page_ranges, len(rv))
+            rv = [item for i, item in enumerate(rv) if i + 1 in page_numbers]
+            return rv
+        finally:
+            _switch_to_window(self.marionette, handle)
+
+class MarionetteProtocol(Protocol):
+    implements = [MarionetteBaseProtocolPart,
+                  MarionetteTestharnessProtocolPart,
+                  MarionettePrefsProtocolPart,
+                  MarionetteStorageProtocolPart,
+                  MarionetteSelectorProtocolPart,
+                  MarionetteClickProtocolPart,
+                  MarionetteCookiesProtocolPart,
+                  MarionetteSendKeysProtocolPart,
+                  MarionetteActionSequenceProtocolPart,
+                  MarionetteTestDriverProtocolPart,
+                  MarionetteAssertsProtocolPart,
+                  MarionetteCoverageProtocolPart,
+                  MarionetteGenerateTestReportProtocolPart,
+                  MarionetteVirtualAuthenticatorProtocolPart,
+                  MarionetteSetPermissionProtocolPart,
+                  MarionettePrintProtocolPart]
+
+    def __init__(self, executor, browser, capabilities=None, timeout_multiplier=1, e10s=True, ccov=False):
+        do_delayed_imports()
+
+        super(MarionetteProtocol, self).__init__(executor, browser)
+        self.marionette = None
+        self.marionette_port = browser.marionette_port
+        self.capabilities = capabilities
+        self.timeout_multiplier = timeout_multiplier
+        self.runner_handle = None
+        self.e10s = e10s
+        self.ccov = ccov
+
+    def connect(self):
+        self.logger.debug("Connecting to Marionette on port %i" % self.marionette_port)
+        startup_timeout = marionette.Marionette.DEFAULT_STARTUP_TIMEOUT * self.timeout_multiplier
+        self.marionette = marionette.Marionette(host='127.0.0.1',
+                                                port=self.marionette_port,
+                                                socket_timeout=None,
+                                                startup_timeout=startup_timeout)
+
+        self.logger.debug("Waiting for Marionette connection")
+        while True:
+            try:
+                self.marionette.raise_for_port()
+                break
+            except IOError:
+                # When running in a debugger wait indefinitely for Firefox to start
+                if self.executor.debug_info is None:
+                    raise
+
+        self.logger.debug("Starting Marionette session")
+        self.marionette.start_session(self.capabilities)
+        self.logger.debug("Marionette session started")
+
+    def after_connect(self):
+        pass
+
+    def teardown(self):
+        if self.marionette and self.marionette.session_id:
+            try:
+                self.marionette._request_in_app_shutdown()
+                self.marionette.delete_session(send_request=False)
+            except Exception:
+                # This is typically because the session never started
+                pass
+        if self.marionette is not None:
+            del self.marionette
+        super(MarionetteProtocol, self).teardown()
+
+    def is_alive(self):
+        try:
+            self.marionette.current_window_handle
+        except Exception:
+            return False
+        return True
+
+    def on_environment_change(self, old_environment, new_environment):
+        #Unset all the old prefs
+        for name in iterkeys(old_environment.get("prefs", {})):
+            value = self.executor.original_pref_values[name]
+            if value is None:
+                self.prefs.clear(name)
+            else:
+                self.prefs.set(name, value)
+
+        for name, value in iteritems(new_environment.get("prefs", {})):
+            self.executor.original_pref_values[name] = self.prefs.get(name)
+            self.prefs.set(name, value)
+
+
+class ExecuteAsyncScriptRun(TimedRunner):
+    def set_timeout(self):
+        timeout = self.timeout
+
+        try:
+            if timeout is not None:
+                self.protocol.base.set_timeout(timeout + self.extra_timeout)
+            else:
+                # We just want it to never time out, really, but marionette doesn't
+                # make that possible. It also seems to time out immediately if the
+                # timeout is set too high. This works at least.
+                self.protocol.base.set_timeout(2**28 - 1)
+        except IOError:
+            msg = "Lost marionette connection before starting test"
+            self.logger.error(msg)
+            return ("INTERNAL-ERROR", msg)
+
+    def before_run(self):
+        index = self.url.rfind("/storage/")
+        if index != -1:
+            # Clear storage
+            self.protocol.storage.clear_origin(self.url)
+
+    def run_func(self):
+        try:
+            self.result = True, self.func(self.protocol, self.url, self.timeout)
+        except errors.ScriptTimeoutException:
+            self.logger.debug("Got a marionette timeout")
+            self.result = False, ("EXTERNAL-TIMEOUT", None)
+        except IOError:
+            # This can happen on a crash
+            # Also, should check after the test if the firefox process is still running
+            # and otherwise ignore any other result and set it to crash
+            self.logger.info("IOError on command, setting status to CRASH")
+            self.result = False, ("CRASH", None)
+        except errors.NoSuchWindowException:
+            self.logger.info("NoSuchWindowException on command, setting status to CRASH")
+            self.result = False, ("CRASH", None)
+        except Exception as e:
+            if isinstance(e, errors.JavascriptException) and e.message.startswith("Document was unloaded"):
+                message = "Document unloaded; maybe test navigated the top-level-browsing context?"
+            else:
+                message = getattr(e, "message", "")
+                if message:
+                    message += "\n"
+                message += traceback.format_exc()
+                self.logger.warning(traceback.format_exc())
+            self.result = False, ("INTERNAL-ERROR", message)
+        finally:
+            self.result_flag.set()
+
+
+class MarionetteTestharnessExecutor(TestharnessExecutor):
+    supports_testdriver = True
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 close_after_done=True, debug_info=None, capabilities=None,
+                 debug=False, ccov=False, **kwargs):
+        """Marionette-based executor for testharness.js tests"""
+        TestharnessExecutor.__init__(self, logger, browser, server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+        self.protocol = MarionetteProtocol(self,
+                                           browser,
+                                           capabilities,
+                                           timeout_multiplier,
+                                           kwargs["e10s"],
+                                           ccov)
+        with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
+            self.script_resume = f.read()
+        self.close_after_done = close_after_done
+        self.window_id = str(uuid.uuid4())
+        self.debug = debug
+
+        self.install_extensions = browser.extensions
+
+        self.original_pref_values = {}
+
+        if marionette is None:
+            do_delayed_imports()
+
+    def setup(self, runner):
+        super(MarionetteTestharnessExecutor, self).setup(runner)
+        for extension_path in self.install_extensions:
+            self.logger.info("Installing extension from %s" % extension_path)
+            addons = Addons(self.protocol.marionette)
+            addons.install(extension_path)
+
+        self.protocol.testharness.load_runner(self.last_environment["protocol"])
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        self.protocol.on_environment_change(self.last_environment, new_environment)
+
+        if new_environment["protocol"] != self.last_environment["protocol"]:
+            self.protocol.testharness.load_runner(new_environment["protocol"])
+
+    def do_test(self, test):
+        timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
+                   else None)
+
+        success, data = ExecuteAsyncScriptRun(self.logger,
+                                              self.do_testharness,
+                                              self.protocol,
+                                              self.test_url(test),
+                                              timeout,
+                                              self.extra_timeout).run()
+        # The format of data depends on whether the test ran to completion or not
+        # For asserts we only care about the fact that if it didn't complete, the
+        # status is in the first field.
+        status = None
+        if not success:
+            status = data[0]
+
+        extra = None
+        if self.debug and (success or status not in ("CRASH", "INTERNAL-ERROR")):
+            assertion_count = self.protocol.asserts.get()
+            if assertion_count is not None:
+                extra = {"assertion_count": assertion_count}
+
+        if success:
+            return self.convert_result(test, data, extra=extra)
+
+        return (test.result_cls(extra=extra, *data), [])
+
+    def do_testharness(self, protocol, url, timeout):
+        parent_window = protocol.testharness.close_old_windows(protocol)
+
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.reset()
+
+        format_map = {"url": strip_server(url)}
+
+        protocol.base.execute_script("window.open('about:blank', '%s', 'noopener')" % self.window_id)
+        test_window = protocol.testharness.get_test_window(self.window_id, parent_window,
+                                                           timeout=10 * self.timeout_multiplier)
+        self.protocol.base.set_window(test_window)
+        protocol.testharness.test_window_loaded()
+
+        handler = CallbackHandler(self.logger, protocol, test_window)
+        protocol.marionette.navigate(url)
+        while True:
+            result = protocol.base.execute_script(
+                self.script_resume % format_map, asynchronous=True)
+            if result is None:
+                # This can happen if we get an content process crash
+                return None
+            done, rv = handler(result)
+            if done:
+                break
+
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.dump()
+
+        return rv
+
+
+class MarionetteRefTestExecutor(RefTestExecutor):
+    is_print = False
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, close_after_done=True,
+                 debug_info=None, reftest_internal=False,
+                 reftest_screenshot="unexpected", ccov=False,
+                 group_metadata=None, capabilities=None, debug=False,
+                 browser_version=None, **kwargs):
+        """Marionette-based executor for reftests"""
+        RefTestExecutor.__init__(self,
+                                 logger,
+                                 browser,
+                                 server_config,
+                                 screenshot_cache=screenshot_cache,
+                                 timeout_multiplier=timeout_multiplier,
+                                 debug_info=debug_info)
+        self.protocol = MarionetteProtocol(self, browser, capabilities,
+                                           timeout_multiplier, kwargs["e10s"],
+                                           ccov)
+        self.implementation = self.get_implementation(reftest_internal)
+        self.implementation_kwargs = {}
+        if reftest_internal:
+            self.implementation_kwargs["screenshot"] = reftest_screenshot
+            self.implementation_kwargs["chrome_scope"] = (browser_version is not None and
+                                                          int(browser_version.split(".")[0]) < 82)
+        self.close_after_done = close_after_done
+        self.has_window = False
+        self.original_pref_values = {}
+        self.group_metadata = group_metadata
+        self.debug = debug
+
+        with open(os.path.join(here, "reftest.js")) as f:
+            self.script = f.read()
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "reftest-wait"}
+
+    def get_implementation(self, reftest_internal):
+        return (InternalRefTestImplementation if reftest_internal
+                else RefTestImplementation)(self)
+
+    def setup(self, runner):
+        super(MarionetteRefTestExecutor, self).setup(runner)
+        self.implementation.setup(**self.implementation_kwargs)
+
+    def teardown(self):
+        try:
+            self.implementation.teardown()
+            if self.protocol.marionette and self.protocol.marionette.session_id:
+                handles = self.protocol.marionette.window_handles
+                if handles:
+                    _switch_to_window(self.protocol.marionette, handles[0])
+            super(MarionetteRefTestExecutor, self).teardown()
+        except Exception:
+            # Ignore errors during teardown
+            self.logger.warning("Exception during reftest teardown:\n%s" %
+                                traceback.format_exc())
+
+    def reset(self):
+        self.implementation.reset(**self.implementation_kwargs)
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        self.protocol.on_environment_change(self.last_environment, new_environment)
+
+    def do_test(self, test):
+        if not isinstance(self.implementation, InternalRefTestImplementation):
+            if self.close_after_done and self.has_window:
+                self.protocol.marionette.close()
+                _switch_to_window(self.protocol.marionette,
+                                 self.protocol.marionette.window_handles[-1])
+                self.has_window = False
+
+            if not self.has_window:
+                self.protocol.base.execute_script(self.script)
+                self.protocol.base.set_window(self.protocol.marionette.window_handles[-1])
+                self.has_window = True
+                self.protocol.testharness.test_window_loaded()
+
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.reset()
+
+        result = self.implementation.run_test(test)
+
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.dump()
+
+        if self.debug:
+            assertion_count = self.protocol.asserts.get()
+            if "extra" not in result:
+                result["extra"] = {}
+            if assertion_count is not None:
+                result["extra"]["assertion_count"] = assertion_count
+
+        return self.convert_result(test, result)
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7135
+        assert viewport_size is None
+        assert dpi is None
+
+        timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
+
+        test_url = self.test_url(test)
+
+        return ExecuteAsyncScriptRun(self.logger,
+                                     self._screenshot,
+                                     self.protocol,
+                                     test_url,
+                                     timeout,
+                                     self.extra_timeout).run()
+
+    def _screenshot(self, protocol, url, timeout):
+        protocol.marionette.navigate(url)
+
+        protocol.base.execute_script(self.wait_script, asynchronous=True)
+
+        screenshot = protocol.marionette.screenshot(full=False)
+        # strip off the data:img/png, part of the url
+        if screenshot.startswith("data:image/png;base64,"):
+            screenshot = screenshot.split(",", 1)[1]
+
+        return screenshot
+
+
+class InternalRefTestImplementation(RefTestImplementation):
+    def __init__(self, executor):
+        self.timeout_multiplier = executor.timeout_multiplier
+        self.executor = executor
+        self.chrome_scope = False
+
+    @property
+    def logger(self):
+        return self.executor.logger
+
+    def setup(self, screenshot="unexpected", chrome_scope=False):
+        data = {"screenshot": screenshot, "isPrint": self.executor.is_print}
+        if self.executor.group_metadata is not None:
+            data["urlCount"] = {urljoin(self.executor.server_url(key[0]), key[1]):value
+                                for key, value in iteritems(
+                                    self.executor.group_metadata.get("url_count", {}))
+                                if value > 1}
+        self.chrome_scope = chrome_scope
+        if chrome_scope:
+            self.logger.debug("Using marionette Chrome scope for reftests")
+            self.executor.protocol.marionette.set_context(self.executor.protocol.marionette.CONTEXT_CHROME)
+        self.executor.protocol.marionette._send_message("reftest:setup", data)
+
+    def reset(self, **kwargs):
+        # this is obvious wrong; it shouldn't be a no-op
+        # see https://github.com/web-platform-tests/wpt/issues/15604
+        pass
+
+    def run_test(self, test):
+        references = self.get_references(test, test)
+        timeout = (test.timeout * 1000) * self.timeout_multiplier
+        rv = self.executor.protocol.marionette._send_message("reftest:run",
+                                                             {"test": self.executor.test_url(test),
+                                                              "references": references,
+                                                              "expected": test.expected(),
+                                                              "timeout": timeout,
+                                                              "width": 800,
+                                                              "height": 600,
+                                                              "pageRanges": test.page_ranges})["value"]
+        return rv
+
+    def get_references(self, root_test, node):
+        rv = []
+        for item, relation in node.references:
+            rv.append([self.executor.test_url(item), self.get_references(root_test, item), relation,
+                       {"fuzzy": self.get_fuzzy(root_test, [node, item], relation)}])
+        return rv
+
+    def teardown(self):
+        try:
+            if self.executor.protocol.marionette and self.executor.protocol.marionette.session_id:
+                self.executor.protocol.marionette._send_message("reftest:teardown", {})
+                if self.chrome_scope:
+                    self.executor.protocol.marionette.set_context(
+                        self.executor.protocol.marionette.CONTEXT_CONTENT)
+                # the reftest runner opens/closes a window with focus, so as
+                # with after closing a window we need to give a new window
+                # focus
+                handles = self.executor.protocol.marionette.window_handles
+                if handles:
+                    _switch_to_window(self.executor.protocol.marionette, handles[0])
+        except Exception:
+            # Ignore errors during teardown
+            self.logger.warning(traceback.format_exc())
+
+
+class GeckoDriverProtocol(WdspecProtocol):
+    server_cls = GeckoDriverServer
+
+
+class MarionetteWdspecExecutor(WdspecExecutor):
+    protocol_cls = GeckoDriverProtocol
+
+
+class MarionetteCrashtestExecutor(CrashtestExecutor):
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 debug_info=None, capabilities=None, debug=False,
+                 ccov=False, **kwargs):
+        """Marionette-based executor for testharness.js tests"""
+        CrashtestExecutor.__init__(self, logger, browser, server_config,
+                                   timeout_multiplier=timeout_multiplier,
+                                   debug_info=debug_info)
+        self.protocol = MarionetteProtocol(self,
+                                           browser,
+                                           capabilities,
+                                           timeout_multiplier,
+                                           kwargs["e10s"],
+                                           ccov)
+
+        self.original_pref_values = {}
+        self.debug = debug
+
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "test-wait"}
+
+        if marionette is None:
+            do_delayed_imports()
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        self.protocol.on_environment_change(self.last_environment, new_environment)
+
+    def do_test(self, test):
+        timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
+                   else None)
+
+        success, data = ExecuteAsyncScriptRun(self.logger,
+                                              self.do_crashtest,
+                                              self.protocol,
+                                              self.test_url(test),
+                                              timeout,
+                                              self.extra_timeout).run()
+        status = None
+        if not success:
+            status = data[0]
+
+        extra = None
+        if self.debug and (success or status not in ("CRASH", "INTERNAL-ERROR")):
+            assertion_count = self.protocol.asserts.get()
+            if assertion_count is not None:
+                extra = {"assertion_count": assertion_count}
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(extra=extra, *data), [])
+
+    def do_crashtest(self, protocol, url, timeout):
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.reset()
+
+        protocol.base.load(url)
+        protocol.base.execute_script(self.wait_script, asynchronous=True)
+
+        if self.protocol.coverage.is_enabled:
+            self.protocol.coverage.dump()
+
+        return {"status": "PASS",
+                "message": None}
+
+
+class MarionettePrintRefTestExecutor(MarionetteRefTestExecutor):
+    is_print = True
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, close_after_done=True,
+                 debug_info=None, reftest_screenshot="unexpected", ccov=False,
+                 group_metadata=None, capabilities=None, debug=False,
+                 reftest_internal=False, **kwargs):
+        """Marionette-based executor for reftests"""
+        MarionetteRefTestExecutor.__init__(self,
+                                           logger,
+                                           browser,
+                                           server_config,
+                                           timeout_multiplier=timeout_multiplier,
+                                           screenshot_cache=screenshot_cache,
+                                           close_after_done=close_after_done,
+                                           debug_info=debug_info,
+                                           reftest_screenshot=reftest_screenshot,
+                                           reftest_internal=reftest_internal,
+                                           ccov=ccov,
+                                           group_metadata=group_metadata,
+                                           capabilities=capabilities,
+                                           debug=debug,
+                                           **kwargs)
+
+    def setup(self, runner):
+        super(MarionettePrintRefTestExecutor, self).setup(runner)
+        if not isinstance(self.implementation, InternalRefTestImplementation):
+            self.protocol.pdf_print.load_runner()
+
+    def get_implementation(self, reftest_internal):
+        return (InternalRefTestImplementation if reftest_internal
+                else RefTestImplementation)(self)
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7140
+        assert dpi is None
+
+        self.viewport_size = viewport_size
+        timeout = self.timeout_multiplier * test.timeout if self.debug_info is None else None
+
+        test_url = self.test_url(test)
+        self.page_ranges = page_ranges.get(test.url)
+
+        return ExecuteAsyncScriptRun(self.logger,
+                                     self._render,
+                                     self.protocol,
+                                     test_url,
+                                     timeout,
+                                     self.extra_timeout).run()
+
+    def _render(self, protocol, url, timeout):
+        protocol.marionette.navigate(url)
+
+        protocol.base.execute_script(self.wait_script, asynchronous=True)
+
+        pdf = protocol.pdf_print.render_as_pdf(*self.viewport_size)
+        screenshots = protocol.pdf_print.pdf_to_png(pdf, self.page_ranges)
+        for i, screenshot in enumerate(screenshots):
+            # strip off the data:img/png, part of the url
+            if screenshot.startswith("data:image/png;base64,"):
+                screenshots[i] = screenshot.split(",", 1)[1]
+
+        return screenshots
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoropera.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoropera.py
new file mode 100644
index 0000000..3a945a1
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executoropera.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import OperaDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class OperaDriverProtocol(WdspecProtocol):
+    server_cls = OperaDriverServer
+
+
+class OperaDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = OperaDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorsafari.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorsafari.py
new file mode 100644
index 0000000..86d7fcd
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorsafari.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import SafariDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class SafariDriverProtocol(WdspecProtocol):
+    server_cls = SafariDriverServer
+
+
+class SafariDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = SafariDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
new file mode 100644
index 0000000..6070007
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorselenium.py
@@ -0,0 +1,455 @@
+from __future__ import absolute_import
+import json
+import os
+import socket
+import threading
+import time
+import traceback
+import uuid
+from six.moves.urllib.parse import urljoin
+
+from .base import (CallbackHandler,
+                   RefTestExecutor,
+                   RefTestImplementation,
+                   TestharnessExecutor,
+                   TimedRunner,
+                   strip_server)
+from .protocol import (BaseProtocolPart,
+                       TestharnessProtocolPart,
+                       Protocol,
+                       SelectorProtocolPart,
+                       ClickProtocolPart,
+                       CookiesProtocolPart,
+                       SendKeysProtocolPart,
+                       ActionSequenceProtocolPart,
+                       TestDriverProtocolPart)
+
+here = os.path.dirname(__file__)
+
+webdriver = None
+exceptions = None
+RemoteConnection = None
+Command = None
+
+
+def do_delayed_imports():
+    global webdriver
+    global exceptions
+    global RemoteConnection
+    global Command
+    from selenium import webdriver
+    from selenium.common import exceptions
+    from selenium.webdriver.remote.remote_connection import RemoteConnection
+    from selenium.webdriver.remote.command import Command
+
+
+class SeleniumBaseProtocolPart(BaseProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def execute_script(self, script, asynchronous=False):
+        method = self.webdriver.execute_async_script if asynchronous else self.webdriver.execute_script
+        return method(script)
+
+    def set_timeout(self, timeout):
+        self.webdriver.set_script_timeout(timeout * 1000)
+
+    @property
+    def current_window(self):
+        return self.webdriver.current_window_handle
+
+    def set_window(self, handle):
+        self.webdriver.switch_to_window(handle)
+
+    def window_handles(self):
+        return self.webdriver.window_handles
+
+    def load(self, url):
+        self.webdriver.get(url)
+
+    def wait(self):
+        while True:
+            try:
+                self.webdriver.execute_async_script("")
+            except exceptions.TimeoutException:
+                pass
+            except (socket.timeout, exceptions.NoSuchWindowException,
+                    exceptions.ErrorInResponseException, IOError):
+                break
+            except Exception:
+                self.logger.error(traceback.format_exc())
+                break
+
+
+class SeleniumTestharnessProtocolPart(TestharnessProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+        self.runner_handle = None
+        with open(os.path.join(here, "runner.js")) as f:
+            self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
+
+    def load_runner(self, url_protocol):
+        if self.runner_handle:
+            self.webdriver.switch_to_window(self.runner_handle)
+        url = urljoin(self.parent.executor.server_url(url_protocol),
+                      "/testharness_runner.html")
+        self.logger.debug("Loading %s" % url)
+        self.webdriver.get(url)
+        self.runner_handle = self.webdriver.current_window_handle
+        format_map = {"title": threading.current_thread().name.replace("'", '"')}
+        self.parent.base.execute_script(self.runner_script % format_map)
+
+    def close_old_windows(self):
+        handles = [item for item in self.webdriver.window_handles if item != self.runner_handle]
+        for handle in handles:
+            try:
+                self.webdriver.switch_to_window(handle)
+                self.webdriver.close()
+            except exceptions.NoSuchWindowException:
+                pass
+        self.webdriver.switch_to_window(self.runner_handle)
+        return self.runner_handle
+
+    def get_test_window(self, window_id, parent, timeout=5):
+        """Find the test window amongst all the open windows.
+        This is assumed to be either the named window or the one after the parent in the list of
+        window handles
+
+        :param window_id: The DOM name of the Window
+        :param parent: The handle of the runner window
+        :param timeout: The time in seconds to wait for the window to appear. This is because in
+                        some implementations there's a race between calling window.open and the
+                        window being added to the list of WebDriver accessible windows."""
+        test_window = None
+        end_time = time.time() + timeout
+        while time.time() < end_time:
+            try:
+                # Try using the JSON serialization of the WindowProxy object,
+                # it's in Level 1 but nothing supports it yet
+                win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
+                win_obj = json.loads(win_s)
+                test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
+            except Exception:
+                pass
+
+            if test_window is None:
+                after = self.webdriver.window_handles
+                if len(after) == 2:
+                    test_window = next(iter(set(after) - {parent}))
+                elif after[0] == parent and len(after) > 2:
+                    # Hope the first one here is the test window
+                    test_window = after[1]
+
+            if test_window is not None:
+                assert test_window != parent
+                return test_window
+
+            time.sleep(0.1)
+
+        raise Exception("unable to find test window")
+
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.webdriver.execute_async_script(self.window_loaded_script)
+                break
+            except exceptions.JavascriptException:
+                pass
+
+
+class SeleniumSelectorProtocolPart(SelectorProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def elements_by_selector(self, selector):
+        return self.webdriver.find_elements_by_css_selector(selector)
+
+    def elements_by_selector_and_frame(self, element_selector, frame):
+        return self.webdriver.find_elements_by_css_selector(element_selector)
+
+
+class SeleniumClickProtocolPart(ClickProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def element(self, element):
+        return element.click()
+
+
+class SeleniumCookiesProtocolPart(CookiesProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def delete_all_cookies(self):
+        self.logger.info("Deleting all cookies")
+        return self.webdriver.delete_all_cookies()
+
+
+class SeleniumSendKeysProtocolPart(SendKeysProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_keys(self, element, keys):
+        return element.send_keys(keys)
+
+
+class SeleniumActionSequenceProtocolPart(ActionSequenceProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_actions(self, actions):
+        self.webdriver.execute(Command.W3C_ACTIONS, {"actions": actions})
+
+
+class SeleniumTestDriverProtocolPart(TestDriverProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_message(self, cmd_id, message_type, status, message=None):
+        obj = {
+            "cmd_id": cmd_id,
+            "type": "testdriver-%s" % str(message_type),
+            "status": str(status)
+        }
+        if message:
+            obj["message"] = str(message)
+        self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
+
+
+class SeleniumProtocol(Protocol):
+    implements = [SeleniumBaseProtocolPart,
+                  SeleniumTestharnessProtocolPart,
+                  SeleniumSelectorProtocolPart,
+                  SeleniumClickProtocolPart,
+                  SeleniumCookiesProtocolPart,
+                  SeleniumSendKeysProtocolPart,
+                  SeleniumTestDriverProtocolPart,
+                  SeleniumActionSequenceProtocolPart]
+
+    def __init__(self, executor, browser, capabilities, **kwargs):
+        do_delayed_imports()
+
+        super(SeleniumProtocol, self).__init__(executor, browser)
+        self.capabilities = capabilities
+        self.url = browser.webdriver_url
+        self.webdriver = None
+
+    def connect(self):
+        """Connect to browser via Selenium's WebDriver implementation."""
+        self.logger.debug("Connecting to Selenium on URL: %s" % self.url)
+
+        self.webdriver = webdriver.Remote(command_executor=RemoteConnection(self.url.strip("/"),
+                                                                            resolve_ip=False),
+                                          desired_capabilities=self.capabilities)
+
+    def teardown(self):
+        self.logger.debug("Hanging up on Selenium session")
+        try:
+            self.webdriver.quit()
+        except Exception:
+            pass
+        del self.webdriver
+
+    def is_alive(self):
+        try:
+            # Get a simple property over the connection
+            self.webdriver.current_window_handle
+        # TODO what exception?
+        except (socket.timeout, exceptions.ErrorInResponseException):
+            return False
+        return True
+
+    def after_connect(self):
+        self.testharness.load_runner(self.executor.last_environment["protocol"])
+
+
+class SeleniumRun(TimedRunner):
+    def set_timeout(self):
+        timeout = self.timeout
+
+        try:
+            self.protocol.base.set_timeout(timeout + self.extra_timeout)
+        except exceptions.ErrorInResponseException:
+            msg = "Lost WebDriver connection"
+            self.logger.error(msg)
+            return ("INTERNAL-ERROR", msg)
+
+    def run_func(self):
+        try:
+            self.result = True, self.func(self.protocol, self.url, self.timeout)
+        except exceptions.TimeoutException:
+            self.result = False, ("EXTERNAL-TIMEOUT", None)
+        except (socket.timeout, exceptions.ErrorInResponseException):
+            self.result = False, ("CRASH", None)
+        except Exception as e:
+            message = str(getattr(e, "message", ""))
+            if message:
+                message += "\n"
+            message += traceback.format_exc()
+            self.result = False, ("INTERNAL-ERROR", message)
+        finally:
+            self.result_flag.set()
+
+
+class SeleniumTestharnessExecutor(TestharnessExecutor):
+    supports_testdriver = True
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 close_after_done=True, capabilities=None, debug_info=None,
+                 supports_eager_pageload=True, **kwargs):
+        """Selenium-based executor for testharness.js tests"""
+        TestharnessExecutor.__init__(self, logger, browser, server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+        self.protocol = SeleniumProtocol(self, browser, capabilities)
+        with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
+            self.script_resume = f.read()
+        self.close_after_done = close_after_done
+        self.window_id = str(uuid.uuid4())
+        self.supports_eager_pageload = supports_eager_pageload
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        if new_environment["protocol"] != self.last_environment["protocol"]:
+            self.protocol.testharness.load_runner(new_environment["protocol"])
+
+    def do_test(self, test):
+        url = self.test_url(test)
+
+        success, data = SeleniumRun(self.logger,
+                                    self.do_testharness,
+                                    self.protocol,
+                                    url,
+                                    test.timeout * self.timeout_multiplier,
+                                    self.extra_timeout).run()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_testharness(self, protocol, url, timeout):
+        format_map = {"url": strip_server(url)}
+
+        parent_window = protocol.testharness.close_old_windows()
+        # Now start the test harness
+        protocol.base.execute_script("window.open('about:blank', '%s', 'noopener')" % self.window_id)
+        test_window = protocol.testharness.get_test_window(self.window_id,
+                                                           parent_window,
+                                                           timeout=5*self.timeout_multiplier)
+        self.protocol.base.set_window(test_window)
+        protocol.testharness.test_window_loaded()
+
+        protocol.base.load(url)
+
+        if not self.supports_eager_pageload:
+            self.wait_for_load(protocol)
+
+        handler = CallbackHandler(self.logger, protocol, test_window)
+        while True:
+            result = protocol.base.execute_script(
+                self.script_resume % format_map, asynchronous=True)
+            done, rv = handler(result)
+            if done:
+                break
+        return rv
+
+    def wait_for_load(self, protocol):
+        # pageLoadStrategy=eager doesn't work in Chrome so try to emulate in user script
+        loaded = False
+        seen_error = False
+        while not loaded:
+            try:
+                loaded = protocol.base.execute_script("""
+var callback = arguments[arguments.length - 1];
+if (location.href === "about:blank") {
+  callback(false);
+} else if (document.readyState !== "loading") {
+  callback(true);
+} else {
+  document.addEventListener("readystatechange", () => {if (document.readyState !== "loading") {callback(true)}});
+}""", asynchronous=True)
+            except Exception:
+                # We can get an error here if the script runs in the initial about:blank
+                # document before it has navigated, with the driver returning an error
+                # indicating that the document was unloaded
+                if seen_error:
+                    raise
+                seen_error = True
+
+
+class SeleniumRefTestExecutor(RefTestExecutor):
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, close_after_done=True,
+                 debug_info=None, capabilities=None, **kwargs):
+        """Selenium WebDriver-based executor for reftests"""
+        RefTestExecutor.__init__(self,
+                                 logger,
+                                 browser,
+                                 server_config,
+                                 screenshot_cache=screenshot_cache,
+                                 timeout_multiplier=timeout_multiplier,
+                                 debug_info=debug_info)
+        self.protocol = SeleniumProtocol(self, browser,
+                                         capabilities=capabilities)
+        self.implementation = RefTestImplementation(self)
+        self.close_after_done = close_after_done
+        self.has_window = False
+
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "reftest-wait"}
+
+    def reset(self):
+        self.implementation.reset()
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def do_test(self, test):
+        self.logger.info("Test requires OS-level window focus")
+
+        width_offset, height_offset = self.protocol.webdriver.execute_script(
+            """return [window.outerWidth - window.innerWidth,
+                       window.outerHeight - window.innerHeight];"""
+        )
+        self.protocol.webdriver.set_window_position(0, 0)
+        self.protocol.webdriver.set_window_size(800 + width_offset, 600 + height_offset)
+
+        result = self.implementation.run_test(test)
+
+        return self.convert_result(test, result)
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7135
+        assert viewport_size is None
+        assert dpi is None
+
+        return SeleniumRun(self.logger,
+                           self._screenshot,
+                           self.protocol,
+                           self.test_url(test),
+                           test.timeout,
+                           self.extra_timeout).run()
+
+    def _screenshot(self, protocol, url, timeout):
+        webdriver = protocol.webdriver
+        webdriver.get(url)
+
+        webdriver.execute_async_script(self.wait_script)
+
+        screenshot = webdriver.get_screenshot_as_base64()
+
+        # strip off the data:img/png, part of the url
+        if screenshot.startswith("data:image/png;base64,"):
+            screenshot = screenshot.split(",", 1)[1]
+
+        return screenshot
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservo.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
new file mode 100644
index 0000000..efe93ab
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservo.py
@@ -0,0 +1,371 @@
+from __future__ import print_function
+import base64
+import json
+import os
+import subprocess
+import tempfile
+import threading
+import traceback
+import uuid
+from six import ensure_str, iteritems
+
+from mozprocess import ProcessHandler
+
+from tools.serve.serve import make_hosts_file
+
+from .base import (ConnectionlessProtocol,
+                   RefTestImplementation,
+                   crashtest_result_converter,
+                   testharness_result_converter,
+                   reftest_result_converter,
+                   TimedRunner,
+                   WdspecExecutor,
+                   WdspecProtocol)
+from .process import ProcessTestExecutor
+from ..browsers.base import browser_command
+from ..process import cast_env
+from ..webdriver_server import ServoDriverServer
+
+
+pytestrunner = None
+webdriver = None
+
+
+def write_hosts_file(config):
+    hosts_fd, hosts_path = tempfile.mkstemp()
+    with os.fdopen(hosts_fd, "w") as f:
+        f.write(make_hosts_file(config, "127.0.0.1"))
+    return hosts_path
+
+
+def build_servo_command(test, test_url_func, browser, binary, pause_after_test, debug_info,
+                        extra_args=None, debug_opts="replace-surrogates"):
+    args = [
+        "--hard-fail", "-u", "Servo/wptrunner",
+        "-z", test_url_func(test),
+    ]
+    if debug_opts:
+        args += ["-Z", debug_opts]
+    for stylesheet in browser.user_stylesheets:
+        args += ["--user-stylesheet", stylesheet]
+    for pref, value in iteritems(test.environment.get('prefs', {})):
+        args += ["--pref", "%s=%s" % (pref, value)]
+    if browser.ca_certificate_path:
+        args += ["--certificate-path", browser.ca_certificate_path]
+    if extra_args:
+        args += extra_args
+    args += browser.binary_args
+    debug_args, command = browser_command(binary, args, debug_info)
+    if pause_after_test:
+        command.remove("-z")
+    return debug_args + command
+
+
+
+class ServoTestharnessExecutor(ProcessTestExecutor):
+    convert_result = testharness_result_converter
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1, debug_info=None,
+                 pause_after_test=False, **kwargs):
+        ProcessTestExecutor.__init__(self, logger, browser, server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+        self.pause_after_test = pause_after_test
+        self.result_data = None
+        self.result_flag = None
+        self.protocol = ConnectionlessProtocol(self, browser)
+        self.hosts_path = write_hosts_file(server_config)
+
+    def teardown(self):
+        try:
+            os.unlink(self.hosts_path)
+        except OSError:
+            pass
+        ProcessTestExecutor.teardown(self)
+
+    def do_test(self, test):
+        self.result_data = None
+        self.result_flag = threading.Event()
+
+        self.command = build_servo_command(test,
+                                           self.test_url,
+                                           self.browser,
+                                           self.binary,
+                                           self.pause_after_test,
+                                           self.debug_info)
+
+        env = os.environ.copy()
+        env["HOST_FILE"] = self.hosts_path
+        env["RUST_BACKTRACE"] = "1"
+
+
+        if not self.interactive:
+            self.proc = ProcessHandler(self.command,
+                                       processOutputLine=[self.on_output],
+                                       onFinish=self.on_finish,
+                                       env=cast_env(env),
+                                       storeOutput=False)
+            self.proc.run()
+        else:
+            self.proc = subprocess.Popen(self.command, env=cast_env(env))
+
+        try:
+            timeout = test.timeout * self.timeout_multiplier
+
+            # Now wait to get the output we expect, or until we reach the timeout
+            if not self.interactive and not self.pause_after_test:
+                wait_timeout = timeout + 5
+                self.result_flag.wait(wait_timeout)
+            else:
+                wait_timeout = None
+                self.proc.wait()
+
+            proc_is_running = True
+
+            if self.result_flag.is_set():
+                if self.result_data is not None:
+                    result = self.convert_result(test, self.result_data)
+                else:
+                    self.proc.wait()
+                    result = (test.result_cls("CRASH", None), [])
+                    proc_is_running = False
+            else:
+                result = (test.result_cls("TIMEOUT", None), [])
+
+
+            if proc_is_running:
+                if self.pause_after_test:
+                    self.logger.info("Pausing until the browser exits")
+                    self.proc.wait()
+                else:
+                    self.proc.kill()
+        except:  # noqa
+            self.proc.kill()
+            raise
+
+        return result
+
+    def on_output(self, line):
+        prefix = "ALERT: RESULT: "
+        line = line.decode("utf8", "replace")
+        if line.startswith(prefix):
+            self.result_data = json.loads(line[len(prefix):])
+            self.result_flag.set()
+        else:
+            if self.interactive:
+                print(line)
+            else:
+                self.logger.process_output(self.proc.pid,
+                                           line,
+                                           " ".join(self.command))
+
+    def on_finish(self):
+        self.result_flag.set()
+
+
+class TempFilename(object):
+    def __init__(self, directory):
+        self.directory = directory
+        self.path = None
+
+    def __enter__(self):
+        self.path = os.path.join(self.directory, str(uuid.uuid4()))
+        return self.path
+
+    def __exit__(self, *args, **kwargs):
+        try:
+            os.unlink(self.path)
+        except OSError:
+            pass
+
+
+class ServoRefTestExecutor(ProcessTestExecutor):
+    convert_result = reftest_result_converter
+
+    def __init__(self, logger, browser, server_config, binary=None, timeout_multiplier=1,
+                 screenshot_cache=None, debug_info=None, pause_after_test=False,
+                 **kwargs):
+        ProcessTestExecutor.__init__(self,
+                                     logger,
+                                     browser,
+                                     server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+
+        self.protocol = ConnectionlessProtocol(self, browser)
+        self.screenshot_cache = screenshot_cache
+        self.implementation = RefTestImplementation(self)
+        self.tempdir = tempfile.mkdtemp()
+        self.hosts_path = write_hosts_file(server_config)
+
+    def reset(self):
+        self.implementation.reset()
+
+    def teardown(self):
+        try:
+            os.unlink(self.hosts_path)
+        except OSError:
+            pass
+        os.rmdir(self.tempdir)
+        ProcessTestExecutor.teardown(self)
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        with TempFilename(self.tempdir) as output_path:
+            extra_args = ["--exit",
+                          "--output=%s" % output_path,
+                          "--resolution", viewport_size or "800x600"]
+            debug_opts = "disable-text-aa,load-webfonts-synchronously,replace-surrogates"
+
+            if dpi:
+                extra_args += ["--device-pixel-ratio", dpi]
+
+            self.command = build_servo_command(test,
+                                               self.test_url,
+                                               self.browser,
+                                               self.binary,
+                                               False,
+                                               self.debug_info,
+                                               extra_args,
+                                               debug_opts)
+
+            env = os.environ.copy()
+            env["HOST_FILE"] = self.hosts_path
+            env["RUST_BACKTRACE"] = "1"
+
+            if not self.interactive:
+                self.proc = ProcessHandler(self.command,
+                                           processOutputLine=[self.on_output],
+                                           env=cast_env(env))
+
+
+                try:
+                    self.proc.run()
+                    timeout = test.timeout * self.timeout_multiplier + 5
+                    rv = self.proc.wait(timeout=timeout)
+                except KeyboardInterrupt:
+                    self.proc.kill()
+                    raise
+            else:
+                self.proc = subprocess.Popen(self.command,
+                                             env=cast_env(env))
+                try:
+                    rv = self.proc.wait()
+                except KeyboardInterrupt:
+                    self.proc.kill()
+                    raise
+
+            if rv is None:
+                self.proc.kill()
+                return False, ("EXTERNAL-TIMEOUT", None)
+
+            if rv != 0 or not os.path.exists(output_path):
+                return False, ("CRASH", None)
+
+            with open(output_path, "rb") as f:
+                # Might need to strip variable headers or something here
+                data = f.read()
+                return True, [ensure_str(base64.b64encode(data))]
+
+    def do_test(self, test):
+        result = self.implementation.run_test(test)
+
+        return self.convert_result(test, result)
+
+    def on_output(self, line):
+        line = line.decode("utf8", "replace")
+        if self.interactive:
+            print(line)
+        else:
+            self.logger.process_output(self.proc.pid,
+                                       line,
+                                       " ".join(self.command))
+
+
+class ServoDriverProtocol(WdspecProtocol):
+    server_cls = ServoDriverServer
+
+
+class ServoWdspecExecutor(WdspecExecutor):
+    protocol_cls = ServoDriverProtocol
+
+
+class ServoTimedRunner(TimedRunner):
+    def run_func(self):
+        try:
+            self.result = True, self.func(self.protocol, self.url, self.timeout)
+        except Exception as e:
+            message = getattr(e, "message", "")
+            if message:
+                message += "\n"
+            message += traceback.format_exc(e)
+            self.result = False, ("INTERNAL-ERROR", message)
+        finally:
+            self.result_flag.set()
+
+    def set_timeout(self):
+        pass
+
+
+class ServoCrashtestExecutor(ProcessTestExecutor):
+    convert_result = crashtest_result_converter
+
+    def __init__(self, logger, browser, server_config, binary=None, timeout_multiplier=1,
+                 screenshot_cache=None, debug_info=None, pause_after_test=False,
+                 **kwargs):
+        ProcessTestExecutor.__init__(self,
+                                     logger,
+                                     browser,
+                                     server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+
+        self.pause_after_test = pause_after_test
+        self.protocol = ConnectionlessProtocol(self, browser)
+        self.tempdir = tempfile.mkdtemp()
+        self.hosts_path = write_hosts_file(server_config)
+
+    def do_test(self, test):
+        timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
+                   else None)
+
+        test_url = self.test_url(test)
+        # We want to pass the full test object into build_servo_command,
+        # so stash it in the class
+        self.test = test
+        success, data = ServoTimedRunner(self.logger, self.do_crashtest, self.protocol,
+                                         test_url, timeout, self.extra_timeout).run()
+        # Ensure that no processes hang around if they timeout.
+        self.proc.kill()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_crashtest(self, protocol, url, timeout):
+        env = os.environ.copy()
+        env["HOST_FILE"] = self.hosts_path
+        env["RUST_BACKTRACE"] = "1"
+
+        command = build_servo_command(self.test,
+                                      self.test_url,
+                                      self.browser,
+                                      self.binary,
+                                      False,
+                                      self.debug_info,
+                                      extra_args=["-x"])
+
+        if not self.interactive:
+            self.proc = ProcessHandler(command,
+                                       env=cast_env(env),
+                                       storeOutput=False)
+            self.proc.run()
+        else:
+            self.proc = subprocess.Popen(command, env=cast_env(env))
+
+        self.proc.wait()
+
+        if self.proc.poll() >= 0:
+            return {"status": "PASS", "message": None}
+
+        return {"status": "CRASH", "message": None}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py
new file mode 100644
index 0000000..039bcd1
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorservodriver.py
@@ -0,0 +1,299 @@
+import json
+import os
+import socket
+import traceback
+
+from .base import (Protocol,
+                   BaseProtocolPart,
+                   RefTestExecutor,
+                   RefTestImplementation,
+                   TestharnessExecutor,
+                   TimedRunner,
+                   strip_server)
+from ..webdriver_server import wait_for_service
+
+webdriver = None
+ServoCommandExtensions = None
+
+here = os.path.dirname(__file__)
+
+
+def do_delayed_imports():
+    global webdriver
+    import webdriver
+
+    global ServoCommandExtensions
+
+    class ServoCommandExtensions(object):
+        def __init__(self, session):
+            self.session = session
+
+        @webdriver.client.command
+        def get_prefs(self, *prefs):
+            body = {"prefs": list(prefs)}
+            return self.session.send_session_command("POST", "servo/prefs/get", body)
+
+        @webdriver.client.command
+        def set_prefs(self, prefs):
+            body = {"prefs": prefs}
+            return self.session.send_session_command("POST", "servo/prefs/set", body)
+
+        @webdriver.client.command
+        def reset_prefs(self, *prefs):
+            body = {"prefs": list(prefs)}
+            return self.session.send_session_command("POST", "servo/prefs/reset", body)
+
+        def change_prefs(self, old_prefs, new_prefs):
+            # Servo interprets reset with an empty list as reset everything
+            if old_prefs:
+                self.reset_prefs(*old_prefs.keys())
+            self.set_prefs({k: parse_pref_value(v) for k, v in new_prefs.items()})
+
+
+# See parse_pref_from_command_line() in components/config/opts.rs
+def parse_pref_value(value):
+    if value == "true":
+        return True
+    if value == "false":
+        return False
+    try:
+        return float(value)
+    except ValueError:
+        return value
+
+
+class ServoBaseProtocolPart(BaseProtocolPart):
+    def execute_script(self, script, asynchronous=False):
+        pass
+
+    def set_timeout(self, timeout):
+        pass
+
+    def wait(self):
+        pass
+
+    def set_window(self, handle):
+        pass
+
+    def window_handles(self):
+        return []
+
+    def load(self, url):
+        pass
+
+
+class ServoWebDriverProtocol(Protocol):
+    implements = [ServoBaseProtocolPart]
+
+    def __init__(self, executor, browser, capabilities, **kwargs):
+        do_delayed_imports()
+        Protocol.__init__(self, executor, browser)
+        self.capabilities = capabilities
+        self.host = browser.webdriver_host
+        self.port = browser.webdriver_port
+        self.init_timeout = browser.init_timeout
+        self.session = None
+
+    def connect(self):
+        """Connect to browser via WebDriver."""
+        wait_for_service((self.host, self.port), timeout=self.init_timeout)
+
+        self.session = webdriver.Session(self.host, self.port, extension=ServoCommandExtensions)
+        self.session.start()
+
+    def after_connect(self):
+        pass
+
+    def teardown(self):
+        self.logger.debug("Hanging up on WebDriver session")
+        try:
+            self.session.end()
+        except Exception:
+            pass
+
+    def is_alive(self):
+        try:
+            # Get a simple property over the connection
+            self.session.window_handle
+        # TODO what exception?
+        except Exception:
+            return False
+        return True
+
+    def wait(self):
+        while True:
+            try:
+                self.session.execute_async_script("")
+            except webdriver.TimeoutException:
+                pass
+            except (socket.timeout, IOError):
+                break
+            except Exception:
+                self.logger.error(traceback.format_exc())
+                break
+
+
+class ServoWebDriverRun(TimedRunner):
+    def set_timeout(self):
+        pass
+
+    def run_func(self):
+        try:
+            self.result = True, self.func(self.protocol.session, self.url, self.timeout)
+        except webdriver.TimeoutException:
+            self.result = False, ("EXTERNAL-TIMEOUT", None)
+        except (socket.timeout, IOError):
+            self.result = False, ("CRASH", None)
+        except Exception as e:
+            message = getattr(e, "message", "")
+            if message:
+                message += "\n"
+            message += traceback.format_exc()
+            self.result = False, ("INTERNAL-ERROR", e)
+        finally:
+            self.result_flag.set()
+
+
+class ServoWebDriverTestharnessExecutor(TestharnessExecutor):
+    supports_testdriver = True
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 close_after_done=True, capabilities=None, debug_info=None,
+                 **kwargs):
+        TestharnessExecutor.__init__(self, logger, browser, server_config, timeout_multiplier=1,
+                                     debug_info=None)
+        self.protocol = ServoWebDriverProtocol(self, browser, capabilities=capabilities)
+        with open(os.path.join(here, "testharness_servodriver.js")) as f:
+            self.script = f.read()
+        self.timeout = None
+
+    def on_protocol_change(self, new_protocol):
+        pass
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def do_test(self, test):
+        url = self.test_url(test)
+
+        timeout = test.timeout * self.timeout_multiplier + self.extra_timeout
+
+        if timeout != self.timeout:
+            try:
+                self.protocol.session.timeouts.script = timeout
+                self.timeout = timeout
+            except IOError:
+                msg = "Lost WebDriver connection"
+                self.logger.error(msg)
+                return ("INTERNAL-ERROR", msg)
+
+        success, data = ServoWebDriverRun(self.logger,
+                                          self.do_testharness,
+                                          self.protocol,
+                                          url,
+                                          timeout,
+                                          self.extra_timeout).run()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_testharness(self, session, url, timeout):
+        session.url = url
+        result = json.loads(
+            session.execute_async_script(
+                self.script % {"abs_url": url,
+                               "url": strip_server(url),
+                               "timeout_multiplier": self.timeout_multiplier,
+                               "timeout": timeout * 1000}))
+        # Prevent leaking every page in history until Servo develops a more sane
+        # page cache
+        session.back()
+        return result
+
+    def on_environment_change(self, new_environment):
+        self.protocol.session.extension.change_prefs(
+            self.last_environment.get("prefs", {}),
+            new_environment.get("prefs", {})
+        )
+
+
+class TimeoutError(Exception):
+    pass
+
+
+class ServoWebDriverRefTestExecutor(RefTestExecutor):
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, capabilities=None, debug_info=None,
+                 **kwargs):
+        """Selenium WebDriver-based executor for reftests"""
+        RefTestExecutor.__init__(self,
+                                 logger,
+                                 browser,
+                                 server_config,
+                                 screenshot_cache=screenshot_cache,
+                                 timeout_multiplier=timeout_multiplier,
+                                 debug_info=debug_info)
+        self.protocol = ServoWebDriverProtocol(self, browser,
+                                               capabilities=capabilities)
+        self.implementation = RefTestImplementation(self)
+        self.timeout = None
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "reftest-wait"}
+
+    def reset(self):
+        self.implementation.reset()
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def do_test(self, test):
+        try:
+            result = self.implementation.run_test(test)
+            return self.convert_result(test, result)
+        except IOError:
+            return test.result_cls("CRASH", None), []
+        except TimeoutError:
+            return test.result_cls("TIMEOUT", None), []
+        except Exception as e:
+            message = getattr(e, "message", "")
+            if message:
+                message += "\n"
+            message += traceback.format_exc()
+            return test.result_cls("INTERNAL-ERROR", message), []
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7135
+        assert viewport_size is None
+        assert dpi is None
+
+        timeout = (test.timeout * self.timeout_multiplier + self.extra_timeout
+                   if self.debug_info is None else None)
+
+        if self.timeout != timeout:
+            try:
+                self.protocol.session.timeouts.script = timeout
+                self.timeout = timeout
+            except IOError:
+                msg = "Lost webdriver connection"
+                self.logger.error(msg)
+                return ("INTERNAL-ERROR", msg)
+
+        return ServoWebDriverRun(self.logger,
+                                 self._screenshot,
+                                 self.protocol,
+                                 self.test_url(test),
+                                 timeout,
+                                 self.extra_timeout).run()
+
+    def _screenshot(self, session, url, timeout):
+        session.url = url
+        session.execute_async_script(self.wait_script)
+        return session.screenshot()
+
+    def on_environment_change(self, new_environment):
+        self.protocol.session.extension.change_prefs(
+            self.last_environment.get("prefs", {}),
+            new_environment.get("prefs", {})
+        )
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
new file mode 100644
index 0000000..e6c5f9f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebdriver.py
@@ -0,0 +1,620 @@
+from __future__ import absolute_import
+import json
+import os
+import socket
+import threading
+import time
+import traceback
+import uuid
+from six.moves.urllib.parse import urljoin
+
+from .base import (CallbackHandler,
+                   CrashtestExecutor,
+                   RefTestExecutor,
+                   RefTestImplementation,
+                   TestharnessExecutor,
+                   TimedRunner,
+                   strip_server)
+from .protocol import (BaseProtocolPart,
+                       TestharnessProtocolPart,
+                       Protocol,
+                       SelectorProtocolPart,
+                       ClickProtocolPart,
+                       CookiesProtocolPart,
+                       SendKeysProtocolPart,
+                       ActionSequenceProtocolPart,
+                       TestDriverProtocolPart,
+                       GenerateTestReportProtocolPart,
+                       SetPermissionProtocolPart,
+                       VirtualAuthenticatorProtocolPart)
+
+import webdriver as client
+from webdriver import error
+
+here = os.path.dirname(__file__)
+
+
+class WebDriverCallbackHandler(CallbackHandler):
+    unimplemented_exc = (NotImplementedError, client.UnknownCommandException)
+
+
+class WebDriverBaseProtocolPart(BaseProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def execute_script(self, script, asynchronous=False):
+        method = self.webdriver.execute_async_script if asynchronous else self.webdriver.execute_script
+        return method(script)
+
+    def set_timeout(self, timeout):
+        try:
+            self.webdriver.timeouts.script = timeout
+        except client.WebDriverException:
+            # workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=2057
+            body = {"type": "script", "ms": timeout * 1000}
+            self.webdriver.send_session_command("POST", "timeouts", body)
+
+    @property
+    def current_window(self):
+        return self.webdriver.window_handle
+
+    def set_window(self, handle):
+        self.webdriver.window_handle = handle
+
+    def window_handles(self):
+        return self.webdriver.handles
+
+    def load(self, url):
+        self.webdriver.url = url
+
+    def wait(self):
+        while True:
+            try:
+                self.webdriver.execute_async_script("")
+            except (client.TimeoutException,
+                    client.ScriptTimeoutException,
+                    client.JavascriptErrorException):
+                # A JavascriptErrorException will happen when we navigate;
+                # by ignoring it it's possible to reload the test whilst the
+                # harness remains paused
+                pass
+            except (socket.timeout,
+                    client.NoSuchWindowException,
+                    client.UnknownErrorException,
+                    IOError):
+                break
+            except Exception:
+                self.logger.error(traceback.format_exc())
+                break
+
+
+class WebDriverTestharnessProtocolPart(TestharnessProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+        self.runner_handle = None
+        with open(os.path.join(here, "runner.js")) as f:
+            self.runner_script = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
+
+    def load_runner(self, url_protocol):
+        if self.runner_handle:
+            self.webdriver.window_handle = self.runner_handle
+        url = urljoin(self.parent.executor.server_url(url_protocol),
+                      "/testharness_runner.html")
+        self.logger.debug("Loading %s" % url)
+
+        self.webdriver.url = url
+        self.runner_handle = self.webdriver.window_handle
+        format_map = {"title": threading.current_thread().name.replace("'", '"')}
+        self.parent.base.execute_script(self.runner_script % format_map)
+
+    def close_old_windows(self):
+        self.webdriver.actions.release()
+        handles = [item for item in self.webdriver.handles if item != self.runner_handle]
+        for handle in handles:
+            try:
+                self.webdriver.window_handle = handle
+                self.webdriver.window.close()
+            except client.NoSuchWindowException:
+                pass
+        self.webdriver.window_handle = self.runner_handle
+        return self.runner_handle
+
+    def get_test_window(self, window_id, parent, timeout=5):
+        """Find the test window amongst all the open windows.
+        This is assumed to be either the named window or the one after the parent in the list of
+        window handles
+
+        :param window_id: The DOM name of the Window
+        :param parent: The handle of the runner window
+        :param timeout: The time in seconds to wait for the window to appear. This is because in
+                        some implementations there's a race between calling window.open and the
+                        window being added to the list of WebDriver accessible windows."""
+        test_window = None
+        end_time = time.time() + timeout
+        while time.time() < end_time:
+            try:
+                # Try using the JSON serialization of the WindowProxy object,
+                # it's in Level 1 but nothing supports it yet
+                win_s = self.webdriver.execute_script("return window['%s'];" % window_id)
+                win_obj = json.loads(win_s)
+                test_window = win_obj["window-fcc6-11e5-b4f8-330a88ab9d7f"]
+            except Exception:
+                pass
+
+            if test_window is None:
+                after = self.webdriver.handles
+                if len(after) == 2:
+                    test_window = next(iter(set(after) - {parent}))
+                elif after[0] == parent and len(after) > 2:
+                    # Hope the first one here is the test window
+                    test_window = after[1]
+
+            if test_window is not None:
+                assert test_window != parent
+                return test_window
+
+            time.sleep(0.1)
+
+        raise Exception("unable to find test window")
+
+    def test_window_loaded(self):
+        """Wait until the page in the new window has been loaded.
+
+        Hereby ignore Javascript execptions that are thrown when
+        the document has been unloaded due to a process change.
+        """
+        while True:
+            try:
+                self.webdriver.execute_script(self.window_loaded_script, asynchronous=True)
+                break
+            except error.JavascriptErrorException:
+                pass
+
+
+class WebDriverSelectorProtocolPart(SelectorProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def elements_by_selector(self, selector):
+        return self.webdriver.find.css(selector)
+
+
+class WebDriverClickProtocolPart(ClickProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def element(self, element):
+        self.logger.info("click " + repr(element))
+        return element.click()
+
+
+class WebDriverCookiesProtocolPart(CookiesProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def delete_all_cookies(self):
+        self.logger.info("Deleting all cookies")
+        return self.webdriver.send_session_command("DELETE", "cookie")
+
+
+class WebDriverSendKeysProtocolPart(SendKeysProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_keys(self, element, keys):
+        try:
+            return element.send_keys(keys)
+        except client.UnknownErrorException as e:
+            # workaround https://bugs.chromium.org/p/chromedriver/issues/detail?id=1999
+            if (e.http_status != 500 or
+                e.status_code != "unknown error"):
+                raise
+            return element.send_element_command("POST", "value", {"value": list(keys)})
+
+
+class WebDriverActionSequenceProtocolPart(ActionSequenceProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_actions(self, actions):
+        self.webdriver.actions.perform(actions['actions'])
+
+
+class WebDriverTestDriverProtocolPart(TestDriverProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def send_message(self, cmd_id, message_type, status, message=None):
+        obj = {
+            "cmd_id": cmd_id,
+            "type": "testdriver-%s" % str(message_type),
+            "status": str(status)
+        }
+        if message:
+            obj["message"] = str(message)
+        self.webdriver.execute_script("window.postMessage(%s, '*')" % json.dumps(obj))
+
+    def _switch_to_frame(self, frame_number):
+        self.webdriver.switch_frame(frame_number)
+
+    def _switch_to_parent_frame(self):
+        self.webdriver.switch_frame("parent")
+
+
+class WebDriverGenerateTestReportProtocolPart(GenerateTestReportProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def generate_test_report(self, message):
+        json_message = {"message": message}
+        self.webdriver.send_session_command("POST", "reporting/generate_test_report", json_message)
+
+
+class WebDriverSetPermissionProtocolPart(SetPermissionProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def set_permission(self, descriptor, state, one_realm):
+        permission_params_dict = {
+            "descriptor": descriptor,
+            "state": state,
+        }
+        if one_realm is not None:
+            permission_params_dict["oneRealm"] = one_realm
+        self.webdriver.send_session_command("POST", "permissions", permission_params_dict)
+
+
+class WebDriverVirtualAuthenticatorProtocolPart(VirtualAuthenticatorProtocolPart):
+    def setup(self):
+        self.webdriver = self.parent.webdriver
+
+    def add_virtual_authenticator(self, config):
+        return self.webdriver.send_session_command("POST", "webauthn/authenticator", config)
+
+    def remove_virtual_authenticator(self, authenticator_id):
+        return self.webdriver.send_session_command("DELETE", "webauthn/authenticator/%s" % authenticator_id)
+
+    def add_credential(self, authenticator_id, credential):
+        return self.webdriver.send_session_command("POST", "webauthn/authenticator/%s/credential" % authenticator_id, credential)
+
+    def get_credentials(self, authenticator_id):
+        return self.webdriver.send_session_command("GET", "webauthn/authenticator/%s/credentials" % authenticator_id)
+
+    def remove_credential(self, authenticator_id, credential_id):
+        return self.webdriver.send_session_command("DELETE", "webauthn/authenticator/%s/credentials/%s" % (authenticator_id, credential_id))
+
+    def remove_all_credentials(self, authenticator_id):
+        return self.webdriver.send_session_command("DELETE", "webauthn/authenticator/%s/credentials" % authenticator_id)
+
+    def set_user_verified(self, authenticator_id, uv):
+        return self.webdriver.send_session_command("POST", "webauthn/authenticator/%s/uv" % authenticator_id, uv)
+
+
+class WebDriverProtocol(Protocol):
+    implements = [WebDriverBaseProtocolPart,
+                  WebDriverTestharnessProtocolPart,
+                  WebDriverSelectorProtocolPart,
+                  WebDriverClickProtocolPart,
+                  WebDriverCookiesProtocolPart,
+                  WebDriverSendKeysProtocolPart,
+                  WebDriverActionSequenceProtocolPart,
+                  WebDriverTestDriverProtocolPart,
+                  WebDriverGenerateTestReportProtocolPart,
+                  WebDriverSetPermissionProtocolPart,
+                  WebDriverVirtualAuthenticatorProtocolPart]
+
+    def __init__(self, executor, browser, capabilities, **kwargs):
+        super(WebDriverProtocol, self).__init__(executor, browser)
+        self.capabilities = capabilities
+        self.url = browser.webdriver_url
+        self.webdriver = None
+
+    def connect(self):
+        """Connect to browser via WebDriver."""
+        self.logger.debug("Connecting to WebDriver on URL: %s" % self.url)
+
+        host, port = self.url.split(":")[1].strip("/"), self.url.split(':')[-1].strip("/")
+
+        capabilities = {"alwaysMatch": self.capabilities}
+        self.webdriver = client.Session(host, port, capabilities=capabilities)
+        self.webdriver.start()
+
+    def teardown(self):
+        self.logger.debug("Hanging up on WebDriver session")
+        try:
+            self.webdriver.end()
+        except Exception as e:
+            message = str(getattr(e, "message", ""))
+            if message:
+                message += "\n"
+            message += traceback.format_exc()
+            self.logger.debug(message)
+        self.webdriver = None
+
+    def is_alive(self):
+        try:
+            # Get a simple property over the connection, with 2 seconds of timeout
+            # that should be more than enough to check if the WebDriver its
+            # still alive, and allows to complete the check within the testrunner
+            # 5 seconds of extra_timeout we have as maximum to end the test before
+            # the external timeout from testrunner triggers.
+            self.webdriver.send_session_command("GET", "window", timeout=2)
+        except (socket.timeout, client.UnknownErrorException, client.InvalidSessionIdException):
+            return False
+        return True
+
+    def after_connect(self):
+        self.testharness.load_runner(self.executor.last_environment["protocol"])
+
+
+class WebDriverRun(TimedRunner):
+    def set_timeout(self):
+        try:
+            self.protocol.base.set_timeout(self.timeout + self.extra_timeout)
+        except client.UnknownErrorException:
+            msg = "Lost WebDriver connection"
+            self.logger.error(msg)
+            return ("INTERNAL-ERROR", msg)
+
+    def run_func(self):
+        try:
+            self.result = True, self.func(self.protocol, self.url, self.timeout)
+        except (client.TimeoutException, client.ScriptTimeoutException):
+            self.result = False, ("EXTERNAL-TIMEOUT", None)
+        except (socket.timeout, client.UnknownErrorException):
+            self.result = False, ("CRASH", None)
+        except Exception as e:
+            if (isinstance(e, client.WebDriverException) and
+                    e.http_status == 408 and
+                    e.status_code == "asynchronous script timeout"):
+                # workaround for https://bugs.chromium.org/p/chromedriver/issues/detail?id=2001
+                self.result = False, ("EXTERNAL-TIMEOUT", None)
+            else:
+                message = str(getattr(e, "message", ""))
+                if message:
+                    message += "\n"
+                message += traceback.format_exc()
+                self.result = False, ("INTERNAL-ERROR", message)
+        finally:
+            self.result_flag.set()
+
+
+class WebDriverTestharnessExecutor(TestharnessExecutor):
+    supports_testdriver = True
+    protocol_cls = WebDriverProtocol
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 close_after_done=True, capabilities=None, debug_info=None,
+                 supports_eager_pageload=True, cleanup_after_test=True,
+                 **kwargs):
+        """WebDriver-based executor for testharness.js tests"""
+        TestharnessExecutor.__init__(self, logger, browser, server_config,
+                                     timeout_multiplier=timeout_multiplier,
+                                     debug_info=debug_info)
+        self.protocol = self.protocol_cls(self, browser, capabilities)
+        with open(os.path.join(here, "testharness_webdriver_resume.js")) as f:
+            self.script_resume = f.read()
+        with open(os.path.join(here, "window-loaded.js")) as f:
+            self.window_loaded_script = f.read()
+
+        self.close_after_done = close_after_done
+        self.window_id = str(uuid.uuid4())
+        self.supports_eager_pageload = supports_eager_pageload
+        self.cleanup_after_test = cleanup_after_test
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def on_environment_change(self, new_environment):
+        if new_environment["protocol"] != self.last_environment["protocol"]:
+            self.protocol.testharness.load_runner(new_environment["protocol"])
+
+    def do_test(self, test):
+        url = self.test_url(test)
+
+        success, data = WebDriverRun(self.logger,
+                                     self.do_testharness,
+                                     self.protocol,
+                                     url,
+                                     test.timeout * self.timeout_multiplier,
+                                     self.extra_timeout).run()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_testharness(self, protocol, url, timeout):
+        format_map = {"url": strip_server(url)}
+
+        # The previous test may not have closed its old windows (if something
+        # went wrong or if cleanup_after_test was False), so clean up here.
+        parent_window = protocol.testharness.close_old_windows()
+
+        # Now start the test harness
+        protocol.base.execute_script("window.open('about:blank', '%s', 'noopener')" % self.window_id)
+        test_window = protocol.testharness.get_test_window(self.window_id,
+                                                           parent_window,
+                                                           timeout=5*self.timeout_multiplier)
+        self.protocol.base.set_window(test_window)
+
+        # Wait until about:blank has been loaded
+        protocol.base.execute_script(self.window_loaded_script, asynchronous=True)
+
+        handler = WebDriverCallbackHandler(self.logger, protocol, test_window)
+        protocol.webdriver.url = url
+
+        if not self.supports_eager_pageload:
+            self.wait_for_load(protocol)
+
+        while True:
+            result = protocol.base.execute_script(
+                self.script_resume % format_map, asynchronous=True)
+
+            # As of 2019-03-29, WebDriver does not define expected behavior for
+            # cases where the browser crashes during script execution:
+            #
+            # https://github.com/w3c/webdriver/issues/1308
+            if not isinstance(result, list) or len(result) != 2:
+                try:
+                    is_alive = self.is_alive()
+                except client.WebDriverException:
+                    is_alive = False
+
+                if not is_alive:
+                    raise Exception("Browser crashed during script execution.")
+
+            done, rv = handler(result)
+            if done:
+                break
+
+        # Attempt to cleanup any leftover windows, if allowed. This is
+        # preferable as it will blame the correct test if something goes wrong
+        # closing windows, but if the user wants to see the test results we
+        # have to leave the window(s) open.
+        if self.cleanup_after_test:
+            protocol.testharness.close_old_windows()
+
+        return rv
+
+    def wait_for_load(self, protocol):
+        # pageLoadStrategy=eager doesn't work in Chrome so try to emulate in user script
+        loaded = False
+        seen_error = False
+        while not loaded:
+            try:
+                loaded = protocol.base.execute_script("""
+var callback = arguments[arguments.length - 1];
+if (location.href === "about:blank") {
+  callback(false);
+} else if (document.readyState !== "loading") {
+  callback(true);
+} else {
+  document.addEventListener("readystatechange", () => {if (document.readyState !== "loading") {callback(true)}});
+}""", asynchronous=True)
+            except client.JavascriptErrorException:
+                # We can get an error here if the script runs in the initial about:blank
+                # document before it has navigated, with the driver returning an error
+                # indicating that the document was unloaded
+                if seen_error:
+                    raise
+                seen_error = True
+
+
+class WebDriverRefTestExecutor(RefTestExecutor):
+    protocol_cls = WebDriverProtocol
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, close_after_done=True,
+                 debug_info=None, capabilities=None, **kwargs):
+        """WebDriver-based executor for reftests"""
+        RefTestExecutor.__init__(self,
+                                 logger,
+                                 browser,
+                                 server_config,
+                                 screenshot_cache=screenshot_cache,
+                                 timeout_multiplier=timeout_multiplier,
+                                 debug_info=debug_info)
+        self.protocol = self.protocol_cls(self,
+                                          browser,
+                                          capabilities=capabilities)
+        self.implementation = RefTestImplementation(self)
+        self.close_after_done = close_after_done
+        self.has_window = False
+
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "reftest-wait"}
+
+    def reset(self):
+        self.implementation.reset()
+
+    def is_alive(self):
+        return self.protocol.is_alive()
+
+    def do_test(self, test):
+        width_offset, height_offset = self.protocol.webdriver.execute_script(
+            """return [window.outerWidth - window.innerWidth,
+                       window.outerHeight - window.innerHeight];"""
+        )
+        try:
+            self.protocol.webdriver.window.position = (0, 0)
+        except client.InvalidArgumentException:
+            # Safari 12 throws with 0 or 1, treating them as bools; fixed in STP
+            self.protocol.webdriver.window.position = (2, 2)
+        self.protocol.webdriver.window.size = (800 + width_offset, 600 + height_offset)
+
+        result = self.implementation.run_test(test)
+
+        return self.convert_result(test, result)
+
+    def screenshot(self, test, viewport_size, dpi, page_ranges):
+        # https://github.com/web-platform-tests/wpt/issues/7135
+        assert viewport_size is None
+        assert dpi is None
+
+        return WebDriverRun(self.logger,
+                            self._screenshot,
+                            self.protocol,
+                            self.test_url(test),
+                            test.timeout,
+                            self.extra_timeout).run()
+
+    def _screenshot(self, protocol, url, timeout):
+        self.protocol.base.load(url)
+
+        self.protocol.base.execute_script(self.wait_script, True)
+
+        screenshot = self.protocol.webdriver.screenshot()
+
+        # strip off the data:img/png, part of the url
+        if screenshot.startswith("data:image/png;base64,"):
+            screenshot = screenshot.split(",", 1)[1]
+
+        return screenshot
+
+
+class WebDriverCrashtestExecutor(CrashtestExecutor):
+    protocol_cls = WebDriverProtocol
+
+    def __init__(self, logger, browser, server_config, timeout_multiplier=1,
+                 screenshot_cache=None, close_after_done=True,
+                 debug_info=None, capabilities=None, **kwargs):
+        """WebDriver-based executor for reftests"""
+        CrashtestExecutor.__init__(self,
+                                   logger,
+                                   browser,
+                                   server_config,
+                                   screenshot_cache=screenshot_cache,
+                                   timeout_multiplier=timeout_multiplier,
+                                   debug_info=debug_info)
+        self.protocol = self.protocol_cls(self,
+                                          browser,
+                                          capabilities=capabilities)
+
+        with open(os.path.join(here, "test-wait.js")) as f:
+            self.wait_script = f.read() % {"classname": "test-wait"}
+
+    def do_test(self, test):
+        timeout = (test.timeout * self.timeout_multiplier if self.debug_info is None
+                   else None)
+
+        success, data = WebDriverRun(self.logger,
+                                     self.do_crashtest,
+                                     self.protocol,
+                                     self.test_url(test),
+                                     timeout,
+                                     self.extra_timeout).run()
+
+        if success:
+            return self.convert_result(test, data)
+
+        return (test.result_cls(*data), [])
+
+    def do_crashtest(self, protocol, url, timeout):
+        protocol.base.load(url)
+        protocol.base.execute_script(self.wait_script, asynchronous=True)
+
+        return {"status": "PASS",
+                "message": None}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebkit.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebkit.py
new file mode 100644
index 0000000..1a4b4fa
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/executorwebkit.py
@@ -0,0 +1,10 @@
+from ..webdriver_server import WebKitDriverServer
+from .base import WdspecExecutor, WdspecProtocol
+
+
+class WebKitDriverProtocol(WdspecProtocol):
+    server_cls = WebKitDriverServer
+
+
+class WebKitDriverWdspecExecutor(WdspecExecutor):
+    protocol_cls = WebKitDriverProtocol
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/process.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/process.py
new file mode 100644
index 0000000..fb8c17a9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/process.py
@@ -0,0 +1,20 @@
+from .base import TestExecutor
+
+
+class ProcessTestExecutor(TestExecutor):
+    def __init__(self, *args, **kwargs):
+        TestExecutor.__init__(self, *args, **kwargs)
+        self.binary = self.browser.binary
+        self.interactive = (False if self.debug_info is None
+                            else self.debug_info.interactive)
+
+    def setup(self, runner):
+        self.runner = runner
+        self.runner.send_message("init_succeeded")
+        return True
+
+    def is_alive(self):
+        return True
+
+    def do_test(self, test):
+        raise NotImplementedError
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/protocol.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/protocol.py
new file mode 100644
index 0000000..8bdc8b0
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/protocol.py
@@ -0,0 +1,517 @@
+import traceback
+
+from abc import ABCMeta, abstractmethod
+
+
+class Protocol(object):
+    """Backend for a specific browser-control protocol.
+
+    Each Protocol is composed of a set of ProtocolParts that implement
+    the APIs required for specific interactions. This reflects the fact
+    that not all implementaions will support exactly the same feature set.
+    Each ProtocolPart is exposed directly on the protocol through an accessor
+    attribute with a name given by its `name` property.
+
+    :param Executor executor: The Executor instance that's using this Protocol
+    :param Browser browser: The Browser using this protocol"""
+    __metaclass__ = ABCMeta
+
+    implements = []
+
+    def __init__(self, executor, browser):
+        self.executor = executor
+        self.browser = browser
+
+        for cls in self.implements:
+            name = cls.name
+            assert not hasattr(self, name)
+            setattr(self, name, cls(self))
+
+    @property
+    def logger(self):
+        """:returns: Current logger"""
+        return self.executor.logger
+
+    def is_alive(self):
+        """Is the browser connection still active
+
+        :returns: A boolean indicating whether the connection is still active."""
+        return True
+
+    def setup(self, runner):
+        """Handle protocol setup, and send a message to the runner to indicate
+        success or failure."""
+        msg = None
+        try:
+            msg = "Failed to start protocol connection"
+            self.connect()
+
+            msg = None
+
+            for cls in self.implements:
+                getattr(self, cls.name).setup()
+
+            msg = "Post-connection steps failed"
+            self.after_connect()
+        except Exception:
+            if msg is not None:
+                self.logger.warning(msg)
+            self.logger.warning(traceback.format_exc())
+            raise
+
+    @abstractmethod
+    def connect(self):
+        """Make a connection to the remote browser"""
+        pass
+
+    @abstractmethod
+    def after_connect(self):
+        """Run any post-connection steps. This happens after the ProtocolParts are
+        initalized so can depend on a fully-populated object."""
+        pass
+
+    def teardown(self):
+        """Run cleanup steps after the tests are finished."""
+        for cls in self.implements:
+            getattr(self, cls.name).teardown()
+
+
+class ProtocolPart(object):
+    """Base class  for all ProtocolParts.
+
+    :param Protocol parent: The parent protocol"""
+    __metaclass__ = ABCMeta
+
+    name = None
+
+    def __init__(self, parent):
+        self.parent = parent
+
+    @property
+    def logger(self):
+        """:returns: Current logger"""
+        return self.parent.logger
+
+    def setup(self):
+        """Run any setup steps required for the ProtocolPart."""
+        pass
+
+    def teardown(self):
+        """Run any teardown steps required for the ProtocolPart."""
+        pass
+
+
+class BaseProtocolPart(ProtocolPart):
+    """Generic bits of protocol that are required for multiple test types"""
+    __metaclass__ = ABCMeta
+
+    name = "base"
+
+    @abstractmethod
+    def execute_script(self, script, asynchronous=False):
+        """Execute javascript in the current Window.
+
+        :param str script: The js source to execute. This is implicitly wrapped in a function.
+        :param bool asynchronous: Whether the script is asynchronous in the webdriver
+                           sense i.e. whether the return value is the result of
+                           the initial function call or if it waits for some callback.
+        :returns: The result of the script execution.
+        """
+        pass
+
+    @abstractmethod
+    def set_timeout(self, timeout):
+        """Set the timeout for script execution.
+
+        :param timeout: Script timeout in seconds"""
+        pass
+
+    @abstractmethod
+    def wait(self):
+        """Wait indefinitely for the browser to close"""
+        pass
+
+    @property
+    def current_window(self):
+        """Return a handle identifying the current top level browsing context
+
+        :returns: A protocol-specific handle"""
+        pass
+
+    @abstractmethod
+    def set_window(self, handle):
+        """Set the top level browsing context to one specified by a given handle.
+
+        :param handle: A protocol-specific handle identifying a top level browsing
+                       context."""
+        pass
+
+    @abstractmethod
+    def window_handles(self):
+        """Get a list of handles to top-level browsing contexts"""
+        pass
+
+    @abstractmethod
+    def load(self, url):
+        """Load a url in the current browsing context
+
+        :param url: The url to load"""
+        pass
+
+
+class TestharnessProtocolPart(ProtocolPart):
+    """Protocol part required to run testharness tests."""
+    __metaclass__ = ABCMeta
+
+    name = "testharness"
+
+    @abstractmethod
+    def load_runner(self, url_protocol):
+        """Load the initial page used to control the tests.
+
+        :param str url_protocol: "https" or "http" depending on the test metadata.
+        """
+        pass
+
+    @abstractmethod
+    def close_old_windows(self, url_protocol):
+        """Close existing windows except for the initial runner window.
+        After calling this method there must be exactly one open window that
+        contains the initial runner page.
+
+        :param str url_protocol: "https" or "http" depending on the test metadata.
+        """
+        pass
+
+    @abstractmethod
+    def get_test_window(self, window_id, parent):
+        """Get the window handle dorresponding to the window containing the
+        currently active test.
+
+        :param window_id: A string containing the DOM name of the Window that
+        contains the test, or None.
+        :param parent: The handle of the runner window.
+        :returns: A protocol-specific window handle.
+        """
+        pass
+
+    @abstractmethod
+    def test_window_loaded(self):
+        """Wait until the newly opened test window has been loaded."""
+
+
+class PrefsProtocolPart(ProtocolPart):
+    """Protocol part that allows getting and setting browser prefs."""
+    __metaclass__ = ABCMeta
+
+    name = "prefs"
+
+    @abstractmethod
+    def set(self, name, value):
+        """Set the named pref to value.
+
+        :param name: A pref name of browser-specific type
+        :param value: A pref value of browser-specific type"""
+        pass
+
+    @abstractmethod
+    def get(self, name):
+        """Get the current value of a named pref
+
+        :param name: A pref name of browser-specific type
+        :returns: A pref value of browser-specific type"""
+        pass
+
+    @abstractmethod
+    def clear(self, name):
+        """Reset the value of a named pref back to the default.
+
+        :param name: A pref name of browser-specific type"""
+        pass
+
+
+class StorageProtocolPart(ProtocolPart):
+    """Protocol part for manipulating browser storage."""
+    __metaclass__ = ABCMeta
+
+    name = "storage"
+
+    @abstractmethod
+    def clear_origin(self, url):
+        """Clear all the storage for a specified origin.
+
+        :param url: A url belonging to the origin"""
+        pass
+
+
+class SelectorProtocolPart(ProtocolPart):
+    """Protocol part for selecting elements on the page."""
+    __metaclass__ = ABCMeta
+
+    name = "select"
+
+    def element_by_selector(self, element_selector):
+        elements = self.elements_by_selector(element_selector)
+        if len(elements) == 0:
+            raise ValueError("Selector '%s' matches no elements" % (element_selector,))
+        elif len(elements) > 1:
+            raise ValueError("Selector '%s' matches multiple elements" % (element_selector,))
+        return elements[0]
+
+    @abstractmethod
+    def elements_by_selector(self, selector):
+        """Select elements matching a CSS selector
+
+        :param str selector: The CSS selector
+        :returns: A list of protocol-specific handles to elements"""
+        pass
+
+
+class ClickProtocolPart(ProtocolPart):
+    """Protocol part for performing trusted clicks"""
+    __metaclass__ = ABCMeta
+
+    name = "click"
+
+    @abstractmethod
+    def element(self, element):
+        """Perform a trusted click somewhere on a specific element.
+
+        :param element: A protocol-specific handle to an element."""
+        pass
+
+
+class CookiesProtocolPart(ProtocolPart):
+    """Protocol part for managing cookies"""
+    __metaclass__ = ABCMeta
+
+    name = "cookies"
+
+    @abstractmethod
+    def delete_all_cookies(self):
+        """Delete all cookies."""
+        pass
+
+
+class SendKeysProtocolPart(ProtocolPart):
+    """Protocol part for performing trusted clicks"""
+    __metaclass__ = ABCMeta
+
+    name = "send_keys"
+
+    @abstractmethod
+    def send_keys(self, element, keys):
+        """Send keys to a specific element.
+
+        :param element: A protocol-specific handle to an element.
+        :param keys: A protocol-specific handle to a string of input keys."""
+        pass
+
+
+class GenerateTestReportProtocolPart(ProtocolPart):
+    """Protocol part for generating test reports"""
+    __metaclass__ = ABCMeta
+
+    name = "generate_test_report"
+
+    @abstractmethod
+    def generate_test_report(self, message):
+        """Generate a test report.
+
+        :param message: The message to be contained in the report."""
+        pass
+
+
+class SetPermissionProtocolPart(ProtocolPart):
+    """Protocol part for setting permissions"""
+    __metaclass__ = ABCMeta
+
+    name = "set_permission"
+
+    @abstractmethod
+    def set_permission(self, descriptor, state, one_realm=False):
+        """Set permission state.
+
+        :param descriptor: A PermissionDescriptor object.
+        :param state: The state to set the permission to.
+        :param one_realm: Whether to set the permission for only one realm."""
+        pass
+
+
+class ActionSequenceProtocolPart(ProtocolPart):
+    """Protocol part for performing trusted clicks"""
+    __metaclass__ = ABCMeta
+
+    name = "action_sequence"
+
+    @abstractmethod
+    def send_actions(self, actions):
+        """Send a sequence of actions to the window.
+
+        :param actions: A protocol-specific handle to an array of actions."""
+        pass
+
+
+class TestDriverProtocolPart(ProtocolPart):
+    """Protocol part that implements the basic functionality required for
+    all testdriver-based tests."""
+    __metaclass__ = ABCMeta
+
+    name = "testdriver"
+
+    @abstractmethod
+    def send_message(self, cmd_id, message_type, status, message=None):
+        """Send a testdriver message to the browser.
+
+        :param int cmd_id: The id of the command to which we're responding
+        :param str message_type: The kind of the message.
+        :param str status: Either "failure" or "success" depending on whether the
+                           previous command succeeded.
+        :param str message: Additional data to add to the message."""
+        pass
+
+    def switch_to_window(self, wptrunner_id):
+        """Switch to a window given a wptrunner window id
+
+        :param str wptrunner_id: window id"""
+        if wptrunner_id is None:
+            return
+
+        stack = [str(item) for item in self.parent.base.window_handles()]
+        while stack:
+            item = stack.pop()
+            if item is None:
+                self._switch_to_parent_frame()
+                continue
+            elif isinstance(item, str):
+                self.parent.base.set_window(item)
+            else:
+                self._switch_to_frame(item)
+
+            try:
+                handle_window_id = self.parent.base.execute_script("return window.__wptrunner_id")
+                if str(handle_window_id) == wptrunner_id:
+                    return
+            except Exception:
+                pass
+            frame_count = self.parent.base.execute_script("return window.length")
+            # None here makes us switch back to the parent after we've processed all the subframes
+            stack.append(None)
+            if frame_count:
+                stack.extend(reversed(range(0, frame_count)))
+
+        raise Exception("Window with id %s not found" % wptrunner_id)
+
+    @abstractmethod
+    def _switch_to_frame(self, index):
+        """Switch to a frame in the current window
+
+        :param int index: Frame id"""
+        pass
+
+    @abstractmethod
+    def _switch_to_parent_frame(self):
+        """Switch to the parent of the current frame"""
+        pass
+
+
+class AssertsProtocolPart(ProtocolPart):
+    """ProtocolPart that implements the functionality required to get a count of non-fatal
+    assertions triggered"""
+    __metaclass__ = ABCMeta
+
+    name = "asserts"
+
+    @abstractmethod
+    def get(self):
+        """Get a count of assertions since the last browser start"""
+        pass
+
+
+class CoverageProtocolPart(ProtocolPart):
+    """Protocol part for collecting per-test coverage data."""
+    __metaclass__ = ABCMeta
+
+    name = "coverage"
+
+    @abstractmethod
+    def reset(self):
+        """Reset coverage counters"""
+        pass
+
+    @abstractmethod
+    def dump(self):
+        """Dump coverage counters"""
+        pass
+
+
+class VirtualAuthenticatorProtocolPart(ProtocolPart):
+    """Protocol part for creating and manipulating virtual authenticators"""
+    __metaclass__ = ABCMeta
+
+    name = "virtual_authenticator"
+
+    @abstractmethod
+    def add_virtual_authenticator(self, config):
+        """Add a virtual authenticator
+
+        :param config: The Authenticator Configuration"""
+        pass
+
+    @abstractmethod
+    def remove_virtual_authenticator(self, authenticator_id):
+        """Remove a virtual authenticator
+
+        :param str authenticator_id: The ID of the authenticator to remove"""
+        pass
+
+    @abstractmethod
+    def add_credential(self, authenticator_id, credential):
+        """Inject a credential onto an authenticator
+
+        :param str authenticator_id: The ID of the authenticator to add the credential to
+        :param credential: The credential to inject"""
+        pass
+
+    @abstractmethod
+    def get_credentials(self, authenticator_id):
+        """Get the credentials stored in an authenticator
+
+        :param str authenticator_id: The ID of the authenticator
+        :returns: An array with the credentials stored on the authenticator"""
+        pass
+
+    @abstractmethod
+    def remove_credential(self, authenticator_id, credential_id):
+        """Remove a credential stored in an authenticator
+
+        :param str authenticator_id: The ID of the authenticator
+        :param str credential_id: The ID of the credential"""
+        pass
+
+    @abstractmethod
+    def remove_all_credentials(self, authenticator_id):
+        """Remove all the credentials stored in an authenticator
+
+        :param str authenticator_id: The ID of the authenticator"""
+        pass
+
+    @abstractmethod
+    def set_user_verified(self, authenticator_id, uv):
+        """Sets the user verified flag on an authenticator
+
+        :param str authenticator_id: The ID of the authenticator
+        :param bool uv: the user verified flag"""
+        pass
+
+
+class PrintProtocolPart(ProtocolPart):
+    """Protocol part for rendering to a PDF."""
+    __metaclass__ = ABCMeta
+
+    name = "pdf_print"
+
+    @abstractmethod
+    def render_as_pdf(self, width, height):
+        """Output document as PDF"""
+        pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py
new file mode 100644
index 0000000..1baaf95
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/__init__.py
@@ -0,0 +1 @@
+from .runner import run  # noqa: F401
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
new file mode 100644
index 0000000..113eff99
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/pytestrunner/runner.py
@@ -0,0 +1,155 @@
+"""
+Provides interface to deal with pytest.
+
+Usage::
+
+    session = webdriver.client.Session("127.0.0.1", "4444", "/")
+    harness_result = ("OK", None)
+    subtest_results = pytestrunner.run("/path/to/test", session.url)
+    return (harness_result, subtest_results)
+"""
+
+import errno
+import json
+import os
+import shutil
+import tempfile
+
+
+pytest = None
+
+
+def do_delayed_imports():
+    global pytest
+    import pytest
+
+
+def run(path, server_config, session_config, timeout=0, environ=None):
+    """
+    Run Python test at ``path`` in pytest.  The provided ``session``
+    is exposed as a fixture available in the scope of the test functions.
+
+    :param path: Path to the test file.
+    :param session_config: dictionary of host, port,capabilities parameters
+    to pass through to the webdriver session
+    :param timeout: Duration before interrupting potentially hanging
+        tests.  If 0, there is no timeout.
+
+    :returns: (<harness result>, [<subtest result>, ...]),
+        where <subtest result> is (test id, status, message, stacktrace).
+    """
+    if pytest is None:
+        do_delayed_imports()
+
+    old_environ = os.environ.copy()
+    try:
+        os.environ["WD_HOST"] = session_config["host"]
+        os.environ["WD_PORT"] = str(session_config["port"])
+        os.environ["WD_CAPABILITIES"] = json.dumps(session_config["capabilities"])
+        os.environ["WD_SERVER_CONFIG"] = json.dumps(server_config.as_dict_for_wd_env_variable())
+        if environ:
+            os.environ.update(environ)
+
+        harness = HarnessResultRecorder()
+        subtests = SubtestResultRecorder()
+
+        with TemporaryDirectory() as cache:
+            try:
+                pytest.main(["--strict",  # turn warnings into errors
+                             "-vv",  # show each individual subtest and full failure logs
+                             "--capture", "no",  # enable stdout/stderr from tests
+                             "--basetemp", cache,  # temporary directory
+                             "--showlocals",  # display contents of variables in local scope
+                             "-p", "no:mozlog",  # use the WPT result recorder
+                             "-p", "no:cacheprovider",  # disable state preservation across invocations
+                             "-o=console_output_style=classic",  # disable test progress bar
+                             path],
+                            plugins=[harness, subtests])
+            except Exception as e:
+                harness.outcome = ("INTERNAL-ERROR", str(e))
+
+    finally:
+        os.environ = old_environ
+
+    return (harness.outcome, subtests.results)
+
+
+class HarnessResultRecorder(object):
+    outcomes = {
+        "failed": "ERROR",
+        "passed": "OK",
+        "skipped": "SKIP",
+    }
+
+    def __init__(self):
+        # we are ok unless told otherwise
+        self.outcome = ("OK", None)
+
+    def pytest_collectreport(self, report):
+        harness_result = self.outcomes[report.outcome]
+        self.outcome = (harness_result, None)
+
+
+class SubtestResultRecorder(object):
+    def __init__(self):
+        self.results = []
+
+    def pytest_runtest_logreport(self, report):
+        if report.passed and report.when == "call":
+            self.record_pass(report)
+        elif report.failed:
+            if report.when != "call":
+                self.record_error(report)
+            else:
+                self.record_fail(report)
+        elif report.skipped:
+            self.record_skip(report)
+
+    def record_pass(self, report):
+        self.record(report.nodeid, "PASS")
+
+    def record_fail(self, report):
+        # pytest outputs the stacktrace followed by an error message prefixed
+        # with "E   ", e.g.
+        #
+        #        def test_example():
+        #  >         assert "fuu" in "foobar"
+        #  > E       AssertionError: assert 'fuu' in 'foobar'
+        message = ""
+        for line in report.longreprtext.splitlines():
+            if line.startswith("E   "):
+                message = line[1:].strip()
+                break
+
+        self.record(report.nodeid, "FAIL", message=message, stack=report.longrepr)
+
+    def record_error(self, report):
+        # error in setup/teardown
+        if report.when != "call":
+            message = "%s error" % report.when
+        self.record(report.nodeid, "ERROR", message, report.longrepr)
+
+    def record_skip(self, report):
+        self.record(report.nodeid, "ERROR",
+                    "In-test skip decorators are disallowed, "
+                    "please use WPT metadata to ignore tests.")
+
+    def record(self, test, status, message=None, stack=None):
+        if stack is not None:
+            stack = str(stack)
+        new_result = (test.split("::")[-1], status, message, stack)
+        self.results.append(new_result)
+
+
+class TemporaryDirectory(object):
+    def __enter__(self):
+        self.path = tempfile.mkdtemp(prefix="pytest-")
+        return self.path
+
+    def __exit__(self, *args):
+        try:
+            shutil.rmtree(self.path)
+        except OSError as e:
+            # no such file or directory
+            if e.errno != errno.ENOENT:
+                raise
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/reftest.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/reftest.js
new file mode 100644
index 0000000..1ba98c6
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/reftest.js
@@ -0,0 +1 @@
+var win = window.open("about:blank", "test", "left=0,top=0,width=800,height=600");
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/runner.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/runner.js
new file mode 100644
index 0000000..171e6fe
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/runner.js
@@ -0,0 +1 @@
+document.title = '%(title)s';
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/test-wait.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
new file mode 100644
index 0000000..ad08ad7
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/test-wait.js
@@ -0,0 +1,55 @@
+var callback = arguments[arguments.length - 1];
+var observer = null;
+var root = document.documentElement;
+
+function wait_load() {
+  if (Document.prototype.hasOwnProperty("fonts")) {
+    document.fonts.ready.then(wait_paints);
+  } else {
+    // This might take the screenshot too early, depending on whether the
+    // load event is blocked on fonts being loaded. See:
+    // https://github.com/w3c/csswg-drafts/issues/1088
+    wait_paints();
+  }
+}
+
+
+function wait_paints() {
+  // As of 2017-04-05, the Chromium web browser exhibits a rendering bug
+  // (https://bugs.chromium.org/p/chromium/issues/detail?id=708757) that
+  // produces instability during screen capture. The following use of
+  // `requestAnimationFrame` is intended as a short-term workaround, though
+  // it is not guaranteed to resolve the issue.
+  //
+  // For further detail, see:
+  // https://github.com/jugglinmike/chrome-screenshot-race/issues/1
+
+  requestAnimationFrame(function() {
+    requestAnimationFrame(function() {
+      screenshot_if_ready();
+    });
+  });
+}
+
+function screenshot_if_ready() {
+  if (root &&
+      root.classList.contains("%(classname)s") &&
+      observer === null) {
+    observer = new MutationObserver(wait_paints);
+    observer.observe(root, {attributes: true});
+    var event = new Event("TestRendered", {bubbles: true});
+    root.dispatchEvent(event);
+    return;
+  }
+  if (observer !== null) {
+    observer.disconnect();
+  }
+  callback();
+}
+
+
+if (document.readyState != "complete") {
+  addEventListener('load', wait_load);
+} else {
+  wait_load();
+}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_servodriver.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_servodriver.js
new file mode 100644
index 0000000..d731cc04
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_servodriver.js
@@ -0,0 +1,2 @@
+window.__wd_results_callback__ = arguments[arguments.length - 1];
+window.__wd_results_timer__ = setTimeout(timeout, %(timeout)s);
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
new file mode 100644
index 0000000..36d086c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/testharness_webdriver_resume.js
@@ -0,0 +1,5 @@
+// We have to set the url here to ensure we get the same escaping as in the harness
+// and also to handle the case where the test changes the fragment
+window.__wptrunner_url = "%(url)s";
+window.__wptrunner_testdriver_callback = arguments[arguments.length - 1];
+window.__wptrunner_process_next_event();
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js
new file mode 100644
index 0000000..78d73285a
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/executors/window-loaded.js
@@ -0,0 +1,9 @@
+const [resolve] = arguments;
+
+if (document.readyState != "complete") {
+  window.addEventListener("load", () => {
+    resolve();
+  }, { once: true });
+} else {
+  resolve();
+}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expected.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expected.py
new file mode 100644
index 0000000..f06abb9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expected.py
@@ -0,0 +1,14 @@
+import os
+
+
+def expected_path(metadata_path, test_path):
+    """Path to the expectation data file for a given test path.
+
+    This is defined as metadata_path + relative_test_path + .ini
+
+    :param metadata_path: Path to the root of the metadata directory
+    :param test_path: Relative path to the test file from the test root
+    """
+    args = list(test_path.split("/"))
+    args[-1] += ".ini"
+    return os.path.join(metadata_path, *args)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expectedtree.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expectedtree.py
new file mode 100644
index 0000000..7521f25
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/expectedtree.py
@@ -0,0 +1,132 @@
+from math import log
+from collections import defaultdict
+from six import iteritems, itervalues
+
+class Node(object):
+    def __init__(self, prop, value):
+        self.prop = prop
+        self.value = value
+        self.parent = None
+
+        self.children = set()
+
+        # Populated for leaf nodes
+        self.run_info = set()
+        self.result_values = defaultdict(int)
+
+    def add(self, node):
+        self.children.add(node)
+        node.parent = self
+
+    def __iter__(self):
+        yield self
+        for node in self.children:
+            for item in node:
+                yield item
+
+    def __len__(self):
+        return 1 + sum(len(item) for item in self.children)
+
+
+def entropy(results):
+    """This is basically a measure of the uniformity of the values in results
+    based on the shannon entropy"""
+
+    result_counts = defaultdict(int)
+    total = float(len(results))
+    for values in itervalues(results):
+        # Not sure this is right, possibly want to treat multiple values as
+        # distinct from multiple of the same value?
+        for value in values:
+            result_counts[value] += 1
+
+    entropy_sum = 0
+
+    for count in itervalues(result_counts):
+        prop = float(count) / total
+        entropy_sum -= prop * log(prop, 2)
+
+    return entropy_sum
+
+
+def split_results(prop, results):
+    """Split a dictionary of results into a dictionary of dictionaries where
+    each sub-dictionary has a specific value of the given property"""
+    by_prop = defaultdict(dict)
+    for run_info, value in iteritems(results):
+        by_prop[run_info[prop]][run_info] = value
+
+    return by_prop
+
+
+def build_tree(properties, dependent_props, results, tree=None):
+    """Build a decision tree mapping properties to results
+
+    :param properties: - A list of run_info properties to consider
+                         in the tree
+    :param dependent_props: - A dictionary mapping property name
+                              to properties that should only be considered
+                              after the properties in the key. For example
+                              {"os": ["version"]} means that "version" won't
+                              be used until after os.
+    :param results: Dictionary mapping run_info to set of results
+    :tree: A Node object to use as the root of the (sub)tree"""
+
+    if tree is None:
+        tree = Node(None, None)
+
+    prop_index = {prop: i for i, prop in enumerate(properties)}
+
+    all_results = defaultdict(int)
+    for result_values in itervalues(results):
+        for result_value, count in iteritems(result_values):
+            all_results[result_value] += count
+
+    # If there is only one result we are done
+    if not properties or len(all_results) == 1:
+        for value, count in iteritems(all_results):
+            tree.result_values[value] += count
+        tree.run_info |= set(results.keys())
+        return tree
+
+    results_partitions = []
+    remove_properties = set()
+    for prop in properties:
+        result_sets = split_results(prop, results)
+        if len(result_sets) == 1:
+            # If this property doesn't partition the space then just remove it
+            # from the set to consider
+            remove_properties.add(prop)
+            continue
+        new_entropy = 0.
+        results_sets_entropy = []
+        for prop_value, result_set in iteritems(result_sets):
+            results_sets_entropy.append((entropy(result_set), prop_value, result_set))
+            new_entropy += (float(len(result_set)) / len(results)) * results_sets_entropy[-1][0]
+
+        results_partitions.append((new_entropy,
+                                   prop,
+                                   results_sets_entropy))
+
+    # In the case that no properties partition the space
+    if not results_partitions:
+        for value, count in iteritems(all_results):
+            tree.result_values[value] += count
+        tree.run_info |= set(results.keys())
+        return tree
+
+    # split by the property with the highest entropy
+    results_partitions.sort(key=lambda x: (x[0], prop_index[x[1]]))
+    _, best_prop, sub_results = results_partitions[0]
+
+    # Create a new set of properties that can be used
+    new_props = properties[:prop_index[best_prop]] + properties[prop_index[best_prop] + 1:]
+    new_props.extend(dependent_props.get(best_prop, []))
+    if remove_properties:
+        new_props = [item for item in new_props if item not in remove_properties]
+
+    for _, prop_value, results_sets in sub_results:
+        node = Node(best_prop, prop_value)
+        tree.add(node)
+        build_tree(new_props, dependent_props, results_sets, node)
+    return tree
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/font.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/font.py
new file mode 100644
index 0000000..910358f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/font.py
@@ -0,0 +1,140 @@
+import ctypes
+import os
+import platform
+import plistlib
+
+from shutil import copy2, rmtree
+from subprocess import call, check_output
+
+HERE = os.path.dirname(__file__)
+SYSTEM = platform.system().lower()
+
+
+class FontInstaller(object):
+    def __init__(self, logger, font_dir=None, **fonts):
+        self.logger = logger
+        self.font_dir = font_dir
+        self.installed_fonts = False
+        self.created_dir = False
+        self.fonts = fonts
+
+    def __call__(self, env_options=None, env_config=None):
+        return self
+
+    def __enter__(self):
+        for _, font_path in self.fonts.items():
+            font_name = font_path.split('/')[-1]
+            install = getattr(self, 'install_%s_font' % SYSTEM, None)
+            if not install:
+                self.logger.warning('Font installation not supported on %s' % SYSTEM)
+                return False
+            if install(font_name, font_path):
+                self.installed_fonts = True
+                self.logger.info('Installed font: %s' % font_name)
+            else:
+                self.logger.warning('Unable to install font: %s' % font_name)
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        if not self.installed_fonts:
+            return False
+
+        for _, font_path in self.fonts.items():
+            font_name = font_path.split('/')[-1]
+            remove = getattr(self, 'remove_%s_font' % SYSTEM, None)
+            if not remove:
+                self.logger.warning('Font removal not supported on %s' % SYSTEM)
+                return False
+            if remove(font_name, font_path):
+                self.logger.info('Removed font: %s' % font_name)
+            else:
+                self.logger.warning('Unable to remove font: %s' % font_name)
+
+    def install_linux_font(self, font_name, font_path):
+        if not self.font_dir:
+            self.font_dir = os.path.join(os.path.expanduser('~'), '.fonts')
+        if not os.path.exists(self.font_dir):
+            os.makedirs(self.font_dir)
+            self.created_dir = True
+        if not os.path.exists(os.path.join(self.font_dir, font_name)):
+            copy2(font_path, self.font_dir)
+        try:
+            fc_cache_returncode = call('fc-cache')
+            return not fc_cache_returncode
+        except OSError:  # If fontconfig doesn't exist, return False
+            self.logger.error('fontconfig not available on this Linux system.')
+            return False
+
+    def install_darwin_font(self, font_name, font_path):
+        if not self.font_dir:
+            self.font_dir = os.path.join(os.path.expanduser('~'),
+                                         'Library/Fonts')
+        if not os.path.exists(self.font_dir):
+            os.makedirs(self.font_dir)
+            self.created_dir = True
+        installed_font_path = os.path.join(self.font_dir, font_name)
+        if not os.path.exists(installed_font_path):
+            copy2(font_path, self.font_dir)
+
+        # Per https://github.com/web-platform-tests/results-collection/issues/218
+        # installing Ahem on macOS is flaky, so check if it actually installed
+        fonts = check_output(['/usr/sbin/system_profiler', '-xml', 'SPFontsDataType'])
+        try:
+            # if py3
+            readPlistFromBytes = plistlib.readPlistFromBytes
+        except AttributeError:
+            readPlistFromBytes = plistlib.readPlistFromString
+        fonts = readPlistFromBytes(fonts)
+        assert len(fonts) == 1
+        for font in fonts[0]['_items']:
+            if font['path'] == installed_font_path:
+                return True
+        return False
+
+    def install_windows_font(self, _, font_path):
+        hwnd_broadcast = 0xFFFF
+        wm_fontchange = 0x001D
+
+        gdi32 = ctypes.WinDLL('gdi32')
+        if gdi32.AddFontResourceW(font_path):
+            from ctypes import wintypes
+            wparam = 0
+            lparam = 0
+            SendNotifyMessageW = ctypes.windll.user32.SendNotifyMessageW
+            SendNotifyMessageW.argtypes = [wintypes.HANDLE, wintypes.UINT,
+                                           wintypes.WPARAM, wintypes.LPARAM]
+            return bool(SendNotifyMessageW(hwnd_broadcast, wm_fontchange,
+                                           wparam, lparam))
+
+    def remove_linux_font(self, font_name, _):
+        if self.created_dir:
+            rmtree(self.font_dir)
+        else:
+            os.remove('%s/%s' % (self.font_dir, font_name))
+        try:
+            fc_cache_returncode = call('fc-cache')
+            return not fc_cache_returncode
+        except OSError:  # If fontconfig doesn't exist, return False
+            self.logger.error('fontconfig not available on this Linux system.')
+            return False
+
+    def remove_darwin_font(self, font_name, _):
+        if self.created_dir:
+            rmtree(self.font_dir)
+        else:
+            os.remove(os.path.join(self.font_dir, font_name))
+        return True
+
+    def remove_windows_font(self, _, font_path):
+        hwnd_broadcast = 0xFFFF
+        wm_fontchange = 0x001D
+
+        gdi32 = ctypes.WinDLL('gdi32')
+        if gdi32.RemoveFontResourceW(font_path):
+            from ctypes import wintypes
+            wparam = 0
+            lparam = 0
+            SendNotifyMessageW = ctypes.windll.user32.SendNotifyMessageW
+            SendNotifyMessageW.argtypes = [wintypes.HANDLE, wintypes.UINT,
+                                           wintypes.WPARAM, wintypes.LPARAM]
+            return bool(SendNotifyMessageW(hwnd_broadcast, wm_fontchange,
+                                           wparam, lparam))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/__init__.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/chromium.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
new file mode 100644
index 0000000..2ff2bd1
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/chromium.py
@@ -0,0 +1,276 @@
+import json
+import time
+import six
+
+from collections import defaultdict
+from mozlog.formatters import base
+
+
+class ChromiumFormatter(base.BaseFormatter):
+    """Formatter to produce results matching the Chromium JSON Test Results format.
+    https://chromium.googlesource.com/chromium/src/+/master/docs/testing/json_test_results_format.md
+
+    Notably, each test has an "artifacts" field that is a dict consisting of
+        "log": a list of strings (one per subtest + one for harness status, see
+            _append_test_message for the format)
+        "screenshots": a list of strings in the format of "url: base64"
+
+    """
+
+    def __init__(self):
+        # Whether the run was interrupted, either by the test runner or user.
+        self.interrupted = False
+
+        # A map of test status to the number of tests that had that status.
+        self.num_failures_by_status = defaultdict(int)
+
+        # Start time, expressed as offset since UNIX epoch in seconds.
+        self.start_timestamp_seconds = None
+
+        # Trie of test results. Each directory in the test name is a node in
+        # the trie and the leaf contains the dict of per-test data.
+        self.tests = {}
+
+        # Two dictionaries keyed by test name. Values are lists of strings:
+        # actual metadata content and other messages, respectively.
+        # See _append_test_message for examples.
+        self.actual_metadata = defaultdict(list)
+        self.messages = defaultdict(list)
+
+        # List of tests that have failing subtests.
+        self.tests_with_subtest_fails = set()
+
+        # Browser log for the current test under execution.
+        # These logs are from ChromeDriver's stdout/err, so we cannot say for
+        # sure which test a message is from, but instead we correlate them based
+        # on timing.
+        self.browser_log = []
+
+    def _append_test_message(self, test, subtest, wpt_actual_status, message):
+        r"""
+        Appends the message data for a test or subtest.
+
+        :param str test: the name of the test
+        :param str subtest: the name of the subtest with the message. Will be
+                            None if this is called for a test.
+        :param str wpt_actual_status: the test status as reported by WPT
+        :param str message: the string to append to the message for this test
+
+        Example actual_metadata of a test with a subtest:
+            "[test_name]\n  expected: OK\n"
+            "  [subtest_name]\n    expected: FAIL\n"
+
+        NOTE: throughout this function we output a key called "expected" but
+        fill it in with the actual status. This is by design. The goal of this
+        output is to look exactly like WPT's expectation metadata so that it
+        can be easily diff-ed.
+
+        Messages are appended verbatim to self.messages[test].
+        """
+        if subtest:
+            result = "  [%s]\n    expected: %s\n" % (subtest, wpt_actual_status)
+            self.actual_metadata[test].append(result)
+            if message:
+                self.messages[test].append("%s: %s\n" % (subtest, message))
+        else:
+            # No subtest, so this is the top-level test. The result must be
+            # prepended to the list, so that it comes before any subtest.
+            test_name_last_part = test.split("/")[-1]
+            result = "[%s]\n  expected: %s\n" % (test_name_last_part, wpt_actual_status)
+            self.actual_metadata[test].insert(0, result)
+            if message:
+                self.messages[test].insert(0, "Harness: %s\n" % message)
+
+    def _append_artifact(self, cur_dict, artifact_name, artifact_value):
+        """
+        Appends artifacts to the specified dictionary.
+        :param dict cur_dict: the test leaf dictionary to append to
+        :param str artifact_name: the name of the artifact
+        :param str artifact_value: the value of the artifact
+        """
+        assert isinstance(artifact_value, six.string_types), "artifact_value must be a str"
+        if "artifacts" not in cur_dict.keys():
+            cur_dict["artifacts"] = defaultdict(list)
+        cur_dict["artifacts"][artifact_name].append(artifact_value)
+
+    def _store_test_result(self, name, actual, expected, actual_metadata,
+                           messages, wpt_actual, subtest_failure,
+                           reftest_screenshots=None):
+        """
+        Stores the result of a single test in |self.tests|
+
+        :param str name: name of the test.
+        :param str actual: actual status of the test.
+        :param str expected: expected statuses of the test.
+        :param list actual_metadata: a list of metadata items.
+        :param list messages: a list of test messages.
+        :param str wpt_actual: actual status reported by wpt, may differ from |actual|.
+        :param bool subtest_failure: whether this test failed because of subtests.
+        :param Optional[list] reftest_screenshots: see executors/base.py for definition.
+        """
+        # The test name can contain a leading / which will produce an empty
+        # string in the first position of the list returned by split. We use
+        # filter(None) to remove such entries.
+        name_parts = filter(None, name.split("/"))
+        cur_dict = self.tests
+        for name_part in name_parts:
+            cur_dict = cur_dict.setdefault(name_part, {})
+        cur_dict["actual"] = actual
+        cur_dict["expected"] = expected
+        if subtest_failure:
+            self._append_artifact(cur_dict, "wpt_subtest_failure", "true")
+        if wpt_actual != actual:
+            self._append_artifact(cur_dict, "wpt_actual_status", wpt_actual)
+        if wpt_actual == 'CRASH':
+            for line in self.browser_log:
+                self._append_artifact(cur_dict, "wpt_crash_log", line)
+        for metadata in actual_metadata:
+            self._append_artifact(cur_dict, "wpt_actual_metadata", metadata)
+        for message in messages:
+            self._append_artifact(cur_dict, "wpt_log", message)
+
+        # Store screenshots (if any).
+        for item in reftest_screenshots or []:
+            if not isinstance(item, dict):
+                # Skip the relation string.
+                continue
+            data = "%s: %s" % (item["url"], item["screenshot"])
+            self._append_artifact(cur_dict, "screenshots", data)
+
+        # Figure out if there was a regression or unexpected status. This only
+        # happens for tests that were run
+        if actual != "SKIP":
+            if actual not in expected:
+                cur_dict["is_unexpected"] = True
+                if actual != "PASS":
+                    cur_dict["is_regression"] = True
+
+    def _map_status_name(self, status):
+        """
+        Maps a WPT status to a Chromium status.
+
+        Chromium has five main statuses that we have to map to:
+        CRASH: the test harness crashed
+        FAIL: the test did not run as expected
+        PASS: the test ran as expected
+        SKIP: the test was not run
+        TIMEOUT: the did not finish in time and was aborted
+
+        :param str status: the string status of a test from WPT
+        :return: a corresponding string status for Chromium
+        """
+        if status == "OK":
+            return "PASS"
+        if status == "NOTRUN":
+            return "SKIP"
+        if status == "EXTERNAL-TIMEOUT":
+            return "TIMEOUT"
+        if status in ("ERROR", "PRECONDITION_FAILED"):
+            return "FAIL"
+        if status == "INTERNAL-ERROR":
+            return "CRASH"
+        # Any other status just gets returned as-is.
+        return status
+
+    def _get_expected_status_from_data(self, actual_status, data):
+        """
+        Gets the expected statuses from a |data| dictionary.
+
+        If there is no expected status in data, the actual status is returned.
+        This is because mozlog will delete "expected" from |data| if it is the
+        same as "status". So the presence of "expected" implies that "status" is
+        unexpected. Conversely, the absence of "expected" implies the "status"
+        is expected. So we use the "expected" status if it's there or fall back
+        to the actual status if it's not.
+
+        If the test has multiple statuses, it will have other statuses listed as
+        "known_intermittent" in |data|. If these exist, they will be added to
+        the returned status with spaced in between.
+
+        :param str actual_status: the actual status of the test
+        :param data: a data dictionary to extract expected status from
+        :return str: the expected statuses as a string
+        """
+        expected_statuses = self._map_status_name(data["expected"]) if "expected" in data else actual_status
+        if data.get("known_intermittent"):
+            all_statsues = {self._map_status_name(other_status) for other_status in data["known_intermittent"]}
+            all_statsues.add(expected_statuses)
+            expected_statuses = " ".join(sorted(all_statsues))
+        return expected_statuses
+
+    def suite_start(self, data):
+        # |data| contains a timestamp in microseconds, while time.time() gives
+        # it in seconds.
+        self.start_timestamp_seconds = (float(data["time"]) / 1000 if "time" in data
+                                        else time.time())
+
+    def test_status(self, data):
+        test_name = data["test"]
+        wpt_actual_status = data["status"]
+        actual_status = self._map_status_name(wpt_actual_status)
+        expected_statuses = self._get_expected_status_from_data(actual_status, data)
+
+        is_unexpected = actual_status not in expected_statuses
+        if is_unexpected and test_name not in self.tests_with_subtest_fails:
+            self.tests_with_subtest_fails.add(test_name)
+        # We should always get a subtest in the data dict, but it's technically
+        # possible that it's missing. Be resilient here.
+        subtest_name = data.get("subtest", "UNKNOWN SUBTEST")
+        self._append_test_message(test_name, subtest_name,
+                                  wpt_actual_status, data.get("message", ""))
+
+    def test_end(self, data):
+        test_name = data["test"]
+        # Save the status reported by WPT since we might change it when
+        # reporting to Chromium.
+        wpt_actual_status = data["status"]
+        actual_status = self._map_status_name(wpt_actual_status)
+        expected_statuses = self._get_expected_status_from_data(actual_status, data)
+        subtest_failure = False
+        if test_name in self.tests_with_subtest_fails:
+            subtest_failure = True
+            # Clean up the test list to avoid accumulating too many.
+            self.tests_with_subtest_fails.remove(test_name)
+            # This test passed but it has failing subtests. Since we can only
+            # report a single status to Chromium, we choose FAIL to indicate
+            # that something about this test did not run correctly.
+            if actual_status == "PASS":
+                actual_status = "FAIL"
+
+        self._append_test_message(test_name, None, wpt_actual_status,
+                                  data.get("message", ""))
+        self._store_test_result(test_name,
+                                actual_status,
+                                expected_statuses,
+                                self.actual_metadata[test_name],
+                                self.messages[test_name],
+                                wpt_actual_status,
+                                subtest_failure,
+                                data.get("extra", {}).get("reftest_screenshots"))
+
+        # Remove the test from dicts to avoid accumulating too many.
+        self.actual_metadata.pop(test_name)
+        self.messages.pop(test_name)
+
+        # Update the count of how many tests ran with each status.
+        self.num_failures_by_status[actual_status] += 1
+
+        # New test, new browser logs.
+        self.browser_log = []
+
+    def suite_end(self, data):
+        # Create the final result dictionary
+        final_result = {
+            # There are some required fields that we just hard-code.
+            "interrupted": False,
+            "path_delimiter": "/",
+            "version": 3,
+            "seconds_since_epoch": self.start_timestamp_seconds,
+            "num_failures_by_type": self.num_failures_by_status,
+            "tests": self.tests
+        }
+        return json.dumps(final_result)
+
+    def process_output(self, data):
+        if 'command' in data and 'chromedriver' in data['command']:
+            self.browser_log.append(data['data'])
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
new file mode 100644
index 0000000..55a12b1
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/tests/test_chromium.py
@@ -0,0 +1,678 @@
+import json
+import sys
+from os.path import dirname, join
+from six.moves import cStringIO as StringIO
+
+from mozlog import handlers, structuredlog
+
+sys.path.insert(0, join(dirname(__file__), "..", ".."))
+from formatters.chromium import ChromiumFormatter
+
+
+def test_chromium_required_fields(capfd):
+    # Test that the test results contain a handful of required fields.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # output a bunch of stuff
+    logger.suite_start(["test-id-1"], run_info={}, time=123)
+    logger.test_start("test-id-1")
+    logger.test_end("test-id-1", status="PASS", expected="PASS")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_obj = json.load(output)
+
+    # Check for existence of required fields
+    assert "interrupted" in output_obj
+    assert "path_delimiter" in output_obj
+    assert "version" in output_obj
+    assert "num_failures_by_type" in output_obj
+    assert "tests" in output_obj
+
+    test_obj = output_obj["tests"]["test-id-1"]
+    assert "actual" in test_obj
+    assert "expected" in test_obj
+
+
+def test_chromium_test_name_trie(capfd):
+    # Ensure test names are broken into directories and stored in a trie with
+    # test results at the leaves.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # output a bunch of stuff
+    logger.suite_start(["/foo/bar/test-id-1", "/foo/test-id-2"], run_info={},
+                       time=123)
+    logger.test_start("/foo/bar/test-id-1")
+    logger.test_end("/foo/bar/test-id-1", status="TIMEOUT", expected="FAIL")
+    logger.test_start("/foo/test-id-2")
+    logger.test_end("/foo/test-id-2", status="ERROR", expected="TIMEOUT")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_obj = json.load(output)
+
+    # Ensure that the test names are broken up by directory name and that the
+    # results are stored at the leaves.
+    test_obj = output_obj["tests"]["foo"]["bar"]["test-id-1"]
+    assert test_obj["actual"] == "TIMEOUT"
+    assert test_obj["expected"] == "FAIL"
+
+    test_obj = output_obj["tests"]["foo"]["test-id-2"]
+    # The ERROR status is mapped to FAIL for Chromium
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["expected"] == "TIMEOUT"
+
+
+def test_num_failures_by_type(capfd):
+    # Test that the number of failures by status type is correctly calculated.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run some tests with different statuses: 3 passes, 1 timeout
+    logger.suite_start(["t1", "t2", "t3", "t4"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="PASS", expected="PASS")
+    logger.test_start("t2")
+    logger.test_end("t2", status="PASS", expected="PASS")
+    logger.test_start("t3")
+    logger.test_end("t3", status="PASS", expected="FAIL")
+    logger.test_start("t4")
+    logger.test_end("t4", status="TIMEOUT", expected="CRASH")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    num_failures_by_type = json.load(output)["num_failures_by_type"]
+
+    # We expect 3 passes and 1 timeout, nothing else.
+    assert sorted(num_failures_by_type.keys()) == ["PASS", "TIMEOUT"]
+    assert num_failures_by_type["PASS"] == 3
+    assert num_failures_by_type["TIMEOUT"] == 1
+
+
+def test_subtest_messages(capfd):
+    # Tests accumulation of test output
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run two tests with subtest messages. The subtest name should be included
+    # in the output. We should also tolerate missing messages.
+    logger.suite_start(["t1", "t2"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_status("t1", status="FAIL", subtest="t1_a",
+                       message="t1_a_message")
+    logger.test_status("t1", status="PASS", subtest="t1_b",
+                       message="t1_b_message")
+    logger.test_end("t1", status="PASS", expected="PASS")
+    logger.test_start("t2")
+    # Subtests with empty messages should not be ignored.
+    logger.test_status("t2", status="PASS", subtest="t2_a")
+    # A test-level message will also be appended
+    logger.test_end("t2", status="TIMEOUT", expected="PASS",
+                    message="t2_message")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    t1_artifacts = output_json["tests"]["t1"]["artifacts"]
+    assert t1_artifacts["wpt_actual_metadata"] == [
+        "[t1]\n  expected: PASS\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
+    ]
+    assert t1_artifacts["wpt_subtest_failure"] == ["true"]
+    t2_artifacts = output_json["tests"]["t2"]["artifacts"]
+    assert t2_artifacts["wpt_actual_metadata"] == [
+        "[t2]\n  expected: TIMEOUT\n",
+        "  [t2_a]\n    expected: PASS\n",
+    ]
+    assert t2_artifacts["wpt_log"] == [
+        "Harness: t2_message\n"
+    ]
+    assert "wpt_subtest_failure" not in t2_artifacts.keys()
+
+
+def test_subtest_failure(capfd):
+    # Tests that a test fails if a subtest fails
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    formatter = ChromiumFormatter()
+    logger.add_handler(handlers.StreamHandler(output, formatter))
+
+    # Run a test with some subtest failures.
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_status("t1", status="FAIL", subtest="t1_a",
+                       message="t1_a_message")
+    logger.test_status("t1", status="PASS", subtest="t1_b",
+                       message="t1_b_message")
+    logger.test_status("t1", status="TIMEOUT", subtest="t1_c",
+                       message="t1_c_message")
+
+    # Make sure the test name was added to the set of tests with subtest fails
+    assert "t1" in formatter.tests_with_subtest_fails
+
+    # The test status is reported as a pass here because the harness was able to
+    # run the test to completion.
+    logger.test_end("t1", status="PASS", expected="PASS", message="top_message")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    t1_artifacts = test_obj["artifacts"]
+    assert t1_artifacts["wpt_actual_metadata"] == [
+        "[t1]\n  expected: PASS\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+        "  [t1_c]\n    expected: TIMEOUT\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "Harness: top_message\n",
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
+        "t1_c: t1_c_message\n",
+    ]
+    assert t1_artifacts["wpt_subtest_failure"] == ["true"]
+    # The status of the test in the output is a failure because subtests failed,
+    # despite the harness reporting that the test passed. But the harness status
+    # is logged as an artifact.
+    assert t1_artifacts["wpt_actual_status"] == ["PASS"]
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["expected"] == "PASS"
+    # Also ensure that the formatter cleaned up its internal state
+    assert "t1" not in formatter.tests_with_subtest_fails
+
+
+def test_expected_subtest_failure(capfd):
+    # Tests that an expected subtest failure does not cause the test to fail
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    formatter = ChromiumFormatter()
+    logger.add_handler(handlers.StreamHandler(output, formatter))
+
+    # Run a test with some expected subtest failures.
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_status("t1", status="FAIL", expected="FAIL", subtest="t1_a",
+                       message="t1_a_message")
+    logger.test_status("t1", status="PASS", subtest="t1_b",
+                       message="t1_b_message")
+    logger.test_status("t1", status="TIMEOUT", expected="TIMEOUT", subtest="t1_c",
+                       message="t1_c_message")
+
+    # The subtest failures are all expected so this test should not be added to
+    # the set of tests with subtest failures.
+    assert "t1" not in formatter.tests_with_subtest_fails
+
+    # The test status is reported as a pass here because the harness was able to
+    # run the test to completion.
+    logger.test_end("t1", status="OK", expected="OK")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    assert test_obj["artifacts"]["wpt_actual_metadata"] == [
+        "[t1]\n  expected: OK\n",
+        "  [t1_a]\n    expected: FAIL\n",
+        "  [t1_b]\n    expected: PASS\n",
+        "  [t1_c]\n    expected: TIMEOUT\n",
+    ]
+    assert test_obj["artifacts"]["wpt_log"] == [
+        "t1_a: t1_a_message\n",
+        "t1_b: t1_b_message\n",
+        "t1_c: t1_c_message\n",
+    ]
+    # The status of the test in the output is a pass because the subtest
+    # failures were all expected.
+    assert test_obj["actual"] == "PASS"
+    assert test_obj["expected"] == "PASS"
+
+
+def test_unexpected_subtest_pass(capfd):
+    # A subtest that unexpectedly passes is considered a failure condition.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    formatter = ChromiumFormatter()
+    logger.add_handler(handlers.StreamHandler(output, formatter))
+
+    # Run a test with a subtest that is expected to fail but passes.
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_status("t1", status="PASS", expected="FAIL", subtest="t1_a",
+                       message="t1_a_message")
+
+    # Since the subtest behaviour is unexpected, it's considered a failure, so
+    # the test should be added to the set of tests with subtest failures.
+    assert "t1" in formatter.tests_with_subtest_fails
+
+    # The test status is reported as a pass here because the harness was able to
+    # run the test to completion.
+    logger.test_end("t1", status="PASS", expected="PASS")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    t1_artifacts = test_obj["artifacts"]
+    assert t1_artifacts["wpt_actual_metadata"] == [
+        "[t1]\n  expected: PASS\n",
+        "  [t1_a]\n    expected: PASS\n",
+    ]
+    assert t1_artifacts["wpt_log"] == [
+        "t1_a: t1_a_message\n",
+    ]
+    assert t1_artifacts["wpt_subtest_failure"] == ["true"]
+    # Since the subtest status is unexpected, we fail the test. But we report
+    # wpt_actual_status as an artifact
+    assert t1_artifacts["wpt_actual_status"] == ["PASS"]
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["expected"] == "PASS"
+    # Also ensure that the formatter cleaned up its internal state
+    assert "t1" not in formatter.tests_with_subtest_fails
+
+
+def test_expected_test_fail(capfd):
+    # Check that an expected test-level failure is treated as a Pass
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run some tests with different statuses: 3 passes, 1 timeout
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="ERROR", expected="ERROR")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # The test's actual and expected status should map from "ERROR" to "FAIL"
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["expected"] == "FAIL"
+    # ..and this test should not be a regression nor unexpected
+    assert "is_regression" not in test_obj
+    assert "is_unexpected" not in test_obj
+
+
+def test_unexpected_test_fail(capfd):
+    # Check that an unexpected test-level failure is marked as unexpected and
+    # as a regression.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run some tests with different statuses: 3 passes, 1 timeout
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="ERROR", expected="OK")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # The test's actual and expected status should be mapped, ERROR->FAIL and
+    # OK->PASS
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["expected"] == "PASS"
+    # ..and this test should be a regression and unexpected
+    assert test_obj["is_regression"] is True
+    assert test_obj["is_unexpected"] is True
+
+
+def test_flaky_test_expected(capfd):
+    # Check that a flaky test with multiple possible statuses is seen as
+    # expected if its actual status is one of the possible ones.
+
+    # set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run a test that is known to be flaky
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="ERROR", expected="OK", known_intermittent=["ERROR", "TIMEOUT"])
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # The test's statuses are all mapped, changing ERROR->FAIL and OK->PASS
+    assert test_obj["actual"] == "FAIL"
+    # All the possible statuses are merged and sorted together into expected.
+    assert test_obj["expected"] == "FAIL PASS TIMEOUT"
+    # ...this is not a regression or unexpected because the actual status is one
+    # of the expected ones
+    assert "is_regression" not in test_obj
+    assert "is_unexpected" not in test_obj
+
+
+def test_flaky_test_unexpected(capfd):
+    # Check that a flaky test with multiple possible statuses is seen as
+    # unexpected if its actual status is NOT one of the possible ones.
+
+    # set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run a test that is known to be flaky
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="ERROR", expected="OK", known_intermittent=["TIMEOUT"])
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # The test's statuses are all mapped, changing ERROR->FAIL and OK->PASS
+    assert test_obj["actual"] == "FAIL"
+    # All the possible statuses are merged and sorted together into expected.
+    assert test_obj["expected"] == "PASS TIMEOUT"
+    # ...this is a regression and unexpected because the actual status is not
+    # one of the expected ones
+    assert test_obj["is_regression"] is True
+    assert test_obj["is_unexpected"] is True
+
+
+def test_precondition_failed(capfd):
+    # Check that a failed precondition gets properly handled.
+
+    # set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run a test with a precondition failure
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="PRECONDITION_FAILED", expected="OK")
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # The precondition failure should map to FAIL status, but we should also
+    # have an artifact containing the original PRECONDITION_FAILED status.
+    assert test_obj["actual"] == "FAIL"
+    assert test_obj["artifacts"]["wpt_actual_status"] == ["PRECONDITION_FAILED"]
+    # ...this is an unexpected regression because we expected a pass but failed
+    assert test_obj["is_regression"] is True
+    assert test_obj["is_unexpected"] is True
+
+
+def test_known_intermittent_empty(capfd):
+    # If the known_intermittent list is empty, we want to ensure we don't append
+    # any extraneous characters to the output.
+
+    # set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run a test and include an empty known_intermittent list
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="OK", expected="OK", known_intermittent=[])
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    # Both actual and expected statuses get mapped to Pass. No extra whitespace
+    # anywhere.
+    assert test_obj["actual"] == "PASS"
+    assert test_obj["expected"] == "PASS"
+
+
+def test_known_intermittent_duplicate(capfd):
+    # We don't want to have duplicate statuses in the final "expected" field.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # There are two duplications in this input:
+    # 1. known_intermittent already contains expected;
+    # 2. both statuses in known_intermittent map to FAIL in Chromium.
+    # In the end, we should only get one FAIL in Chromium "expected".
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="ERROR", expected="ERROR", known_intermittent=["FAIL", "ERROR"])
+    logger.suite_end()
+
+    # Check nothing got output to stdout/stderr.
+    # (Note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # Check the actual output of the formatter.
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    assert test_obj["actual"] == "FAIL"
+    # No duplicate "FAIL" in "expected".
+    assert test_obj["expected"] == "FAIL"
+
+
+def test_reftest_screenshots(capfd):
+    # reftest_screenshots, if present, should be plumbed into artifacts.
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    # Run a reftest with reftest_screenshots.
+    logger.suite_start(["t1"], run_info={}, time=123)
+    logger.test_start("t1")
+    logger.test_end("t1", status="FAIL", expected="PASS", extra={
+        "reftest_screenshots": [
+            {"url": "foo.html", "hash": "HASH1", "screenshot": "DATA1"},
+            "!=",
+            {"url": "foo-ref.html", "hash": "HASH2", "screenshot": "DATA2"},
+        ]
+    })
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    assert test_obj["artifacts"]["screenshots"] == [
+        "foo.html: DATA1",
+        "foo-ref.html: DATA2",
+    ]
+
+
+def test_process_output_crashing_test(capfd):
+    """Test that chromedriver logs are preserved for crashing tests"""
+
+    # Set up the handler.
+    output = StringIO()
+    logger = structuredlog.StructuredLogger("test_a")
+    logger.add_handler(handlers.StreamHandler(output, ChromiumFormatter()))
+
+    logger.suite_start(["t1", "t2", "t3"], run_info={}, time=123)
+
+    logger.test_start("t1")
+    logger.process_output(100, "This message should be recorded", "/some/path/to/chromedriver --some-flag")
+    logger.process_output(101, "This message should not be recorded", "/some/other/process --another-flag")
+    logger.process_output(100, "This message should also be recorded", "/some/path/to/chromedriver --some-flag")
+    logger.test_end("t1", status="CRASH", expected="CRASH")
+
+    logger.test_start("t2")
+    logger.process_output(100, "Another message for the second test", "/some/path/to/chromedriver --some-flag")
+    logger.test_end("t2", status="CRASH", expected="PASS")
+
+    logger.test_start("t3")
+    logger.process_output(100, "This test fails", "/some/path/to/chromedriver --some-flag")
+    logger.process_output(100, "But the output should not be captured", "/some/path/to/chromedriver --some-flag")
+    logger.process_output(100, "Because it does not crash", "/some/path/to/chromedriver --some-flag")
+    logger.test_end("t3", status="FAIL", expected="PASS")
+
+    logger.suite_end()
+
+    # check nothing got output to stdout/stderr
+    # (note that mozlog outputs exceptions during handling to stderr!)
+    captured = capfd.readouterr()
+    assert captured.out == ""
+    assert captured.err == ""
+
+    # check the actual output of the formatter
+    output.seek(0)
+    output_json = json.load(output)
+
+    test_obj = output_json["tests"]["t1"]
+    assert test_obj["artifacts"]["wpt_crash_log"] == [
+        "This message should be recorded",
+        "This message should also be recorded"
+    ]
+
+    test_obj = output_json["tests"]["t2"]
+    assert test_obj["artifacts"]["wpt_crash_log"] == [
+        "Another message for the second test"
+    ]
+
+    test_obj = output_json["tests"]["t3"]
+    assert "wpt_crash_log" not in test_obj["artifacts"]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptreport.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptreport.py
new file mode 100644
index 0000000..6d4401a
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptreport.py
@@ -0,0 +1,170 @@
+import json
+import re
+import sys
+
+from mozlog.structured.formatters.base import BaseFormatter
+from ..executors.base import strip_server
+
+
+LONE_SURROGATE_RE = re.compile(u"[\uD800-\uDFFF]")
+
+
+def surrogate_replacement_ucs4(match):
+    return "U+" + hex(ord(match.group()))[2:]
+
+
+class SurrogateReplacementUcs2(object):
+    def __init__(self):
+        self.skip = False
+
+    def __call__(self, match):
+        char = match.group()
+
+        if self.skip:
+            self.skip = False
+            return char
+
+        is_low = 0xD800 <= ord(char) <= 0xDBFF
+
+        escape = True
+        if is_low:
+            next_idx = match.end()
+            if next_idx < len(match.string):
+                next_char = match.string[next_idx]
+                if 0xDC00 <= ord(next_char) <= 0xDFFF:
+                    escape = False
+
+        if not escape:
+            self.skip = True
+            return char
+
+        return "U+" + hex(ord(match.group()))[2:]
+
+
+if sys.maxunicode == 0x10FFFF:
+    surrogate_replacement = surrogate_replacement_ucs4
+else:
+    surrogate_replacement = SurrogateReplacementUcs2()
+
+
+def replace_lone_surrogate(data):
+    return LONE_SURROGATE_RE.subn(surrogate_replacement, data)[0]
+
+
+class WptreportFormatter(BaseFormatter):
+    """Formatter that produces results in the format that wptreport expects."""
+
+    def __init__(self):
+        self.raw_results = {}
+        self.results = {}
+
+    def suite_start(self, data):
+        if 'run_info' in data:
+            self.results['run_info'] = data['run_info']
+        self.results['time_start'] = data['time']
+        self.results["results"] = []
+
+    def suite_end(self, data):
+        self.results['time_end'] = data['time']
+        for test_name in self.raw_results:
+            result = {"test": test_name}
+            result.update(self.raw_results[test_name])
+            self.results["results"].append(result)
+        return json.dumps(self.results) + "\n"
+
+    def find_or_create_test(self, data):
+        test_name = data["test"]
+        if test_name not in self.raw_results:
+            self.raw_results[test_name] = {
+                "subtests": [],
+                "status": "",
+                "message": None
+            }
+        return self.raw_results[test_name]
+
+    def test_start(self, data):
+        test = self.find_or_create_test(data)
+        test["start_time"] = data["time"]
+
+    def create_subtest(self, data):
+        test = self.find_or_create_test(data)
+        subtest_name = replace_lone_surrogate(data["subtest"])
+
+        subtest = {
+            "name": subtest_name,
+            "status": "",
+            "message": None
+        }
+        test["subtests"].append(subtest)
+
+        return subtest
+
+    def test_status(self, data):
+        subtest = self.create_subtest(data)
+        subtest["status"] = data["status"]
+        if "expected" in data:
+            subtest["expected"] = data["expected"]
+        if "known_intermittent" in data:
+            subtest["known_intermittent"] = data["known_intermittent"]
+        if "message" in data:
+            subtest["message"] = replace_lone_surrogate(data["message"])
+
+    def test_end(self, data):
+        test = self.find_or_create_test(data)
+        start_time = test.pop("start_time")
+        test["duration"] = data["time"] - start_time
+        test["status"] = data["status"]
+        if "expected" in data:
+            test["expected"] = data["expected"]
+        if "known_intermittent" in data:
+            test["known_intermittent"] = data["known_intermittent"]
+        if "message" in data:
+            test["message"] = replace_lone_surrogate(data["message"])
+        if "reftest_screenshots" in data.get("extra", {}):
+            test["screenshots"] = {
+                strip_server(item["url"]): "sha1:" + item["hash"]
+                for item in data["extra"]["reftest_screenshots"]
+                if type(item) == dict
+            }
+        test_name = data["test"]
+        result = {"test": data["test"]}
+        result.update(self.raw_results[test_name])
+        self.results["results"].append(result)
+        self.raw_results.pop(test_name)
+
+    def assertion_count(self, data):
+        test = self.find_or_create_test(data)
+        test["asserts"] = {
+            "count": data["count"],
+            "min": data["min_expected"],
+            "max": data["max_expected"]
+        }
+
+    def lsan_leak(self, data):
+        if "lsan_leaks" not in self.results:
+            self.results["lsan_leaks"] = []
+        lsan_leaks = self.results["lsan_leaks"]
+        lsan_leaks.append({"frames": data["frames"],
+                           "scope": data["scope"],
+                           "allowed_match": data.get("allowed_match")})
+
+    def find_or_create_mozleak(self, data):
+        if "mozleak" not in self.results:
+            self.results["mozleak"] = {}
+        scope = data["scope"]
+        if scope not in self.results["mozleak"]:
+            self.results["mozleak"][scope] = {"objects": [], "total": []}
+        return self.results["mozleak"][scope]
+
+    def mozleak_object(self, data):
+        scope_data = self.find_or_create_mozleak(data)
+        scope_data["objects"].append({"process": data["process"],
+                                      "name": data["name"],
+                                      "allowed": data.get("allowed", False),
+                                      "bytes": data["bytes"]})
+
+    def mozleak_total(self, data):
+        scope_data = self.find_or_create_mozleak(data)
+        scope_data["total"].append({"bytes": data["bytes"],
+                                    "threshold": data.get("threshold", 0),
+                                    "process": data["process"]})
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptscreenshot.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptscreenshot.py
new file mode 100644
index 0000000..f854d95
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/formatters/wptscreenshot.py
@@ -0,0 +1,47 @@
+import requests
+from mozlog.structured.formatters.base import BaseFormatter
+
+DEFAULT_API = "https://wpt.fyi/api/screenshots/hashes"
+
+
+class WptscreenshotFormatter(BaseFormatter):
+    """Formatter that outputs screenshots in the format expected by wpt.fyi."""
+
+    def __init__(self, api=None):
+        self.api = api or DEFAULT_API
+        self.cache = set()
+
+    def suite_start(self, data):
+        # TODO(Hexcles): We might want to move the request into a different
+        # place, make it non-blocking, and handle errors better.
+        params = {}
+        run_info = data.get("run_info", {})
+        if "product" in run_info:
+            params["browser"] = run_info["product"]
+        if "browser_version" in run_info:
+            params["browser_version"] = run_info["browser_version"]
+        if "os" in run_info:
+            params["os"] = run_info["os"]
+        if "os_version" in run_info:
+            params["os_version"] = run_info["os_version"]
+        try:
+            r = requests.get(self.api, params=params)
+            r.raise_for_status()
+            self.cache = set(r.json())
+        except (requests.exceptions.RequestException, ValueError):
+            pass
+
+    def test_end(self, data):
+        if "reftest_screenshots" not in data.get("extra", {}):
+            return
+        output = ""
+        for item in data["extra"]["reftest_screenshots"]:
+            if type(item) != dict:
+                # Skip the relation string.
+                continue
+            checksum = "sha1:" + item["hash"]
+            if checksum in self.cache:
+                continue
+            self.cache.add(checksum)
+            output += "data:image/png;base64,{}\n".format(item["screenshot"])
+        return output if output else None
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/instruments.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/instruments.py
new file mode 100644
index 0000000..a887cf4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/instruments.py
@@ -0,0 +1,117 @@
+import time
+import threading
+from six.moves.queue import Queue
+
+"""Instrumentation for measuring high-level time spent on various tasks inside the runner.
+
+This is lower fidelity than an actual profile, but allows custom data to be considered,
+so that we can see the time spent in specific tests and test directories.
+
+
+Instruments are intended to be used as context managers with the return value of __enter__
+containing the user-facing API e.g.
+
+with Instrument(*args) as recording:
+    recording.set(["init"])
+    do_init()
+    recording.pause()
+    for thread in test_threads:
+       thread.start(recording, *args)
+    for thread in test_threads:
+       thread.join()
+    recording.set(["teardown"])   # un-pauses the Instrument
+    do_teardown()
+"""
+
+class NullInstrument(object):
+    def set(self, stack):
+        """Set the current task to stack
+
+        :param stack: A list of strings defining the current task.
+                      These are interpreted like a stack trace so that ["foo"] and
+                      ["foo", "bar"] both show up as descendants of "foo"
+        """
+        pass
+
+    def pause(self):
+        """Stop recording a task on the current thread. This is useful if the thread
+        is purely waiting on the results of other threads"""
+        pass
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args, **kwargs):
+        return
+
+
+class InstrumentWriter(object):
+    def __init__(self, queue):
+        self.queue = queue
+
+    def set(self, stack):
+        stack.insert(0, threading.current_thread().name)
+        stack = self._check_stack(stack)
+        self.queue.put(("set", threading.current_thread().ident, time.time(), stack))
+
+    def pause(self):
+        self.queue.put(("pause", threading.current_thread().ident, time.time(), None))
+
+    def _check_stack(self, stack):
+        assert isinstance(stack, (tuple, list))
+        return [item.replace(" ", "_") for item in stack]
+
+
+class Instrument(object):
+    def __init__(self, file_path):
+        """Instrument that collects data from multiple threads and sums the time in each
+        thread. The output is in the format required by flamegraph.pl to enable visualisation
+        of the time spent in each task.
+
+        :param file_path: - The path on which to write instrument output. Any existing file
+                            at the path will be overwritten
+        """
+        self.path = file_path
+        self.queue = None
+        self.current = None
+        self.start_time = None
+        self.thread = None
+
+    def __enter__(self):
+        assert self.thread is None
+        assert self.queue is None
+        self.queue = Queue()
+        self.thread = threading.Thread(target=self.run)
+        self.thread.start()
+        return InstrumentWriter(self.queue)
+
+    def __exit__(self, *args, **kwargs):
+        self.queue.put(("stop", None, time.time(), None))
+        self.thread.join()
+        self.thread = None
+        self.queue = None
+
+    def run(self):
+        known_commands = {"stop", "pause", "set"}
+        with open(self.path, "w") as f:
+            thread_data = {}
+            while True:
+                command, thread, time_stamp, stack = self.queue.get()
+                assert command in known_commands
+
+                # If we are done recording, dump the information from all threads to the file
+                # before exiting. Otherwise for either 'set' or 'pause' we only need to dump
+                # information from the current stack (if any) that was recording on the reporting
+                # thread (as that stack is no longer active).
+                items = []
+                if command == "stop":
+                    items = thread_data.values()
+                elif thread in thread_data:
+                    items.append(thread_data.pop(thread))
+                for output_stack, start_time in items:
+                    f.write("%s %d\n" % (";".join(output_stack), int(1000 * (time_stamp - start_time))))
+
+                if command == "set":
+                    thread_data[thread] = (stack, time_stamp)
+                elif command == "stop":
+                    break
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestexpected.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestexpected.py
new file mode 100644
index 0000000..31c57e9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestexpected.py
@@ -0,0 +1,542 @@
+import os
+from collections import deque
+from six import string_types, text_type
+from six.moves.urllib.parse import urljoin
+
+
+from .wptmanifest.backends import static
+from .wptmanifest.backends.base import ManifestItem
+
+from . import expected
+
+"""Manifest structure used to store expected results of a test.
+
+Each manifest file is represented by an ExpectedManifest that
+has one or more TestNode children, one per test in the manifest.
+Each TestNode has zero or more SubtestNode children, one for each
+known subtest of the test.
+"""
+
+
+def data_cls_getter(output_node, visited_node):
+    # visited_node is intentionally unused
+    if output_node is None:
+        return ExpectedManifest
+    if isinstance(output_node, ExpectedManifest):
+        return TestNode
+    if isinstance(output_node, TestNode):
+        return SubtestNode
+    raise ValueError
+
+
+def bool_prop(name, node):
+    """Boolean property"""
+    try:
+        return bool(node.get(name))
+    except KeyError:
+        return None
+
+
+def int_prop(name, node):
+    """Boolean property"""
+    try:
+        return int(node.get(name))
+    except KeyError:
+        return None
+
+
+def list_prop(name, node):
+    """List property"""
+    try:
+        list_prop = node.get(name)
+        if isinstance(list_prop, string_types):
+            return [list_prop]
+        return list(list_prop)
+    except KeyError:
+        return []
+
+
+def str_prop(name, node):
+    try:
+        prop = node.get(name)
+        if not isinstance(prop, string_types):
+            raise ValueError
+        return prop
+    except KeyError:
+        return None
+
+
+def tags(node):
+    """Set of tags that have been applied to the test"""
+    try:
+        value = node.get("tags")
+        if isinstance(value, text_type):
+            return {value}
+        return set(value)
+    except KeyError:
+        return set()
+
+
+def prefs(node):
+    def value(ini_value):
+        if isinstance(ini_value, text_type):
+            return tuple(pref_piece.strip() for pref_piece in ini_value.split(':', 1))
+        else:
+            # this should be things like @Reset, which are apparently type 'object'
+            return (ini_value, None)
+
+    try:
+        node_prefs = node.get("prefs")
+        if isinstance(node_prefs, text_type):
+            rv = dict(value(node_prefs))
+        else:
+            rv = dict(value(item) for item in node_prefs)
+    except KeyError:
+        rv = {}
+    return rv
+
+
+def set_prop(name, node):
+    try:
+        node_items = node.get(name)
+        if isinstance(node_items, text_type):
+            rv = {node_items}
+        else:
+            rv = set(node_items)
+    except KeyError:
+        rv = set()
+    return rv
+
+
+def leak_threshold(node):
+    rv = {}
+    try:
+        node_items = node.get("leak-threshold")
+        if isinstance(node_items, text_type):
+            node_items = [node_items]
+        for item in node_items:
+            process, value = item.rsplit(":", 1)
+            rv[process.strip()] = int(value.strip())
+    except KeyError:
+        pass
+    return rv
+
+
+def fuzzy_prop(node):
+    """Fuzzy reftest match
+
+    This can either be a list of strings or a single string. When a list is
+    supplied, the format of each item matches the description below.
+
+    The general format is
+    fuzzy = [key ":"] <prop> ";" <prop>
+    key = <test name> [reftype <reference name>]
+    reftype = "==" | "!="
+    prop = [propName "=" ] range
+    propName = "maxDifferences" | "totalPixels"
+    range = <digits> ["-" <digits>]
+
+    So for example:
+      maxDifferences=10;totalPixels=10-20
+
+      specifies that for any test/ref pair for which no other rule is supplied,
+      there must be a maximum pixel difference of exactly 10, and betwen 10 and
+      20 total pixels different.
+
+      test.html==ref.htm:10;20
+
+      specifies that for a equality comparison between test.html and ref.htm,
+      resolved relative to the test path, there can be a maximum difference
+      of 10 in the pixel value for any channel and 20 pixels total difference.
+
+      ref.html:10;20
+
+      is just like the above but applies to any comparison involving ref.html
+      on the right hand side.
+
+    The return format is [(key, (maxDifferenceRange, totalPixelsRange))], where
+    the key is either None where no specific reference is specified, the reference
+    name where there is only one component or a tuple (test, ref, reftype) when the
+    exact comparison is specified. maxDifferenceRange and totalPixelsRange are tuples
+    of integers indicating the inclusive range of allowed values.
+"""
+    rv = []
+    args = ["maxDifference", "totalPixels"]
+    try:
+        value = node.get("fuzzy")
+    except KeyError:
+        return rv
+    if not isinstance(value, list):
+        value = [value]
+    for item in value:
+        if not isinstance(item, text_type):
+            rv.append(item)
+            continue
+        parts = item.rsplit(":", 1)
+        if len(parts) == 1:
+            key = None
+            fuzzy_values = parts[0]
+        else:
+            key, fuzzy_values = parts
+            for reftype in ["==", "!="]:
+                if reftype in key:
+                    key = key.split(reftype)
+                    key.append(reftype)
+                    key = tuple(key)
+        ranges = fuzzy_values.split(";")
+        if len(ranges) != 2:
+            raise ValueError("Malformed fuzzy value %s" % item)
+        arg_values = {None: deque()}
+        for range_str_value in ranges:
+            if "=" in range_str_value:
+                name, range_str_value = [part.strip()
+                                         for part in range_str_value.split("=", 1)]
+                if name not in args:
+                    raise ValueError("%s is not a valid fuzzy property" % name)
+                if arg_values.get(name):
+                    raise ValueError("Got multiple values for argument %s" % name)
+            else:
+                name = None
+            if "-" in range_str_value:
+                range_min, range_max = range_str_value.split("-")
+            else:
+                range_min = range_str_value
+                range_max = range_str_value
+            try:
+                range_value = tuple(int(item.strip()) for item in (range_min, range_max))
+            except ValueError:
+                raise ValueError("Fuzzy value %s must be a range of integers" % range_str_value)
+            if name is None:
+                arg_values[None].append(range_value)
+            else:
+                arg_values[name] = range_value
+        range_values = []
+        for arg_name in args:
+            if arg_values.get(arg_name):
+                value = arg_values.pop(arg_name)
+            else:
+                value = arg_values[None].popleft()
+            range_values.append(value)
+        rv.append((key, tuple(range_values)))
+    return rv
+
+
+class ExpectedManifest(ManifestItem):
+    def __init__(self, node, test_path, url_base):
+        """Object representing all the tests in a particular manifest
+
+        :param name: Name of the AST Node associated with this object.
+                     Should always be None since this should always be associated with
+                     the root node of the AST.
+        :param test_path: Path of the test file associated with this manifest.
+        :param url_base: Base url for serving the tests in this manifest
+        """
+        name = node.data
+        if name is not None:
+            raise ValueError("ExpectedManifest should represent the root node")
+        if test_path is None:
+            raise ValueError("ExpectedManifest requires a test path")
+        if url_base is None:
+            raise ValueError("ExpectedManifest requires a base url")
+        ManifestItem.__init__(self, node)
+        self.child_map = {}
+        self.test_path = test_path
+        self.url_base = url_base
+
+    def append(self, child):
+        """Add a test to the manifest"""
+        ManifestItem.append(self, child)
+        self.child_map[child.id] = child
+
+    def _remove_child(self, child):
+        del self.child_map[child.id]
+        ManifestItem.remove_child(self, child)
+        assert len(self.child_map) == len(self.children)
+
+    def get_test(self, test_id):
+        """Get a test from the manifest by ID
+
+        :param test_id: ID of the test to return."""
+        return self.child_map.get(test_id)
+
+    @property
+    def url(self):
+        return urljoin(self.url_base,
+                       "/".join(self.test_path.split(os.path.sep)))
+
+    @property
+    def disabled(self):
+        return bool_prop("disabled", self)
+
+    @property
+    def restart_after(self):
+        return bool_prop("restart-after", self)
+
+    @property
+    def leaks(self):
+        return bool_prop("leaks", self)
+
+    @property
+    def min_assertion_count(self):
+        return int_prop("min-asserts", self)
+
+    @property
+    def max_assertion_count(self):
+        return int_prop("max-asserts", self)
+
+    @property
+    def tags(self):
+        return tags(self)
+
+    @property
+    def prefs(self):
+        return prefs(self)
+
+    @property
+    def lsan_disabled(self):
+        return bool_prop("lsan-disabled", self)
+
+    @property
+    def lsan_allowed(self):
+        return set_prop("lsan-allowed", self)
+
+    @property
+    def leak_allowed(self):
+        return set_prop("leak-allowed", self)
+
+    @property
+    def leak_threshold(self):
+        return leak_threshold(self)
+
+    @property
+    def lsan_max_stack_depth(self):
+        return int_prop("lsan-max-stack-depth", self)
+
+    @property
+    def fuzzy(self):
+        return fuzzy_prop(self)
+
+    @property
+    def expected(self):
+        return list_prop("expected", self)[0]
+
+    @property
+    def known_intermittent(self):
+        return list_prop("expected", self)[1:]
+
+    @property
+    def implementation_status(self):
+        return str_prop("implementation-status", self)
+
+
+class DirectoryManifest(ManifestItem):
+    @property
+    def disabled(self):
+        return bool_prop("disabled", self)
+
+    @property
+    def restart_after(self):
+        return bool_prop("restart-after", self)
+
+    @property
+    def leaks(self):
+        return bool_prop("leaks", self)
+
+    @property
+    def min_assertion_count(self):
+        return int_prop("min-asserts", self)
+
+    @property
+    def max_assertion_count(self):
+        return int_prop("max-asserts", self)
+
+    @property
+    def tags(self):
+        return tags(self)
+
+    @property
+    def prefs(self):
+        return prefs(self)
+
+    @property
+    def lsan_disabled(self):
+        return bool_prop("lsan-disabled", self)
+
+    @property
+    def lsan_allowed(self):
+        return set_prop("lsan-allowed", self)
+
+    @property
+    def leak_allowed(self):
+        return set_prop("leak-allowed", self)
+
+    @property
+    def leak_threshold(self):
+        return leak_threshold(self)
+
+    @property
+    def lsan_max_stack_depth(self):
+        return int_prop("lsan-max-stack-depth", self)
+
+    @property
+    def fuzzy(self):
+        return fuzzy_prop(self)
+
+    @property
+    def implementation_status(self):
+        return str_prop("implementation-status", self)
+
+
+class TestNode(ManifestItem):
+    def __init__(self, node, **kwargs):
+        """Tree node associated with a particular test in a manifest
+
+        :param name: name of the test"""
+        assert node.data is not None
+        ManifestItem.__init__(self, node, **kwargs)
+        self.updated_expected = []
+        self.new_expected = []
+        self.subtests = {}
+        self.default_status = None
+        self._from_file = True
+
+    @property
+    def is_empty(self):
+        required_keys = {"type"}
+        if set(self._data.keys()) != required_keys:
+            return False
+        return all(child.is_empty for child in self.children)
+
+    @property
+    def test_type(self):
+        return self.get("type")
+
+    @property
+    def id(self):
+        return urljoin(self.parent.url, self.name)
+
+    @property
+    def disabled(self):
+        return bool_prop("disabled", self)
+
+    @property
+    def restart_after(self):
+        return bool_prop("restart-after", self)
+
+    @property
+    def leaks(self):
+        return bool_prop("leaks", self)
+
+    @property
+    def min_assertion_count(self):
+        return int_prop("min-asserts", self)
+
+    @property
+    def max_assertion_count(self):
+        return int_prop("max-asserts", self)
+
+    @property
+    def tags(self):
+        return tags(self)
+
+    @property
+    def prefs(self):
+        return prefs(self)
+
+    @property
+    def lsan_disabled(self):
+        return bool_prop("lsan-disabled", self)
+
+    @property
+    def lsan_allowed(self):
+        return set_prop("lsan-allowed", self)
+
+    @property
+    def leak_allowed(self):
+        return set_prop("leak-allowed", self)
+
+    @property
+    def leak_threshold(self):
+        return leak_threshold(self)
+
+    @property
+    def lsan_max_stack_depth(self):
+        return int_prop("lsan-max-stack-depth", self)
+
+    @property
+    def fuzzy(self):
+        return fuzzy_prop(self)
+
+    @property
+    def expected(self):
+        return list_prop("expected", self)[0]
+
+    @property
+    def known_intermittent(self):
+        return list_prop("expected", self)[1:]
+
+    @property
+    def implementation_status(self):
+        return str_prop("implementation-status", self)
+
+    def append(self, node):
+        """Add a subtest to the current test
+
+        :param node: AST Node associated with the subtest"""
+        child = ManifestItem.append(self, node)
+        self.subtests[child.name] = child
+
+    def get_subtest(self, name):
+        """Get the SubtestNode corresponding to a particular subtest, by name
+
+        :param name: Name of the node to return"""
+        if name in self.subtests:
+            return self.subtests[name]
+        return None
+
+
+class SubtestNode(TestNode):
+    @property
+    def is_empty(self):
+        if self._data:
+            return False
+        return True
+
+
+def get_manifest(metadata_root, test_path, url_base, run_info):
+    """Get the ExpectedManifest for a particular test path, or None if there is no
+    metadata stored for that test path.
+
+    :param metadata_root: Absolute path to the root of the metadata directory
+    :param test_path: Path to the test(s) relative to the test root
+    :param url_base: Base url for serving the tests in this manifest
+    :param run_info: Dictionary of properties of the test run for which the expectation
+                     values should be computed.
+    """
+    manifest_path = expected.expected_path(metadata_root, test_path)
+    try:
+        with open(manifest_path, "rb") as f:
+            return static.compile(f,
+                                  run_info,
+                                  data_cls_getter=data_cls_getter,
+                                  test_path=test_path,
+                                  url_base=url_base)
+    except IOError:
+        return None
+
+
+def get_dir_manifest(path, run_info):
+    """Get the ExpectedManifest for a particular test path, or None if there is no
+    metadata stored for that test path.
+
+    :param path: Full path to the ini file
+    :param run_info: Dictionary of properties of the test run for which the expectation
+                     values should be computed.
+    """
+    try:
+        with open(path, "rb") as f:
+            return static.compile(f,
+                                  run_info,
+                                  data_cls_getter=lambda x,y: DirectoryManifest)
+    except IOError:
+        return None
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestinclude.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestinclude.py
new file mode 100644
index 0000000..79b5b19
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestinclude.py
@@ -0,0 +1,155 @@
+"""Manifest structure used to store paths that should be included in a test run.
+
+The manifest is represented by a tree of IncludeManifest objects, the root
+representing the file and each subnode representing a subdirectory that should
+be included or excluded.
+"""
+import glob
+import os
+from six import iteritems
+from six.moves.urllib.parse import urlparse, urlsplit
+
+from .wptmanifest.node import DataNode
+from .wptmanifest.backends import conditional
+from .wptmanifest.backends.conditional import ManifestItem
+
+
+class IncludeManifest(ManifestItem):
+    def __init__(self, node):
+        """Node in a tree structure representing the paths
+        that should be included or excluded from the test run.
+
+        :param node: AST Node corresponding to this Node.
+        """
+        ManifestItem.__init__(self, node)
+        self.child_map = {}
+
+    @classmethod
+    def create(cls):
+        """Create an empty IncludeManifest tree"""
+        node = DataNode(None)
+        return cls(node)
+
+    def set_defaults(self):
+        if not self.has_key("skip"):
+            self.set("skip", "False")
+
+    def append(self, child):
+        ManifestItem.append(self, child)
+        self.child_map[child.name] = child
+        assert len(self.child_map) == len(self.children)
+
+    def include(self, test):
+        """Return a boolean indicating whether a particular test should be
+        included in a test run, based on the IncludeManifest tree rooted on
+        this object.
+
+        :param test: The test object"""
+        path_components = self._get_components(test.url)
+        return self._include(test, path_components)
+
+    def _include(self, test, path_components):
+        if path_components:
+            next_path_part = path_components.pop()
+            if next_path_part in self.child_map:
+                return self.child_map[next_path_part]._include(test, path_components)
+
+        node = self
+        while node:
+            try:
+                skip_value = self.get("skip", {"test_type": test.item_type}).lower()
+                assert skip_value in ("true", "false")
+                return skip_value != "true"
+            except KeyError:
+                if node.parent is not None:
+                    node = node.parent
+                else:
+                    # Include by default
+                    return True
+
+    def _get_components(self, url):
+        rv = []
+        url_parts = urlsplit(url)
+        variant = ""
+        if url_parts.query:
+            variant += "?" + url_parts.query
+        if url_parts.fragment:
+            variant += "#" + url_parts.fragment
+        if variant:
+            rv.append(variant)
+        rv.extend([item for item in reversed(url_parts.path.split("/")) if item])
+        return rv
+
+    def _add_rule(self, test_manifests, url, direction):
+        maybe_path = os.path.join(os.path.abspath(os.curdir), url)
+        rest, last = os.path.split(maybe_path)
+        fragment = query = None
+        if "#" in last:
+            last, fragment = last.rsplit("#", 1)
+        if "?" in last:
+            last, query = last.rsplit("?", 1)
+
+        maybe_path = os.path.join(rest, last)
+        paths = glob.glob(maybe_path)
+
+        if paths:
+            urls = []
+            for path in paths:
+                for manifest, data in iteritems(test_manifests):
+                    found = False
+                    rel_path = os.path.relpath(path, data["tests_path"])
+                    iterator = manifest.iterpath if os.path.isfile(path) else manifest.iterdir
+                    for test in iterator(rel_path):
+                        if not hasattr(test, "url"):
+                            continue
+                        url = test.url
+                        if query or fragment:
+                            parsed = urlparse(url)
+                            if ((query and query != parsed.query) or
+                                (fragment and fragment != parsed.fragment)):
+                                continue
+                        urls.append(url)
+                        found = True
+                    if found:
+                        break
+        else:
+            urls = [url]
+
+        assert direction in ("include", "exclude")
+
+        for url in urls:
+            components = self._get_components(url)
+
+            node = self
+            while components:
+                component = components.pop()
+                if component not in node.child_map:
+                    new_node = IncludeManifest(DataNode(component))
+                    node.append(new_node)
+                    new_node.set("skip", node.get("skip", {}))
+
+                node = node.child_map[component]
+
+            skip = False if direction == "include" else True
+            node.set("skip", str(skip))
+
+    def add_include(self, test_manifests, url_prefix):
+        """Add a rule indicating that tests under a url path
+        should be included in test runs
+
+        :param url_prefix: The url prefix to include
+        """
+        return self._add_rule(test_manifests, url_prefix, "include")
+
+    def add_exclude(self, test_manifests, url_prefix):
+        """Add a rule indicating that tests under a url path
+        should be excluded from test runs
+
+        :param url_prefix: The url prefix to exclude
+        """
+        return self._add_rule(test_manifests, url_prefix, "exclude")
+
+
+def get_manifest(manifest_path):
+    with open(manifest_path, "rb") as f:
+        return conditional.compile(f, data_cls_getter=lambda x, y: IncludeManifest)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestupdate.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestupdate.py
new file mode 100644
index 0000000..c74632b0
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/manifestupdate.py
@@ -0,0 +1,952 @@
+from __future__ import print_function
+import os
+from six.moves.urllib.parse import urljoin, urlsplit
+from collections import namedtuple, defaultdict, deque
+from math import ceil
+from six import integer_types, iterkeys, itervalues, iteritems, string_types, text_type
+
+from .wptmanifest import serialize
+from .wptmanifest.node import (DataNode, ConditionalNode, BinaryExpressionNode,
+                              BinaryOperatorNode, NumberNode, StringNode, VariableNode,
+                              ValueNode, UnaryExpressionNode, UnaryOperatorNode,
+                              ListNode)
+from .wptmanifest.backends import conditional
+from .wptmanifest.backends.conditional import ManifestItem
+
+from . import expected
+from . import expectedtree
+
+"""Manifest structure used to update the expected results of a test
+
+Each manifest file is represented by an ExpectedManifest that has one
+or more TestNode children, one per test in the manifest.  Each
+TestNode has zero or more SubtestNode children, one for each known
+subtest of the test.
+
+In these representations, conditionals expressions in the manifest are
+not evaluated upfront but stored as python functions to be evaluated
+at runtime.
+
+When a result for a test is to be updated set_result on the
+[Sub]TestNode is called to store the new result, alongside the
+existing conditional that result's run info matched, if any. Once all
+new results are known, update is called to compute the new
+set of results and conditionals. The AST of the underlying parsed manifest
+is updated with the changes, and the result is serialised to a file.
+"""
+
+
+class ConditionError(Exception):
+    def __init__(self, cond=None):
+        self.cond = cond
+
+
+class UpdateError(Exception):
+    pass
+
+
+Value = namedtuple("Value", ["run_info", "value"])
+
+
+def data_cls_getter(output_node, visited_node):
+    # visited_node is intentionally unused
+    if output_node is None:
+        return ExpectedManifest
+    elif isinstance(output_node, ExpectedManifest):
+        return TestNode
+    elif isinstance(output_node, TestNode):
+        return SubtestNode
+    else:
+        raise ValueError
+
+
+class UpdateProperties(object):
+    def __init__(self, manifest, **kwargs):
+        self._manifest = manifest
+        self._classes = kwargs
+
+    def __getattr__(self, name):
+        if name in self._classes:
+            rv = self._classes[name](self._manifest)
+            setattr(self, name, rv)
+            return rv
+        raise AttributeError
+
+    def __contains__(self, name):
+        return name in self._classes
+
+    def __iter__(self):
+        for name in iterkeys(self._classes):
+            yield getattr(self, name)
+
+
+class ExpectedManifest(ManifestItem):
+    def __init__(self, node, test_path, url_base, run_info_properties,
+                 update_intermittent=False, remove_intermittent=False):
+        """Object representing all the tests in a particular manifest
+
+        :param node: AST Node associated with this object. If this is None,
+                     a new AST is created to associate with this manifest.
+        :param test_path: Path of the test file associated with this manifest.
+        :param url_base: Base url for serving the tests in this manifest.
+        :param run_info_properties: Tuple of ([property name],
+                                              {property_name: [dependent property]})
+                                    The first part lists run_info properties
+                                    that are always used in the update, the second
+                                    maps property names to additional properties that
+                                    can be considered if we already have a condition on
+                                    the key property e.g. {"foo": ["bar"]} means that
+                                    we consider making conditions on bar only after we
+                                    already made one on foo.
+        :param update_intermittent: When True, intermittent statuses will be recorded
+                                    as `expected` in the test metadata.
+        :param: remove_intermittent: When True, old intermittent statuses will be removed
+                                    if no longer intermittent. This is only relevant if
+                                    `update_intermittent` is also True, because if False,
+                                    the metadata will simply update one `expected`status.
+        """
+        if node is None:
+            node = DataNode(None)
+        ManifestItem.__init__(self, node)
+        self.child_map = {}
+        self.test_path = test_path
+        self.url_base = url_base
+        assert self.url_base is not None
+        self._modified = False
+        self.run_info_properties = run_info_properties
+        self.update_intermittent = update_intermittent
+        self.remove_intermittent = remove_intermittent
+        self.update_properties = UpdateProperties(self, **{
+            "lsan": LsanUpdate,
+            "leak_object": LeakObjectUpdate,
+            "leak_threshold": LeakThresholdUpdate,
+        })
+
+    @property
+    def modified(self):
+        if self._modified:
+            return True
+        return any(item.modified for item in self.children)
+
+    @modified.setter
+    def modified(self, value):
+        self._modified = value
+
+    def append(self, child):
+        ManifestItem.append(self, child)
+        if child.id in self.child_map:
+            print("Warning: Duplicate heading %s" % child.id)
+        self.child_map[child.id] = child
+
+    def _remove_child(self, child):
+        del self.child_map[child.id]
+        ManifestItem._remove_child(self, child)
+
+    def get_test(self, test_id):
+        """Return a TestNode by test id, or None if no test matches
+
+        :param test_id: The id of the test to look up"""
+
+        return self.child_map.get(test_id)
+
+    def has_test(self, test_id):
+        """Boolean indicating whether the current test has a known child test
+        with id test id
+
+        :param test_id: The id of the test to look up"""
+
+        return test_id in self.child_map
+
+    @property
+    def url(self):
+        return urljoin(self.url_base,
+                       "/".join(self.test_path.split(os.path.sep)))
+
+    def set_lsan(self, run_info, result):
+        """Set the result of the test in a particular run
+
+        :param run_info: Dictionary of run_info parameters corresponding
+                         to this run
+        :param result: Lsan violations detected"""
+        self.update_properties.lsan.set(run_info, result)
+
+    def set_leak_object(self, run_info, result):
+        """Set the result of the test in a particular run
+
+        :param run_info: Dictionary of run_info parameters corresponding
+                         to this run
+        :param result: Leaked objects deletec"""
+        self.update_properties.leak_object.set(run_info, result)
+
+    def set_leak_threshold(self, run_info, result):
+        """Set the result of the test in a particular run
+
+        :param run_info: Dictionary of run_info parameters corresponding
+                         to this run
+        :param result: Total number of bytes leaked"""
+        self.update_properties.leak_threshold.set(run_info, result)
+
+    def update(self, full_update, disable_intermittent):
+        for prop_update in self.update_properties:
+            prop_update.update(full_update,
+                               disable_intermittent)
+
+
+class TestNode(ManifestItem):
+    def __init__(self, node):
+        """Tree node associated with a particular test in a manifest
+
+        :param node: AST node associated with the test"""
+
+        ManifestItem.__init__(self, node)
+        self.subtests = {}
+        self._from_file = True
+        self.new_disabled = False
+        self.has_result = False
+        self.modified = False
+        self.update_properties = UpdateProperties(
+            self,
+            expected=ExpectedUpdate,
+            max_asserts=MaxAssertsUpdate,
+            min_asserts=MinAssertsUpdate
+        )
+
+    @classmethod
+    def create(cls, test_id):
+        """Create a TestNode corresponding to a given test
+
+        :param test_type: The type of the test
+        :param test_id: The id of the test"""
+        name = test_id[len(urlsplit(test_id).path.rsplit("/", 1)[0]) + 1:]
+        node = DataNode(name)
+        self = cls(node)
+
+        self._from_file = False
+        return self
+
+    @property
+    def is_empty(self):
+        ignore_keys = {"type"}
+        if set(self._data.keys()) - ignore_keys:
+            return False
+        return all(child.is_empty for child in self.children)
+
+    @property
+    def test_type(self):
+        """The type of the test represented by this TestNode"""
+        return self.get("type", None)
+
+    @property
+    def id(self):
+        """The id of the test represented by this TestNode"""
+        return urljoin(self.parent.url, self.name)
+
+    def disabled(self, run_info):
+        """Boolean indicating whether this test is disabled when run in an
+        environment with the given run_info
+
+        :param run_info: Dictionary of run_info parameters"""
+
+        return self.get("disabled", run_info) is not None
+
+    def set_result(self, run_info, result):
+        """Set the result of the test in a particular run
+
+        :param run_info: Dictionary of run_info parameters corresponding
+                         to this run
+        :param result: Status of the test in this run"""
+        self.update_properties.expected.set(run_info, result)
+
+    def set_asserts(self, run_info, count):
+        """Set the assert count of a test
+
+        """
+        self.update_properties.min_asserts.set(run_info, count)
+        self.update_properties.max_asserts.set(run_info, count)
+
+    def append(self, node):
+        child = ManifestItem.append(self, node)
+        self.subtests[child.name] = child
+
+    def get_subtest(self, name):
+        """Return a SubtestNode corresponding to a particular subtest of
+        the current test, creating a new one if no subtest with that name
+        already exists.
+
+        :param name: Name of the subtest"""
+
+        if name in self.subtests:
+            return self.subtests[name]
+        else:
+            subtest = SubtestNode.create(name)
+            self.append(subtest)
+            return subtest
+
+    def update(self, full_update, disable_intermittent):
+        for prop_update in self.update_properties:
+            prop_update.update(full_update,
+                               disable_intermittent)
+
+
+class SubtestNode(TestNode):
+    def __init__(self, node):
+        assert isinstance(node, DataNode)
+        TestNode.__init__(self, node)
+
+    @classmethod
+    def create(cls, name):
+        node = DataNode(name)
+        self = cls(node)
+        return self
+
+    @property
+    def is_empty(self):
+        if self._data:
+            return False
+        return True
+
+
+def build_conditional_tree(_, run_info_properties, results):
+    properties, dependent_props = run_info_properties
+    return expectedtree.build_tree(properties, dependent_props, results)
+
+
+def build_unconditional_tree(_, run_info_properties, results):
+    root = expectedtree.Node(None, None)
+    for run_info, values in iteritems(results):
+        for value, count in iteritems(values):
+            root.result_values[value] += count
+        root.run_info.add(run_info)
+    return root
+
+
+class PropertyUpdate(object):
+    property_name = None
+    cls_default_value = None
+    value_type = None
+    property_builder = None
+
+    def __init__(self, node):
+        self.node = node
+        self.default_value = self.cls_default_value
+        self.has_result = False
+        self.results = defaultdict(lambda: defaultdict(int))
+        self.update_intermittent = self.node.root.update_intermittent
+        self.remove_intermittent = self.node.root.remove_intermittent
+
+    def run_info_by_condition(self, run_info_index, conditions):
+        run_info_by_condition = defaultdict(list)
+        # A condition might match 0 or more run_info values
+        run_infos = run_info_index.keys()
+        for cond in conditions:
+            for run_info in run_infos:
+                if cond(run_info):
+                    run_info_by_condition[cond].append(run_info)
+
+        return run_info_by_condition
+
+    def set(self, run_info, value):
+        self.has_result = True
+        self.node.has_result = True
+        self.check_default(value)
+        value = self.from_result_value(value)
+        self.results[run_info][value] += 1
+
+    def check_default(self, result):
+        return
+
+    def from_result_value(self, value):
+        """Convert a value from a test result into the internal format"""
+        return value
+
+    def from_ini_value(self, value):
+        """Convert a value from an ini file into the internal format"""
+        if self.value_type:
+            return self.value_type(value)
+        return value
+
+    def to_ini_value(self, value):
+        """Convert a value from the internal format to the ini file format"""
+        return str(value)
+
+    def updated_value(self, current, new):
+        """Given a single current value and a set of observed new values,
+        compute an updated value for the property"""
+        return new
+
+    @property
+    def unconditional_value(self):
+        try:
+            unconditional_value = self.from_ini_value(
+                self.node.get(self.property_name))
+        except KeyError:
+            unconditional_value = self.default_value
+        return unconditional_value
+
+    def update(self,
+               full_update=False,
+               disable_intermittent=None):
+        """Update the underlying manifest AST for this test based on all the
+        added results.
+
+        This will update existing conditionals if they got the same result in
+        all matching runs in the updated results, will delete existing conditionals
+        that get more than one different result in the updated run, and add new
+        conditionals for anything that doesn't match an existing conditional.
+
+        Conditionals not matched by any added result are not changed.
+
+        When `disable_intermittent` is not None, disable any test that shows multiple
+        unexpected results for the same set of parameters.
+        """
+        if not self.has_result:
+            return
+
+        property_tree = self.property_builder(self.node.root.run_info_properties,
+                                              self.results)
+
+        conditions, errors = self.update_conditions(property_tree,
+                                                    full_update)
+
+        for e in errors:
+            if disable_intermittent:
+                condition = e.cond.children[0] if e.cond else None
+                msg = disable_intermittent if isinstance(disable_intermittent, string_types+(text_type,)) else "unstable"
+                self.node.set("disabled", msg, condition)
+                self.node.new_disabled = True
+            else:
+                msg = "Conflicting metadata values for %s" % (
+                    self.node.root.test_path)
+                if e.cond:
+                    msg += ": %s" % serialize(e.cond).strip()
+                print(msg)
+
+        # If all the values match remove all conditionals
+        # This handles the case where we update a number of existing conditions and they
+        # all end up looking like the post-update default.
+        new_default = self.default_value
+        if conditions and conditions[-1][0] is None:
+            new_default = conditions[-1][1]
+        if all(condition[1] == new_default for condition in conditions):
+            conditions = [(None, new_default)]
+
+        # Don't set the default to the class default
+        if (conditions and
+            conditions[-1][0] is None and
+            conditions[-1][1] == self.default_value):
+            self.node.modified = True
+            conditions = conditions[:-1]
+
+        if self.node.modified:
+            self.node.clear(self.property_name)
+
+            for condition, value in conditions:
+                self.node.set(self.property_name,
+                              self.to_ini_value(value),
+                              condition)
+
+    def update_conditions(self,
+                          property_tree,
+                          full_update):
+        # This is complicated because the expected behaviour is complex
+        # The complexity arises from the fact that there are two ways of running
+        # the tool, with a full set of runs (full_update=True) or with partial metadata
+        # (full_update=False). In the case of a full update things are relatively simple:
+        # * All existing conditionals are ignored, with the exception of conditionals that
+        #   depend on variables not used by the updater, which are retained as-is
+        # * All created conditionals are independent of each other (i.e. order isn't
+        #   important in the created conditionals)
+        # In the case where we don't have a full set of runs, the expected behaviour
+        # is much less clear. This is of course the common case for when a developer
+        # runs the test on their own machine. In this case the assumptions above are untrue
+        # * The existing conditions may be required to handle other platforms
+        # * The order of the conditions may be important, since we don't know if they overlap
+        #   e.g. `if os == linux and version == 18.04` overlaps with `if (os != win)`.
+        # So in the case we have a full set of runs, the process is pretty simple:
+        # * Generate the conditionals for the property_tree
+        # * Pick the most common value as the default and add only those conditions
+        #   not matching the default
+        # In the case where we have a partial set of runs, things are more complex
+        # and more best-effort
+        # * For each existing conditional, see if it matches any of the run info we
+        #   have. In cases where it does match, record the new results
+        # * Where all the new results match, update the right hand side of that
+        #   conditional, otherwise remove it
+        # * If this leaves nothing existing, then proceed as with the full update
+        # * Otherwise add conditionals for the run_info that doesn't match any
+        #   remaining conditions
+        prev_default = None
+
+        current_conditions = self.node.get_conditions(self.property_name)
+
+        # Ignore the current default value
+        if current_conditions and current_conditions[-1].condition_node is None:
+            self.node.modified = True
+            prev_default = current_conditions[-1].value
+            current_conditions = current_conditions[:-1]
+
+        # If there aren't any current conditions, or there is just a default
+        # value for all run_info, proceed as for a full update
+        if not current_conditions:
+            return self._update_conditions_full(property_tree,
+                                                prev_default=prev_default)
+
+        conditions = []
+        errors = []
+
+        run_info_index = {run_info: node
+                          for node in property_tree
+                          for run_info in node.run_info}
+
+        node_by_run_info = {run_info: node
+                            for (run_info, node) in iteritems(run_info_index)
+                            if node.result_values}
+
+        run_info_by_condition = self.run_info_by_condition(run_info_index,
+                                                           current_conditions)
+
+        run_info_with_condition = set()
+
+        if full_update:
+            # Even for a full update we need to keep hand-written conditions not
+            # using the properties we've specified and not matching any run_info
+            top_level_props, dependent_props = self.node.root.run_info_properties
+            update_properties = set(top_level_props)
+            for item in itervalues(dependent_props):
+                update_properties |= set(item)
+            for condition in current_conditions:
+                if ((not condition.variables.issubset(update_properties) and
+                     not run_info_by_condition[condition])):
+                    conditions.append((condition.condition_node,
+                                       self.from_ini_value(condition.value)))
+
+            new_conditions, errors = self._update_conditions_full(property_tree,
+                                                                  prev_default=prev_default)
+            conditions.extend(new_conditions)
+            return conditions, errors
+
+        # Retain existing conditions if they match the updated values
+        for condition in current_conditions:
+            # All run_info that isn't handled by some previous condition
+            all_run_infos_condition = run_info_by_condition[condition]
+            run_infos = {item for item in all_run_infos_condition
+                         if item not in run_info_with_condition}
+
+            if not run_infos:
+                # Retain existing conditions that don't match anything in the update
+                conditions.append((condition.condition_node,
+                                   self.from_ini_value(condition.value)))
+                continue
+
+            # Set of nodes in the updated tree that match the same run_info values as the
+            # current existing node
+            nodes = [node_by_run_info[run_info] for run_info in run_infos
+                     if run_info in node_by_run_info]
+            # If all the values are the same, update the value
+            if nodes and all(set(node.result_values.keys()) == set(nodes[0].result_values.keys()) for node in nodes):
+                current_value = self.from_ini_value(condition.value)
+                try:
+                    new_value = self.updated_value(current_value,
+                                                   nodes[0].result_values)
+                except ConditionError as e:
+                    errors.append(e)
+                    continue
+                if new_value != current_value:
+                    self.node.modified = True
+                conditions.append((condition.condition_node, new_value))
+                run_info_with_condition |= set(run_infos)
+            else:
+                # Don't append this condition
+                self.node.modified = True
+
+        new_conditions, new_errors = self.build_tree_conditions(property_tree,
+                                                                run_info_with_condition,
+                                                                prev_default)
+        if new_conditions:
+            self.node.modified = True
+
+        conditions.extend(new_conditions)
+        errors.extend(new_errors)
+
+        return conditions, errors
+
+    def _update_conditions_full(self,
+                                property_tree,
+                                prev_default=None):
+        self.node.modified = True
+        conditions, errors = self.build_tree_conditions(property_tree,
+                                                        set(),
+                                                        prev_default)
+
+        return conditions, errors
+
+    def build_tree_conditions(self,
+                              property_tree,
+                              run_info_with_condition,
+                              prev_default=None):
+        conditions = []
+        errors = []
+
+        value_count = defaultdict(int)
+
+        def to_count_value(v):
+            if v is None:
+                return v
+            # Need to count the values in a hashable type
+            count_value = self.to_ini_value(v)
+            if isinstance(count_value, list):
+                count_value = tuple(count_value)
+            return count_value
+
+
+        queue = deque([(property_tree, [])])
+        while queue:
+            node, parents = queue.popleft()
+            parents_and_self = parents + [node]
+            if node.result_values and any(run_info not in run_info_with_condition
+                                          for run_info in node.run_info):
+                prop_set = [(item.prop, item.value) for item in parents_and_self if item.prop]
+                value = node.result_values
+                error = None
+                if parents:
+                    try:
+                        value = self.updated_value(None, value)
+                    except ConditionError:
+                        expr = make_expr(prop_set, value)
+                        error = ConditionError(expr)
+                    expr = make_expr(prop_set, value)
+                else:
+                    # The root node needs special handling
+                    expr = None
+                    try:
+                        value = self.updated_value(self.unconditional_value,
+                                                   value)
+                    except ConditionError:
+                        error = ConditionError(expr)
+                        # If we got an error for the root node, re-add the previous
+                        # default value
+                        if prev_default:
+                            conditions.append((None, prev_default))
+                if error is None:
+                    count_value = to_count_value(value)
+                    value_count[count_value] += len(node.run_info)
+
+                if error is None:
+                    conditions.append((expr, value))
+                else:
+                    errors.append(error)
+
+            for child in node.children:
+                queue.append((child, parents_and_self))
+
+        conditions = conditions[::-1]
+
+        # If we haven't set a default condition, add one and remove all the conditions
+        # with the same value
+        if value_count and (not conditions or conditions[-1][0] is not None):
+            # Sort in order of occurence, prioritising values that match the class default
+            # or the previous default
+            cls_default = to_count_value(self.default_value)
+            prev_default = to_count_value(prev_default)
+            commonest_value = max(value_count, key=lambda x:(value_count.get(x),
+                                                             x == cls_default,
+                                                             x == prev_default))
+            if isinstance(commonest_value, tuple):
+                commonest_value = list(commonest_value)
+            commonest_value = self.from_ini_value(commonest_value)
+            conditions = [item for item in conditions if item[1] != commonest_value]
+            conditions.append((None, commonest_value))
+
+        return conditions, errors
+
+
+class ExpectedUpdate(PropertyUpdate):
+    property_name = "expected"
+    property_builder = build_conditional_tree
+
+    def check_default(self, result):
+        if self.default_value is not None:
+            assert self.default_value == result.default_expected
+        else:
+            self.default_value = result.default_expected
+
+    def from_result_value(self, result):
+        # When we are updating intermittents, we need to keep a record of any existing
+        # intermittents to pass on when building the property tree and matching statuses and
+        # intermittents to the correct run info -  this is so we can add them back into the
+        # metadata aligned with the right conditions, unless specified not to with
+        # self.remove_intermittent.
+        # The (status, known_intermittent) tuple is counted when the property tree is built, but
+        # the count value only applies to the first item in the tuple, the status from that run,
+        # when passed to `updated_value`.
+        if (not self.update_intermittent or
+            self.remove_intermittent or
+            not result.known_intermittent):
+            return result.status
+        return result.status + result.known_intermittent
+
+    def to_ini_value(self, value):
+        if isinstance(value, (list, tuple)):
+            return [str(item) for item in value]
+        return str(value)
+
+    def updated_value(self, current, new):
+        if len(new) > 1 and not self.update_intermittent and not isinstance(current, list):
+            raise ConditionError
+
+        counts = {}
+        for status, count in iteritems(new):
+            if isinstance(status, tuple):
+                counts[status[0]] = count
+                counts.update({intermittent: 0 for intermittent in status[1:] if intermittent not in counts})
+            else:
+                counts[status] = count
+
+        if not (self.update_intermittent or isinstance(current, list)):
+            return list(counts)[0]
+
+        # Reorder statuses first based on counts, then based on status priority if there are ties.
+        # Counts with 0 are considered intermittent.
+        statuses = ["OK", "PASS", "FAIL", "ERROR", "TIMEOUT", "CRASH"]
+        status_priority = {value: i for i, value in enumerate(statuses)}
+        sorted_new = sorted(iteritems(counts), key=lambda x:(-1 * x[1],
+                                                           status_priority.get(x[0],
+                                                           len(status_priority))))
+        expected = []
+        for status, count in sorted_new:
+            # If we are not removing existing recorded intermittents, with a count of 0,
+            # add them in to expected.
+            if count > 0 or not self.remove_intermittent:
+                expected.append(status)
+
+        # If the new intermittent is a subset of the existing one, just use the existing one
+        # This prevents frequent flip-flopping of results between e.g. [OK, TIMEOUT] and
+        # [TIMEOUT, OK]
+        if current and set(expected).issubset(set(current)):
+            return current
+
+        if self.update_intermittent:
+            if len(expected) == 1:
+                return expected[0]
+            return expected
+
+        # If we are not updating intermittents, return the status with the highest occurence.
+        return expected[0]
+
+
+class MaxAssertsUpdate(PropertyUpdate):
+    """For asserts we always update the default value and never add new conditionals.
+    The value we set as the default is the maximum the current default or one more than the
+    number of asserts we saw in any configuration."""
+
+    property_name = "max-asserts"
+    cls_default_value = 0
+    value_type = int
+    property_builder = build_unconditional_tree
+
+    def updated_value(self, current, new):
+        if any(item > current for item in new):
+            return max(new) + 1
+        return current
+
+
+class MinAssertsUpdate(PropertyUpdate):
+    property_name = "min-asserts"
+    cls_default_value = 0
+    value_type = int
+    property_builder = build_unconditional_tree
+
+    def updated_value(self, current, new):
+        if any(item < current for item in new):
+            rv = min(new) - 1
+        else:
+            rv = current
+        return max(rv, 0)
+
+
+class AppendOnlyListUpdate(PropertyUpdate):
+    cls_default_value = []
+    property_builder = build_unconditional_tree
+
+    def updated_value(self, current, new):
+        if current is None:
+            rv = set()
+        else:
+            rv = set(current)
+
+        for item in new:
+            if item is None:
+                continue
+            elif isinstance(item, text_type):
+                rv.add(item)
+            else:
+                rv |= item
+
+        return sorted(rv)
+
+
+class LsanUpdate(AppendOnlyListUpdate):
+    property_name = "lsan-allowed"
+    property_builder = build_unconditional_tree
+
+    def from_result_value(self, result):
+        # If we have an allowed_match that matched, return None
+        # This value is ignored later (because it matches the default)
+        # We do that because then if we allow a failure in foo/__dir__.ini
+        # we don't want to update foo/bar/__dir__.ini with the same rule
+        if result[1]:
+            return None
+        # Otherwise return the topmost stack frame
+        # TODO: there is probably some improvement to be made by looking for a "better" stack frame
+        return result[0][0]
+
+    def to_ini_value(self, value):
+        return value
+
+
+class LeakObjectUpdate(AppendOnlyListUpdate):
+    property_name = "leak-allowed"
+    property_builder = build_unconditional_tree
+
+    def from_result_value(self, result):
+        # If we have an allowed_match that matched, return None
+        if result[1]:
+            return None
+        # Otherwise return the process/object name
+        return result[0]
+
+
+class LeakThresholdUpdate(PropertyUpdate):
+    property_name = "leak-threshold"
+    cls_default_value = {}
+    property_builder = build_unconditional_tree
+
+    def from_result_value(self, result):
+        return result
+
+    def to_ini_value(self, data):
+        return ["%s:%s" % item for item in sorted(iteritems(data))]
+
+    def from_ini_value(self, data):
+        rv = {}
+        for item in data:
+            key, value = item.split(":", 1)
+            rv[key] = int(float(value))
+        return rv
+
+    def updated_value(self, current, new):
+        if current:
+            rv = current.copy()
+        else:
+            rv = {}
+        for process, leaked_bytes, threshold in new:
+            # If the value is less than the threshold but there isn't
+            # an old value we must have inherited the threshold from
+            # a parent ini file so don't any anything to this one
+            if process not in rv and leaked_bytes < threshold:
+                continue
+            if leaked_bytes > rv.get(process, 0):
+                # Round up to nearest 50 kb
+                boundary = 50 * 1024
+                rv[process] = int(boundary * ceil(float(leaked_bytes) / boundary))
+        return rv
+
+
+def make_expr(prop_set, rhs):
+    """Create an AST that returns the value ``status`` given all the
+    properties in prop_set match.
+
+    :param prop_set: tuple of (property name, value) pairs for each
+                     property in this expression and the value it must match
+    :param status: Status on RHS when all the given properties match
+    """
+    root = ConditionalNode()
+
+    assert len(prop_set) > 0
+
+    expressions = []
+    for prop, value in prop_set:
+        if value not in (True, False):
+            expressions.append(
+                BinaryExpressionNode(
+                    BinaryOperatorNode("=="),
+                    VariableNode(prop),
+                    make_node(value)))
+        else:
+            if value:
+                expressions.append(VariableNode(prop))
+            else:
+                expressions.append(
+                    UnaryExpressionNode(
+                        UnaryOperatorNode("not"),
+                        VariableNode(prop)
+                    ))
+    if len(expressions) > 1:
+        prev = expressions[-1]
+        for curr in reversed(expressions[:-1]):
+            node = BinaryExpressionNode(
+                BinaryOperatorNode("and"),
+                curr,
+                prev)
+            prev = node
+    else:
+        node = expressions[0]
+
+    root.append(node)
+    rhs_node = make_value_node(rhs)
+    root.append(rhs_node)
+
+    return root
+
+
+def make_node(value):
+    if isinstance(value, integer_types+(float,)):
+        node = NumberNode(value)
+    elif isinstance(value, text_type):
+        node = StringNode(text_type(value))
+    elif hasattr(value, "__iter__"):
+        node = ListNode()
+        for item in value:
+            node.append(make_node(item))
+    return node
+
+
+def make_value_node(value):
+    if isinstance(value, integer_types+(float,)):
+        node = ValueNode(value)
+    elif isinstance(value, text_type):
+        node = ValueNode(text_type(value))
+    elif hasattr(value, "__iter__"):
+        node = ListNode()
+        for item in value:
+            node.append(make_node(item))
+    else:
+        raise ValueError("Don't know how to convert %s into node" % type(value))
+    return node
+
+
+def get_manifest(metadata_root, test_path, url_base, run_info_properties, update_intermittent, remove_intermittent):
+    """Get the ExpectedManifest for a particular test path, or None if there is no
+    metadata stored for that test path.
+
+    :param metadata_root: Absolute path to the root of the metadata directory
+    :param test_path: Path to the test(s) relative to the test root
+    :param url_base: Base url for serving the tests in this manifest"""
+    manifest_path = expected.expected_path(metadata_root, test_path)
+    try:
+        with open(manifest_path, "rb") as f:
+            rv = compile(f, test_path, url_base,
+                         run_info_properties, update_intermittent, remove_intermittent)
+    except IOError:
+        return None
+    return rv
+
+
+def compile(manifest_file, test_path, url_base, run_info_properties, update_intermittent, remove_intermittent):
+    return conditional.compile(manifest_file,
+                               data_cls_getter=data_cls_getter,
+                               test_path=test_path,
+                               url_base=url_base,
+                               run_info_properties=run_info_properties,
+                               update_intermittent=update_intermittent,
+                               remove_intermittent=remove_intermittent)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/metadata.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/metadata.py
new file mode 100644
index 0000000..ab8d474
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/metadata.py
@@ -0,0 +1,807 @@
+from __future__ import print_function
+import array
+import os
+import sys
+from collections import defaultdict, namedtuple
+
+from mozlog import structuredlog
+from six import ensure_str, ensure_text, iteritems, iterkeys, itervalues, text_type
+from six.moves import intern, range
+
+from . import manifestupdate
+from . import testloader
+from . import wptmanifest
+from . import wpttest
+from .expected import expected_path
+from .vcs import git
+manifest = None  # Module that will be imported relative to test_root
+manifestitem = None
+
+logger = structuredlog.StructuredLogger("web-platform-tests")
+
+try:
+    import ujson as json
+except ImportError:
+    import json
+
+
+class RunInfo(object):
+    """A wrapper around RunInfo dicts so that they can be hashed by identity"""
+
+    def __init__(self, dict_value):
+        self.data = dict_value
+        self.canonical_repr = tuple(tuple(item) for item in sorted(dict_value.items()))
+
+    def __getitem__(self, key):
+        return self.data[key]
+
+    def __setitem__(self, key, value):
+        raise TypeError
+
+    def __hash__(self):
+        return hash(self.canonical_repr)
+
+    def __eq__(self, other):
+        return self.canonical_repr == other.canonical_repr
+
+    def iteritems(self):
+        for key, value in iteritems(self.data):
+            yield key, value
+
+    def items(self):
+        return list(iteritems(self))
+
+
+def update_expected(test_paths, serve_root, log_file_names,
+                    update_properties, rev_old=None, rev_new="HEAD",
+                    full_update=False, sync_root=None, disable_intermittent=None,
+                    update_intermittent=False, remove_intermittent=False):
+    """Update the metadata files for web-platform-tests based on
+    the results obtained in a previous run or runs
+
+    If `disable_intermittent` is not None, assume log_file_names refers to logs from repeated
+    test jobs, disable tests that don't behave as expected on all runs
+
+    If `update_intermittent` is True, intermittent statuses will be recorded as `expected` in
+    the metadata.
+
+    If `remove_intermittent` is True and used in conjunction with `update_intermittent`, any
+    intermittent statuses which are not present in the current run will be removed from the
+    metadata, else they are left in."""
+
+    do_delayed_imports(serve_root)
+
+    id_test_map = load_test_data(test_paths)
+
+    for metadata_path, updated_ini in update_from_logs(id_test_map,
+                                                       update_properties,
+                                                       disable_intermittent,
+                                                       update_intermittent,
+                                                       remove_intermittent,
+                                                       full_update,
+                                                       *log_file_names):
+
+        write_new_expected(metadata_path, updated_ini)
+        if disable_intermittent:
+            for test in updated_ini.iterchildren():
+                for subtest in test.iterchildren():
+                    if subtest.new_disabled:
+                        print("disabled: %s" % os.path.dirname(subtest.root.test_path) + "/" + subtest.name)
+                    if test.new_disabled:
+                        print("disabled: %s" % test.root.test_path)
+
+
+def do_delayed_imports(serve_root=None):
+    global manifest, manifestitem
+    from manifest import manifest, item as manifestitem
+
+
+def files_in_repo(repo_root):
+    return git("ls-tree", "-r", "--name-only", "HEAD").split("\n")
+
+
+def rev_range(rev_old, rev_new, symmetric=False):
+    joiner = ".." if not symmetric else "..."
+    return "".join([rev_old, joiner, rev_new])
+
+
+def paths_changed(rev_old, rev_new, repo):
+    data = git("diff", "--name-status", rev_range(rev_old, rev_new), repo=repo)
+    lines = [tuple(item.strip() for item in line.strip().split("\t", 1))
+             for line in data.split("\n") if line.strip()]
+    output = set(lines)
+    return output
+
+
+def load_change_data(rev_old, rev_new, repo):
+    changes = paths_changed(rev_old, rev_new, repo)
+    rv = {}
+    status_keys = {"M": "modified",
+                   "A": "new",
+                   "D": "deleted"}
+    # TODO: deal with renames
+    for item in changes:
+        rv[item[1]] = status_keys[item[0]]
+    return rv
+
+
+def unexpected_changes(manifests, change_data, files_changed):
+    files_changed = set(files_changed)
+
+    root_manifest = None
+    for manifest, paths in iteritems(manifests):
+        if paths["url_base"] == "/":
+            root_manifest = manifest
+            break
+    else:
+        return []
+
+    return [fn for _, fn, _ in root_manifest if fn in files_changed and change_data.get(fn) != "M"]
+
+# For each testrun
+# Load all files and scan for the suite_start entry
+# Build a hash of filename: properties
+# For each different set of properties, gather all chunks
+# For each chunk in the set of chunks, go through all tests
+# for each test, make a map of {conditionals: [(platform, new_value)]}
+# Repeat for each platform
+# For each test in the list of tests:
+#   for each conditional:
+#      If all the new values match (or there aren't any) retain that conditional
+#      If any new values mismatch:
+#           If disable_intermittent and any repeated values don't match, disable the test
+#           else mark the test as needing human attention
+#   Check if all the RHS values are the same; if so collapse the conditionals
+
+
+class InternedData(object):
+    """Class for interning data of any (hashable) type.
+
+    This class is intended for building a mapping of int <=> value, such
+    that the integer may be stored as a proxy for the real value, and then
+    the real value obtained later from the proxy value.
+
+    In order to support the use case of packing the integer value as binary,
+    it is possible to specify a maximum bitsize of the data; adding more items
+    than this allowed will result in a ValueError exception.
+
+    The zero value is reserved to use as a sentinal."""
+
+    type_conv = None
+    rev_type_conv = None
+
+    def __init__(self, max_bits=8):
+        self.max_idx = 2**max_bits - 2
+        # Reserve 0 as a sentinal
+        self._data = [None], {}
+
+    def clear(self):
+        self.__init__()
+
+    def store(self, obj):
+        if self.type_conv is not None:
+            obj = self.type_conv(obj)
+
+        objs, obj_to_idx = self._data
+        if obj not in obj_to_idx:
+            value = len(objs)
+            objs.append(obj)
+            obj_to_idx[obj] = value
+            if value > self.max_idx:
+                raise ValueError
+        else:
+            value = obj_to_idx[obj]
+        return value
+
+    def get(self, idx):
+        obj = self._data[0][idx]
+        if self.rev_type_conv is not None:
+            obj = self.rev_type_conv(obj)
+        return obj
+
+    def __iter__(self):
+        for i in range(1, len(self._data[0])):
+            yield self.get(i)
+
+
+class RunInfoInterned(InternedData):
+    def type_conv(self, value):
+        return tuple(value.items())
+
+    def rev_type_conv(self, value):
+        return dict(value)
+
+
+prop_intern = InternedData(4)
+run_info_intern = InternedData(8)
+status_intern = InternedData(4)
+
+
+def pack_result(data):
+    # As `status_intern` normally handles one status, if `known_intermittent` is present in
+    # the test logs, intern and store this with the `status` in an array until needed.
+    if not data.get("known_intermittent"):
+        return status_intern.store(data.get("status"))
+    result = array.array("B")
+    expected = data.get("expected")
+    if expected is None:
+        expected = data["status"]
+    result_parts = [data["status"], expected] + data["known_intermittent"]
+    for i, part in enumerate(result_parts):
+        value = status_intern.store(part)
+        if i % 2 == 0:
+            assert value < 16
+            result.append(value << 4)
+        else:
+            result[-1] += value
+    return result
+
+
+def unpack_result(data):
+    if isinstance(data, int):
+        return (status_intern.get(data), None)
+    if isinstance(data, text_type):
+        return (data, None)
+    # Unpack multiple statuses into a tuple to be used in the Results named tuple below,
+    # separating `status` and `known_intermittent`.
+    results = []
+    for packed_value in data:
+        first = status_intern.get(packed_value >> 4)
+        second = status_intern.get(packed_value & 0x0F)
+        results.append(first)
+        if second:
+            results.append(second)
+    return ((results[0],), tuple(results[1:]))
+
+
+def load_test_data(test_paths):
+    manifest_loader = testloader.ManifestLoader(test_paths, False)
+    manifests = manifest_loader.load()
+
+    id_test_map = {}
+    for test_manifest, paths in iteritems(manifests):
+        id_test_map.update(create_test_tree(paths["metadata_path"],
+                                            test_manifest))
+    return id_test_map
+
+
+def update_from_logs(id_test_map, update_properties, disable_intermittent, update_intermittent,
+                     remove_intermittent, full_update, *log_filenames):
+
+    updater = ExpectedUpdater(id_test_map)
+
+    for i, log_filename in enumerate(log_filenames):
+        print("Processing log %d/%d" % (i + 1, len(log_filenames)))
+        with open(log_filename) as f:
+            updater.update_from_log(f)
+
+    for item in update_results(id_test_map, update_properties, full_update,
+                               disable_intermittent, update_intermittent=update_intermittent,
+                               remove_intermittent=remove_intermittent):
+        yield item
+
+
+def update_results(id_test_map,
+                   update_properties,
+                   full_update,
+                   disable_intermittent,
+                   update_intermittent,
+                   remove_intermittent):
+    test_file_items = set(itervalues(id_test_map))
+
+    default_expected_by_type = {}
+    for test_type, test_cls in iteritems(wpttest.manifest_test_cls):
+        if test_cls.result_cls:
+            default_expected_by_type[(test_type, False)] = test_cls.result_cls.default_expected
+        if test_cls.subtest_result_cls:
+            default_expected_by_type[(test_type, True)] = test_cls.subtest_result_cls.default_expected
+
+    for test_file in test_file_items:
+        updated_expected = test_file.update(default_expected_by_type, update_properties,
+                                            full_update, disable_intermittent, update_intermittent,
+                                            remove_intermittent)
+        if updated_expected is not None and updated_expected.modified:
+            yield test_file.metadata_path, updated_expected
+
+
+def directory_manifests(metadata_path):
+    rv = []
+    for dirpath, dirname, filenames in os.walk(metadata_path):
+        if "__dir__.ini" in filenames:
+            rel_path = os.path.relpath(dirpath, metadata_path)
+            rv.append(os.path.join(rel_path, "__dir__.ini"))
+    return rv
+
+
+def write_new_expected(metadata_path, expected):
+    # Serialize the data back to a file
+    path = expected_path(metadata_path, expected.test_path)
+    if not expected.is_empty:
+        manifest_str = wptmanifest.serialize(expected.node,
+                                             skip_empty_data=True)
+        assert manifest_str != ""
+        dir = os.path.dirname(path)
+        if not os.path.exists(dir):
+            os.makedirs(dir)
+        tmp_path = path + ".tmp"
+        try:
+            with open(tmp_path, "wb") as f:
+                f.write(manifest_str.encode("utf8"))
+            if sys.version_info >= (3, 3):
+                os.replace(tmp_path, path)
+            else:
+                os.rename(tmp_path, path)
+        except (Exception, KeyboardInterrupt):
+            try:
+                os.unlink(tmp_path)
+            except OSError:
+                pass
+    else:
+        try:
+            os.unlink(path)
+        except OSError:
+            pass
+
+
+class ExpectedUpdater(object):
+    def __init__(self, id_test_map):
+        self.id_test_map = id_test_map
+        self.run_info = None
+        self.action_map = {"suite_start": self.suite_start,
+                           "test_start": self.test_start,
+                           "test_status": self.test_status,
+                           "test_end": self.test_end,
+                           "assertion_count": self.assertion_count,
+                           "lsan_leak": self.lsan_leak,
+                           "mozleak_object": self.mozleak_object,
+                           "mozleak_total": self.mozleak_total}
+        self.tests_visited = {}
+
+    def update_from_log(self, log_file):
+        # We support three possible formats:
+        # * wptreport format; one json object in the file, possibly pretty-printed
+        # * wptreport format; one run per line
+        # * raw log format
+
+        # Try reading a single json object in wptreport format
+        self.run_info = None
+        success = self.get_wptreport_data(log_file.read())
+
+        if success:
+            return
+
+        # Try line-separated json objects in wptreport format
+        log_file.seek(0)
+        for line in log_file:
+            success = self.get_wptreport_data(line)
+            if not success:
+                break
+        else:
+            return
+
+        # Assume the file is a raw log
+        log_file.seek(0)
+        self.update_from_raw_log(log_file)
+
+    def get_wptreport_data(self, input_str):
+        try:
+            data = json.loads(input_str)
+        except Exception:
+            pass
+        else:
+            if "action" not in data and "results" in data:
+                self.update_from_wptreport_log(data)
+                return True
+        return False
+
+    def update_from_raw_log(self, log_file):
+        action_map = self.action_map
+        for line in log_file:
+            try:
+                data = json.loads(line)
+            except ValueError:
+                # Just skip lines that aren't json
+                continue
+            action = data["action"]
+            if action in action_map:
+                action_map[action](data)
+
+    def update_from_wptreport_log(self, data):
+        action_map = self.action_map
+        action_map["suite_start"]({"run_info": data["run_info"]})
+        for test in data["results"]:
+            action_map["test_start"]({"test": test["test"]})
+            for subtest in test["subtests"]:
+                action_map["test_status"]({"test": test["test"],
+                                           "subtest": subtest["name"],
+                                           "status": subtest["status"],
+                                           "expected": subtest.get("expected"),
+                                           "known_intermittent": subtest.get("known_intermittent", [])})
+            action_map["test_end"]({"test": test["test"],
+                                    "status": test["status"],
+                                    "expected": test.get("expected"),
+                                    "known_intermittent": test.get("known_intermittent", [])})
+            if "asserts" in test:
+                asserts = test["asserts"]
+                action_map["assertion_count"]({"test": test["test"],
+                                               "count": asserts["count"],
+                                               "min_expected": asserts["min"],
+                                               "max_expected": asserts["max"]})
+        for item in data.get("lsan_leaks", []):
+            action_map["lsan_leak"](item)
+
+        mozleak_data = data.get("mozleak", {})
+        for scope, scope_data in iteritems(mozleak_data):
+            for key, action in [("objects", "mozleak_object"),
+                                ("total", "mozleak_total")]:
+                for item in scope_data.get(key, []):
+                    item_data = {"scope": scope}
+                    item_data.update(item)
+                    action_map[action](item_data)
+
+    def suite_start(self, data):
+        self.run_info = run_info_intern.store(RunInfo(data["run_info"]))
+
+    def test_start(self, data):
+        test_id = intern(ensure_str(data["test"]))
+        try:
+            self.id_test_map[test_id]
+        except KeyError:
+            print("Test not found %s, skipping" % test_id)
+            return
+
+        self.tests_visited[test_id] = set()
+
+    def test_status(self, data):
+        test_id = intern(ensure_str(data["test"]))
+        subtest = intern(ensure_str(data["subtest"]))
+        test_data = self.id_test_map.get(test_id)
+        if test_data is None:
+            return
+
+        self.tests_visited[test_id].add(subtest)
+
+        result = pack_result(data)
+
+        test_data.set(test_id, subtest, "status", self.run_info, result)
+        if data.get("expected") and data["expected"] != data["status"]:
+            test_data.set_requires_update()
+
+    def test_end(self, data):
+        if data["status"] == "SKIP":
+            return
+
+        test_id = intern(ensure_str(data["test"]))
+        test_data = self.id_test_map.get(test_id)
+        if test_data is None:
+            return
+
+        result = pack_result(data)
+
+        test_data.set(test_id, None, "status", self.run_info, result)
+        if data.get("expected") and data["expected"] != data["status"]:
+            test_data.set_requires_update()
+        del self.tests_visited[test_id]
+
+    def assertion_count(self, data):
+        test_id = intern(ensure_str(data["test"]))
+        test_data = self.id_test_map.get(test_id)
+        if test_data is None:
+            return
+
+        test_data.set(test_id, None, "asserts", self.run_info, data["count"])
+        if data["count"] < data["min_expected"] or data["count"] > data["max_expected"]:
+            test_data.set_requires_update()
+
+    def test_for_scope(self, data):
+        dir_path = data.get("scope", "/")
+        dir_id = intern(ensure_str(os.path.join(dir_path, "__dir__").replace(os.path.sep, "/")))
+        if dir_id.startswith("/"):
+            dir_id = dir_id[1:]
+        return dir_id, self.id_test_map[dir_id]
+
+    def lsan_leak(self, data):
+        if data["scope"] == "/":
+            logger.warning("Not updating lsan annotations for root scope")
+            return
+        dir_id, test_data = self.test_for_scope(data)
+        test_data.set(dir_id, None, "lsan",
+                      self.run_info, (data["frames"], data.get("allowed_match")))
+        if not data.get("allowed_match"):
+            test_data.set_requires_update()
+
+    def mozleak_object(self, data):
+        if data["scope"] == "/":
+            logger.warning("Not updating mozleak annotations for root scope")
+            return
+        dir_id, test_data = self.test_for_scope(data)
+        test_data.set(dir_id, None, "leak-object",
+                      self.run_info, ("%s:%s", (data["process"], data["name"]),
+                                      data.get("allowed")))
+        if not data.get("allowed"):
+            test_data.set_requires_update()
+
+    def mozleak_total(self, data):
+        if data["scope"] == "/":
+            logger.warning("Not updating mozleak annotations for root scope")
+            return
+        if data["bytes"]:
+            dir_id, test_data = self.test_for_scope(data)
+            test_data.set(dir_id, None, "leak-threshold",
+                          self.run_info, (data["process"], data["bytes"], data["threshold"]))
+            if data["bytes"] > data["threshold"] or data["bytes"] < 0:
+                test_data.set_requires_update()
+
+
+def create_test_tree(metadata_path, test_manifest):
+    """Create a map of test_id to TestFileData for that test.
+    """
+    do_delayed_imports()
+    id_test_map = {}
+    exclude_types = frozenset(["manual", "support", "conformancechecker"])
+    all_types = set(manifestitem.item_types.keys())
+    assert all_types > exclude_types
+    include_types = all_types - exclude_types
+    for item_type, test_path, tests in test_manifest.itertypes(*include_types):
+        test_file_data = TestFileData(intern(ensure_str(test_manifest.url_base)),
+                                      intern(ensure_str(item_type)),
+                                      metadata_path,
+                                      test_path,
+                                      tests)
+        for test in tests:
+            id_test_map[intern(ensure_str(test.id))] = test_file_data
+
+        dir_path = os.path.dirname(test_path)
+        while True:
+            dir_meta_path = os.path.join(dir_path, "__dir__")
+            dir_id = (test_manifest.url_base + dir_meta_path.replace(os.path.sep, "/")).lstrip("/")
+            if dir_id in id_test_map:
+                break
+
+            test_file_data = TestFileData(intern(ensure_str(test_manifest.url_base)),
+                                          None,
+                                          metadata_path,
+                                          dir_meta_path,
+                                          [])
+            id_test_map[dir_id] = test_file_data
+            dir_path = os.path.dirname(dir_path)
+            if not dir_path:
+                break
+
+    return id_test_map
+
+
+class PackedResultList(object):
+    """Class for storing test results.
+
+    Results are stored as an array of 2-byte integers for compactness.
+    The first 4 bits represent the property name, the second 4 bits
+    represent the test status (if it's a result with a status code), and
+    the final 8 bits represent the run_info. If the result doesn't have a
+    simple status code but instead a richer type, we place that richer type
+    in a dictionary and set the status part of the result type to 0.
+
+    This class depends on the global prop_intern, run_info_intern and
+    status_intern InteredData objects to convert between the bit values
+    and corresponding Python objects."""
+
+    def __init__(self):
+        self.data = array.array("H")
+
+    __slots__ = ("data", "raw_data")
+
+    def append(self, prop, run_info, value):
+        out_val = (prop << 12) + run_info
+        if prop == prop_intern.store("status") and isinstance(value, int):
+            out_val += value << 8
+        else:
+            if not hasattr(self, "raw_data"):
+                self.raw_data = {}
+            self.raw_data[len(self.data)] = value
+        self.data.append(out_val)
+
+    def unpack(self, idx, packed):
+        prop = prop_intern.get((packed & 0xF000) >> 12)
+
+        value_idx = (packed & 0x0F00) >> 8
+        if value_idx == 0:
+            value = self.raw_data[idx]
+        else:
+            value = status_intern.get(value_idx)
+
+        run_info = run_info_intern.get(packed & 0x00FF)
+
+        return prop, run_info, value
+
+    def __iter__(self):
+        for i, item in enumerate(self.data):
+            yield self.unpack(i, item)
+
+
+class TestFileData(object):
+    __slots__ = ("url_base", "item_type", "test_path", "metadata_path", "tests",
+                 "_requires_update", "data")
+
+    def __init__(self, url_base, item_type, metadata_path, test_path, tests):
+        self.url_base = url_base
+        self.item_type = item_type
+        self.test_path = test_path
+        self.metadata_path = metadata_path
+        self.tests = {intern(ensure_str(item.id)) for item in tests}
+        self._requires_update = False
+        self.data = defaultdict(lambda: defaultdict(PackedResultList))
+
+    def set_requires_update(self):
+        self._requires_update = True
+
+    @property
+    def requires_update(self):
+        return self._requires_update
+
+    def set(self, test_id, subtest_id, prop, run_info, value):
+        self.data[test_id][subtest_id].append(prop_intern.store(prop),
+                                              run_info,
+                                              value)
+
+    def expected(self, update_properties, update_intermittent, remove_intermittent):
+        expected_data = load_expected(self.url_base,
+                                      self.metadata_path,
+                                      self.test_path,
+                                      self.tests,
+                                      update_properties,
+                                      update_intermittent,
+                                      remove_intermittent)
+        if expected_data is None:
+            expected_data = create_expected(self.url_base,
+                                            self.test_path,
+                                            update_properties,
+                                            update_intermittent,
+                                            remove_intermittent)
+        return expected_data
+
+    def is_disabled(self, test):
+        # This conservatively assumes that anything that was disabled remains disabled
+        # we could probably do better by checking if it's in the full set of run infos
+        return test.has_key("disabled")
+
+    def orphan_subtests(self, expected):
+        # Return subtest nodes present in the expected file, but missing from the data
+        rv = []
+
+        for test_id, subtests in iteritems(self.data):
+            test = expected.get_test(ensure_text(test_id))
+            if not test:
+                continue
+            seen_subtests = set(ensure_text(item) for item in iterkeys(subtests) if item is not None)
+            missing_subtests = set(test.subtests.keys()) - seen_subtests
+            for item in missing_subtests:
+                expected_subtest = test.get_subtest(item)
+                if not self.is_disabled(expected_subtest):
+                    rv.append(expected_subtest)
+            for name in seen_subtests:
+                subtest = test.get_subtest(name)
+                # If any of the items have children (ie subsubtests) we want to prune thes
+                if subtest.children:
+                    rv.extend(subtest.children)
+
+        return rv
+
+    def filter_unknown_props(self, update_properties, subtests):
+        # Remove subtests which have some conditions that aren't in update_properties
+        # since removing these may be inappropriate
+        top_level_props, dependent_props = update_properties
+        all_properties = set(top_level_props)
+        for item in itervalues(dependent_props):
+            all_properties |= set(item)
+
+        filtered = []
+        for subtest in subtests:
+            include = True
+            for key, _ in subtest.iter_properties():
+                conditions = subtest.get_conditions(key)
+                for condition in conditions:
+                    if not condition.variables.issubset(all_properties):
+                        include = False
+                        break
+                if not include:
+                    break
+            if include:
+                filtered.append(subtest)
+        return filtered
+
+    def update(self, default_expected_by_type, update_properties,
+               full_update=False, disable_intermittent=None, update_intermittent=False,
+               remove_intermittent=False):
+        # If we are doing a full update, we may need to prune missing nodes
+        # even if the expectations didn't change
+        if not self.requires_update and not full_update:
+            return
+
+        expected = self.expected(update_properties,
+                                 update_intermittent=update_intermittent,
+                                 remove_intermittent=remove_intermittent)
+
+        if full_update:
+            orphans = self.orphan_subtests(expected)
+            orphans = self.filter_unknown_props(update_properties, orphans)
+
+            if not self.requires_update and not orphans:
+                return
+
+            if orphans:
+                expected.modified = True
+                for item in orphans:
+                    item.remove()
+
+        expected_by_test = {}
+
+        for test_id in self.tests:
+            if not expected.has_test(test_id):
+                expected.append(manifestupdate.TestNode.create(test_id))
+            test_expected = expected.get_test(test_id)
+            expected_by_test[test_id] = test_expected
+
+        for test_id, test_data in iteritems(self.data):
+            test_id = ensure_str(test_id)
+            for subtest_id, results_list in iteritems(test_data):
+                for prop, run_info, value in results_list:
+                    # Special case directory metadata
+                    if subtest_id is None and test_id.endswith("__dir__"):
+                        if prop == "lsan":
+                            expected.set_lsan(run_info, value)
+                        elif prop == "leak-object":
+                            expected.set_leak_object(run_info, value)
+                        elif prop == "leak-threshold":
+                            expected.set_leak_threshold(run_info, value)
+                        continue
+
+                    test_expected = expected_by_test[test_id]
+                    if subtest_id is None:
+                        item_expected = test_expected
+                    else:
+                        subtest_id = ensure_text(subtest_id)
+                        item_expected = test_expected.get_subtest(subtest_id)
+
+                    if prop == "status":
+                        status, known_intermittent = unpack_result(value)
+                        value = Result(status,
+                                       known_intermittent,
+                                       default_expected_by_type[self.item_type,
+                                                                subtest_id is not None])
+                        item_expected.set_result(run_info, value)
+                    elif prop == "asserts":
+                        item_expected.set_asserts(run_info, value)
+
+        expected.update(full_update=full_update,
+                        disable_intermittent=disable_intermittent)
+        for test in expected.iterchildren():
+            for subtest in test.iterchildren():
+                subtest.update(full_update=full_update,
+                               disable_intermittent=disable_intermittent)
+            test.update(full_update=full_update,
+                        disable_intermittent=disable_intermittent)
+
+        return expected
+
+
+Result = namedtuple("Result", ["status", "known_intermittent", "default_expected"])
+
+
+def create_expected(url_base, test_path, run_info_properties, update_intermittent, remove_intermittent):
+    expected = manifestupdate.ExpectedManifest(None,
+                                               test_path,
+                                               url_base,
+                                               run_info_properties,
+                                               update_intermittent,
+                                               remove_intermittent)
+    return expected
+
+
+def load_expected(url_base, metadata_path, test_path, tests, run_info_properties, update_intermittent, remove_intermittent):
+    expected_manifest = manifestupdate.get_manifest(metadata_path,
+                                                    test_path,
+                                                    url_base,
+                                                    run_info_properties,
+                                                    update_intermittent,
+                                                    remove_intermittent)
+    return expected_manifest
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/mpcontext.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/mpcontext.py
new file mode 100644
index 0000000..daade10
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/mpcontext.py
@@ -0,0 +1,21 @@
+import multiprocessing
+
+import six
+
+_context = None
+
+
+class MpContext(object):
+    def __getattr__(self, name):
+        return getattr(multiprocessing, name)
+
+
+def get_context():
+    global _context
+
+    if _context is None:
+        if six.PY2:
+            _context = MpContext()
+        else:
+            _context = multiprocessing.get_context("spawn")
+    return _context
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/print_reftest_runner.html b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/print_reftest_runner.html
new file mode 100644
index 0000000..3ce18d4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/print_reftest_runner.html
@@ -0,0 +1,33 @@
+<!doctype html>
+<title></title>
+<script src="/_pdf_js/pdf.js"></script>
+<canvas></canvas>
+<script>
+function render(pdfData) {
+  return _render(pdfData);
+}
+
+async function _render(pdfData) {
+  let loadingTask = pdfjsLib.getDocument({data: atob(pdfData)});
+  let pdf = await loadingTask.promise;
+  let rendered = [];
+  for (let pageNumber=1; pageNumber<=pdf.numPages; pageNumber++) {
+    let page = await pdf.getPage(pageNumber);
+    var viewport = page.getViewport({scale: 96./72.});
+    // Prepare canvas using PDF page dimensions
+    var canvas = document.getElementsByTagName('canvas')[0];
+    var context = canvas.getContext('2d');
+    canvas.height = viewport.height;
+    canvas.width = viewport.width;
+
+    // Render PDF page into canvas context
+    var renderContext = {
+      canvasContext: context,
+      viewport: viewport
+    };
+    await page.render(renderContext).promise;
+    rendered.push(canvas.toDataURL());
+  }
+  return rendered;
+}
+</script>
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/process.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/process.py
new file mode 100644
index 0000000..8a2b894
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/process.py
@@ -0,0 +1,11 @@
+import sys
+
+import six
+
+
+def cast_env(env):
+    """Encode all the environment values as the appropriate type for each Python version
+    This assumes that all the data is or can be represented as UTF8"""
+
+    env_type = six.ensure_binary if sys.version_info[0] < 3 else six.ensure_str
+    return {env_type(key): env_type(value) for key, value in six.iteritems(env)}
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/products.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/products.py
new file mode 100644
index 0000000..abd8409
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/products.py
@@ -0,0 +1,79 @@
+import importlib
+import imp
+from six import iteritems
+
+from .browsers import product_list
+
+
+def products_enabled(config):
+    names = config.get("products", {}).keys()
+    if not names:
+        return product_list
+    else:
+        return names
+
+
+def product_module(config, product):
+    if product not in products_enabled(config):
+        raise ValueError("Unknown product %s" % product)
+
+    path = config.get("products", {}).get(product, None)
+    if path:
+        module = imp.load_source('wptrunner.browsers.' + product, path)
+    else:
+        module = importlib.import_module("wptrunner.browsers." + product)
+
+    if not hasattr(module, "__wptrunner__"):
+        raise ValueError("Product module does not define __wptrunner__ variable")
+
+    return module
+
+
+class Product(object):
+    def __init__(self, config, product):
+        module = product_module(config, product)
+        data = module.__wptrunner__
+        self.name = product
+        self.check_args = getattr(module, data["check_args"])
+        self.browser_cls = getattr(module, data["browser"])
+        self.get_browser_kwargs = getattr(module, data["browser_kwargs"])
+        self.get_executor_kwargs = getattr(module, data["executor_kwargs"])
+        self.env_options = getattr(module, data["env_options"])()
+        self.get_env_extras = getattr(module, data["env_extras"])
+        self.run_info_extras = (getattr(module, data["run_info_extras"])
+                           if "run_info_extras" in data else lambda **kwargs:{})
+        self.get_timeout_multiplier = getattr(module, data["timeout_multiplier"])
+
+        self.executor_classes = {}
+        for test_type, cls_name in iteritems(data["executor"]):
+            cls = getattr(module, cls_name)
+            self.executor_classes[test_type] = cls
+
+
+def load_product(config, product, load_cls=False):
+    rv = Product(config, product)
+    if not load_cls:
+        return (rv.check_args,
+                rv.browser_cls,
+                rv.get_browser_kwargs,
+                rv.executor_classes,
+                rv.get_executor_kwargs,
+                rv.env_options,
+                rv.get_env_extras,
+                rv.run_info_extras)
+    return rv
+
+
+def load_product_update(config, product):
+    """Return tuple of (property_order, boolean_properties) indicating the
+    run_info properties to use when constructing the expectation data for
+    this product. None for either key indicates that the default keys
+    appropriate for distinguishing based on platform will be used."""
+
+    module = product_module(config, product)
+    data = module.__wptrunner__
+
+    update_properties = (getattr(module, data["update_properties"])()
+                         if "update_properties" in data else {})
+
+    return update_properties
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/stability.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/stability.py
new file mode 100644
index 0000000..88d1c23
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/stability.py
@@ -0,0 +1,384 @@
+import copy
+import functools
+import imp
+import io
+import os
+from collections import OrderedDict, defaultdict
+from datetime import datetime
+from six import iteritems
+
+from mozlog import reader
+from mozlog.formatters import JSONFormatter
+from mozlog.handlers import BaseHandler, StreamHandler, LogLevelFilter
+
+here = os.path.dirname(__file__)
+localpaths = imp.load_source("localpaths", os.path.abspath(os.path.join(here, os.pardir, os.pardir, "localpaths.py")))
+from ci.tc.github_checks_output import get_gh_checks_outputter
+from wpt.markdown import markdown_adjust, table
+
+
+# If a test takes more than (FLAKY_THRESHOLD*timeout) and does not consistently
+# time out, it is considered slow (potentially flaky).
+FLAKY_THRESHOLD = 0.8
+
+
+class LogActionFilter(BaseHandler):
+
+    """Handler that filters out messages not of a given set of actions.
+
+    Subclasses BaseHandler.
+
+    :param inner: Handler to use for messages that pass this filter
+    :param actions: List of actions for which to fire the handler
+    """
+
+    def __init__(self, inner, actions):
+        """Extend BaseHandler and set inner and actions props on self."""
+        BaseHandler.__init__(self, inner)
+        self.inner = inner
+        self.actions = actions
+
+    def __call__(self, item):
+        """Invoke handler if action is in list passed as constructor param."""
+        if item["action"] in self.actions:
+            return self.inner(item)
+
+
+class LogHandler(reader.LogHandler):
+
+    """Handle updating test and subtest status in log.
+
+    Subclasses reader.LogHandler.
+    """
+    def __init__(self):
+        self.results = OrderedDict()
+
+    def find_or_create_test(self, data):
+        test_name = data["test"]
+        if self.results.get(test_name):
+            return self.results[test_name]
+
+        test = {
+            "subtests": OrderedDict(),
+            "status": defaultdict(int),
+            "longest_duration": defaultdict(float),
+        }
+        self.results[test_name] = test
+        return test
+
+    def find_or_create_subtest(self, data):
+        test = self.find_or_create_test(data)
+        subtest_name = data["subtest"]
+
+        if test["subtests"].get(subtest_name):
+            return test["subtests"][subtest_name]
+
+        subtest = {
+            "status": defaultdict(int),
+            "messages": set()
+        }
+        test["subtests"][subtest_name] = subtest
+
+        return subtest
+
+    def test_start(self, data):
+        test = self.find_or_create_test(data)
+        test["start_time"] = data["time"]
+
+    def test_status(self, data):
+        subtest = self.find_or_create_subtest(data)
+        subtest["status"][data["status"]] += 1
+        if data.get("message"):
+            subtest["messages"].add(data["message"])
+
+    def test_end(self, data):
+        test = self.find_or_create_test(data)
+        test["status"][data["status"]] += 1
+        # Timestamps are in ms since epoch.
+        duration = data["time"] - test.pop("start_time")
+        test["longest_duration"][data["status"]] = max(
+            duration, test["longest_duration"][data["status"]])
+        try:
+            # test_timeout is in seconds; convert it to ms.
+            test["timeout"] = data["extra"]["test_timeout"] * 1000
+        except KeyError:
+            # If a test is skipped, it won't have extra info.
+            pass
+
+
+def is_inconsistent(results_dict, iterations):
+    """Return whether or not a single test is inconsistent."""
+    if 'SKIP' in results_dict:
+        return False
+    return len(results_dict) > 1 or sum(results_dict.values()) != iterations
+
+
+def find_slow_status(test):
+    """Check if a single test almost times out.
+
+    We are interested in tests that almost time out (i.e. likely to be flaky).
+    Therefore, timeout statuses are ignored, including (EXTERNAL-)TIMEOUT.
+    CRASH & ERROR are also ignored because the they override TIMEOUT; a test
+    that both crashes and times out is marked as CRASH, so it won't be flaky.
+
+    Returns:
+        A result status produced by a run that almost times out; None, if no
+        runs almost time out.
+    """
+    if "timeout" not in test:
+        return None
+    threshold = test["timeout"] * FLAKY_THRESHOLD
+    for status in ['PASS', 'FAIL', 'OK']:
+        if (status in test["longest_duration"] and
+            test["longest_duration"][status] > threshold):
+            return status
+    return None
+
+
+def process_results(log, iterations):
+    """Process test log and return overall results and list of inconsistent tests."""
+    inconsistent = []
+    slow = []
+    handler = LogHandler()
+    reader.handle_log(reader.read(log), handler)
+    results = handler.results
+    for test_name, test in iteritems(results):
+        if is_inconsistent(test["status"], iterations):
+            inconsistent.append((test_name, None, test["status"], []))
+        for subtest_name, subtest in iteritems(test["subtests"]):
+            if is_inconsistent(subtest["status"], iterations):
+                inconsistent.append((test_name, subtest_name, subtest["status"], subtest["messages"]))
+
+        slow_status = find_slow_status(test)
+        if slow_status is not None:
+            slow.append((
+                test_name,
+                slow_status,
+                test["longest_duration"][slow_status],
+                test["timeout"]
+            ))
+
+    return results, inconsistent, slow
+
+
+def err_string(results_dict, iterations):
+    """Create and return string with errors from test run."""
+    rv = []
+    total_results = sum(results_dict.values())
+    if total_results > iterations:
+        rv.append("Duplicate subtest name")
+    else:
+        for key, value in sorted(results_dict.items()):
+            rv.append("%s%s" %
+                      (key, ": %s/%s" % (value, iterations) if value != iterations else ""))
+    if total_results < iterations:
+        rv.append("MISSING: %s/%s" % (iterations - total_results, iterations))
+    rv = ", ".join(rv)
+    if is_inconsistent(results_dict, iterations):
+        rv = "**%s**" % rv
+    return rv
+
+
+def write_github_checks_summary_inconsistent(log, inconsistent, iterations):
+    """Outputs a summary of inconsistent tests for GitHub Checks."""
+    log("Some affected tests had inconsistent (flaky) results:\n")
+    write_inconsistent(log, inconsistent, iterations)
+    log("\n")
+    log("These may be pre-existing or new flakes. Please try to reproduce (see "
+        "the above WPT command, though some flags may not be needed when "
+        "running locally) and determine if your change introduced the flake. "
+        "If you are unable to reproduce the problem, please tag "
+        "`@web-platform-tests/wpt-core-team` in a comment for help.\n")
+
+
+def write_github_checks_summary_slow_tests(log, slow):
+    """Outputs a summary of slow tests for GitHub Checks."""
+    log("Some affected tests had slow results:\n")
+    write_slow_tests(log, slow)
+    log("\n")
+    log("These may be pre-existing or newly slow tests. Slow tests indicate "
+        "that a test ran very close to the test timeout limit and so may "
+        "become TIMEOUT-flaky in the future. Consider speeding up the test or "
+        "breaking it into multiple tests. For help, please tag "
+        "`@web-platform-tests/wpt-core-team` in a comment.\n")
+
+
+def write_inconsistent(log, inconsistent, iterations):
+    """Output inconsistent tests to the passed in logging function."""
+    log("## Unstable results ##\n")
+    strings = [(
+        "`%s`" % markdown_adjust(test),
+        ("`%s`" % markdown_adjust(subtest)) if subtest else "",
+        err_string(results, iterations),
+        ("`%s`" % markdown_adjust(";".join(messages))) if len(messages) else "")
+        for test, subtest, results, messages in inconsistent]
+    table(["Test", "Subtest", "Results", "Messages"], strings, log)
+
+
+def write_slow_tests(log, slow):
+    """Output slow tests to the passed in logging function."""
+    log("## Slow tests ##\n")
+    strings = [(
+        "`%s`" % markdown_adjust(test),
+        "`%s`" % status,
+        "`%.0f`" % duration,
+        "`%.0f`" % timeout)
+        for test, status, duration, timeout in slow]
+    table(["Test", "Result", "Longest duration (ms)", "Timeout (ms)"], strings, log)
+
+
+def write_results(log, results, iterations, pr_number=None, use_details=False):
+    log("## All results ##\n")
+    if use_details:
+        log("<details>\n")
+        log("<summary>%i %s ran</summary>\n\n" % (len(results),
+                                                  "tests" if len(results) > 1
+                                                  else "test"))
+
+    for test_name, test in iteritems(results):
+        baseurl = "http://w3c-test.org/submissions"
+        if "https" in os.path.splitext(test_name)[0].split(".")[1:]:
+            baseurl = "https://w3c-test.org/submissions"
+        title = test_name
+        if use_details:
+            log("<details>\n")
+            if pr_number:
+                title = "<a href=\"%s/%s%s\">%s</a>" % (baseurl, pr_number, test_name, title)
+            log('<summary>%s</summary>\n\n' % title)
+        else:
+            log("### %s ###" % title)
+        strings = [("", err_string(test["status"], iterations), "")]
+
+        strings.extend(((
+            ("`%s`" % markdown_adjust(subtest_name)) if subtest else "",
+            err_string(subtest["status"], iterations),
+            ("`%s`" % markdown_adjust(';'.join(subtest["messages"]))) if len(subtest["messages"]) else "")
+            for subtest_name, subtest in test["subtests"].items()))
+        table(["Subtest", "Results", "Messages"], strings, log)
+        if use_details:
+            log("</details>\n")
+
+    if use_details:
+        log("</details>\n")
+
+
+def run_step(logger, iterations, restart_after_iteration, kwargs_extras, **kwargs):
+    from . import wptrunner
+    kwargs = copy.deepcopy(kwargs)
+
+    if restart_after_iteration:
+        kwargs["repeat"] = iterations
+    else:
+        kwargs["rerun"] = iterations
+
+    kwargs["pause_after_test"] = False
+    kwargs.update(kwargs_extras)
+
+    def wrap_handler(x):
+        if not kwargs["verify_log_full"]:
+            x = LogLevelFilter(x, "WARNING")
+            x = LogActionFilter(x, ["log", "process_output"])
+        return x
+
+    initial_handlers = logger._state.handlers
+    logger._state.handlers = [wrap_handler(handler)
+                              for handler in initial_handlers]
+
+    log = io.BytesIO()
+    # Setup logging for wptrunner that keeps process output and
+    # warning+ level logs only
+    logger.add_handler(StreamHandler(log, JSONFormatter()))
+
+    wptrunner.run_tests(**kwargs)
+
+    logger._state.handlers = initial_handlers
+    logger._state.running_tests = set()
+    logger._state.suite_started = False
+
+    log.seek(0)
+    results, inconsistent, slow = process_results(log, iterations)
+    return results, inconsistent, slow, iterations
+
+
+def get_steps(logger, repeat_loop, repeat_restart, kwargs_extras):
+    steps = []
+    for kwargs_extra in kwargs_extras:
+        if kwargs_extra:
+            flags_string = " with flags %s" % " ".join(
+                "%s=%s" % item for item in iteritems(kwargs_extra))
+        else:
+            flags_string = ""
+
+        if repeat_loop:
+            desc = "Running tests in a loop %d times%s" % (repeat_loop,
+                                                           flags_string)
+            steps.append((desc, functools.partial(run_step, logger, repeat_loop, False, kwargs_extra)))
+
+        if repeat_restart:
+            desc = "Running tests in a loop with restarts %s times%s" % (repeat_restart,
+                                                                         flags_string)
+            steps.append((desc, functools.partial(run_step, logger, repeat_restart, True, kwargs_extra)))
+
+    return steps
+
+
+def write_summary(logger, step_results, final_result):
+    for desc, result in step_results:
+        logger.info('::: %s : %s' % (desc, result))
+    logger.info(':::')
+    if final_result == "PASS":
+        log = logger.info
+    elif final_result == "TIMEOUT":
+        log = logger.warning
+    else:
+        log = logger.error
+    log('::: Test verification %s' % final_result)
+
+    logger.info(':::')
+
+def check_stability(logger, repeat_loop=10, repeat_restart=5, chaos_mode=True, max_time=None,
+                    output_results=True, **kwargs):
+    kwargs_extras = [{}]
+    if chaos_mode and kwargs["product"] == "firefox":
+        kwargs_extras.append({"chaos_mode_flags": "0xfb"})
+
+    steps = get_steps(logger, repeat_loop, repeat_restart, kwargs_extras)
+
+    start_time = datetime.now()
+    step_results = []
+
+    github_checks_outputter = get_gh_checks_outputter(kwargs["github_checks_text_file"])
+
+    for desc, step_func in steps:
+        if max_time and datetime.now() - start_time > max_time:
+            logger.info("::: Test verification is taking too long: Giving up!")
+            logger.info("::: So far, all checks passed, but not all checks were run.")
+            write_summary(logger, step_results, "TIMEOUT")
+            return 2
+
+        logger.info(':::')
+        logger.info('::: Running test verification step "%s"...' % desc)
+        logger.info(':::')
+        results, inconsistent, slow, iterations = step_func(**kwargs)
+        if output_results:
+            write_results(logger.info, results, iterations)
+
+        if inconsistent:
+            step_results.append((desc, "FAIL"))
+            if github_checks_outputter:
+                write_github_checks_summary_inconsistent(github_checks_outputter.output, inconsistent, iterations)
+            write_inconsistent(logger.info, inconsistent, iterations)
+            write_summary(logger, step_results, "FAIL")
+            return 1
+
+        if slow:
+            step_results.append((desc, "FAIL"))
+            if github_checks_outputter:
+                write_github_checks_summary_slow_tests(github_checks_outputter.output, slow)
+            write_slow_tests(logger.info, slow)
+            write_summary(logger, step_results, "FAIL")
+            return 1
+
+        step_results.append((desc, "PASS"))
+
+    write_summary(logger, step_results, "PASS")
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-extra.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-extra.js
new file mode 100644
index 0000000..e15652d
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-extra.js
@@ -0,0 +1,236 @@
+"use strict";
+
+(function() {
+    const is_test_context = window.__wptrunner_message_queue !== undefined;
+    const pending = new Map();
+
+    let result = null;
+    let ctx_cmd_id = 0;
+    let testharness_context = null;
+
+    window.addEventListener("message", function(event) {
+        const data = event.data;
+
+        if (typeof data !== "object" && data !== null) {
+            return;
+        }
+
+        if (is_test_context && data.type === "testdriver-command") {
+            const command = data.message;
+            const ctx_id = command.cmd_id;
+            delete command.cmd_id;
+            const cmd_id = window.__wptrunner_message_queue.push(command);
+            let on_success = (data) => {
+                data.type = "testdriver-complete";
+                data.cmd_id = ctx_id;
+                event.source.postMessage(data, "*");
+            };
+            let on_failure = (data) => {
+                data.type = "testdriver-complete";
+                data.cmd_id = ctx_id;
+                event.source.postMessage(data, "*");
+            };
+            pending.set(cmd_id, [on_success, on_failure]);
+        } else if (data.type === "testdriver-complete") {
+            const cmd_id = data.cmd_id;
+            const [on_success, on_failure] = pending.get(cmd_id);
+            pending.delete(cmd_id);
+            const resolver = data.status === "success" ? on_success : on_failure;
+            resolver(data);
+            if (is_test_context) {
+                window.__wptrunner_process_next_event();
+            }
+        }
+    });
+
+    // Code copied from /common/utils.js
+    function rand_int(bits) {
+        if (bits < 1 || bits > 53) {
+            throw new TypeError();
+        } else {
+            if (bits >= 1 && bits <= 30) {
+                return 0 | ((1 << bits) * Math.random());
+            } else {
+                var high = (0 | ((1 << (bits - 30)) * Math.random())) * (1 << 30);
+                var low = 0 | ((1 << 30) * Math.random());
+                return  high + low;
+            }
+        }
+    }
+
+    function to_hex(x, length) {
+        var rv = x.toString(16);
+        while (rv.length < length) {
+            rv = "0" + rv;
+        }
+        return rv;
+    }
+
+    function get_window_id(win) {
+        if (win == window && is_test_context) {
+            return null;
+        }
+        if (!win.__wptrunner_id) {
+            // generate a uuid
+            win.__wptrunner_id = [to_hex(rand_int(32), 8),
+                                  to_hex(rand_int(16), 4),
+                                  to_hex(0x4000 | rand_int(12), 4),
+                                  to_hex(0x8000 | rand_int(14), 4),
+                                  to_hex(rand_int(48), 12)].join("-");
+        }
+        return win.__wptrunner_id;
+    }
+
+    const get_context = function(element) {
+        if (!element) {
+            return null;
+        }
+        let elementWindow = element.ownerDocument.defaultView;
+        if (!elementWindow) {
+            throw new Error("Browsing context for element was detached");
+        }
+        return elementWindow;
+    };
+
+    const get_selector = function(element) {
+        let selector;
+
+        if (element.id) {
+            const id = element.id;
+
+            selector = "#";
+            // escape everything, because it's easy to implement
+            for (let i = 0, len = id.length; i < len; i++) {
+                selector += '\\' + id.charCodeAt(i).toString(16) + ' ';
+            }
+        } else {
+            // push and then reverse to avoid O(n) unshift in the loop
+            let segments = [];
+            for (let node = element;
+                 node.parentElement;
+                 node = node.parentElement) {
+                let segment = "*|" + node.localName;
+                let nth = Array.prototype.indexOf.call(node.parentElement.children, node) + 1;
+                segments.push(segment + ":nth-child(" + nth + ")");
+            }
+            segments.push(":root");
+            segments.reverse();
+
+            selector = segments.join(" > ");
+        }
+
+        return selector;
+    };
+
+    const create_action = function(name, props) {
+        let cmd_id;
+        const action_msg = {type: "action",
+                            action: name,
+                            ...props};
+        if (action_msg.context) {
+          action_msg.context = get_window_id(action_msg.context);
+        }
+        if (is_test_context) {
+            cmd_id = window.__wptrunner_message_queue.push(action_msg);
+        } else {
+            if (testharness_context === null) {
+                throw new Error("Tried to run in a non-testharness window without a call to set_test_context");
+            }
+            cmd_id = ctx_cmd_id++;
+            action_msg.cmd_id = cmd_id;
+            window.test_driver.message_test({type: "testdriver-command",
+                                             message: action_msg});
+        }
+        const pending_promise = new Promise(function(resolve, reject) {
+            const on_success = data => {
+                result = JSON.parse(data.message).result;
+                resolve(result);
+            };
+            const on_failure = data => {
+                reject(`${data.status}: ${data.message}`);
+            };
+            pending.set(cmd_id, [on_success, on_failure]);
+        });
+        return pending_promise;
+    };
+
+    window.test_driver_internal.in_automation = true;
+
+    window.test_driver_internal.set_test_context = function(context) {
+        if (window.__wptrunner_message_queue) {
+            throw new Error("Tried to set testharness context in a window containing testharness.js");
+        }
+        testharness_context = context;
+    };
+
+    window.test_driver_internal.click = function(element) {
+        const selector = get_selector(element);
+        const context = get_context(element);
+        return create_action("click", {selector, context});
+    };
+
+    window.test_driver_internal.delete_all_cookies = function(context=null) {
+        return create_action("delete_all_cookies", {context});
+    };
+
+    window.test_driver_internal.send_keys = function(element, keys) {
+        const selector = get_selector(element);
+        const context = get_context(element);
+        return create_action("send_keys", {selector, keys, context});
+    };
+
+    window.test_driver_internal.action_sequence = function(actions, context=null) {
+        for (let actionSequence of actions) {
+            if (actionSequence.type == "pointer") {
+                for (let action of actionSequence.actions) {
+                    // The origin of each action can only be an element or a string of a value "viewport" or "pointer".
+                    if (action.type == "pointerMove" && typeof(action.origin) != 'string') {
+                        let action_context = get_context(action.origin);
+                        action.origin = {selector: get_selector(action.origin)};
+                        if (context !== null && action_context !== context) {
+                            throw new Error("Actions must be in a single context");
+                        }
+                        context = action_context;
+                    }
+                }
+            }
+        }
+        return create_action("action_sequence", {actions, context});
+    };
+
+    window.test_driver_internal.generate_test_report = function(message, context=null) {
+        return create_action("generate_test_report", {message, context});
+    };
+
+    window.test_driver_internal.set_permission = function(permission_params, context=null) {
+        return create_action("set_permission", {permission_params, context});
+    };
+
+    window.test_driver_internal.add_virtual_authenticator = function(config, context=null) {
+        return create_action("add_virtual_authenticator", {config, context});
+    };
+
+    window.test_driver_internal.remove_virtual_authenticator = function(authenticator_id, context=null) {
+        return create_action("remove_virtual_authenticator", {authenticator_id, context});
+    };
+
+    window.test_driver_internal.add_credential = function(authenticator_id, credential, context=null) {
+        return create_action("add_credential", {authenticator_id, credential, context});
+    };
+
+    window.test_driver_internal.get_credentials = function(authenticator_id, context=null) {
+        return create_action("get_credentials", {authenticator_id, context});
+    };
+
+    window.test_driver_internal.remove_credential = function(authenticator_id, credential_id, context=null) {
+        return create_action("remove_credential", {authenticator_id, credential_id, context});
+    };
+
+    window.test_driver_internal.remove_all_credentials = function(authenticator_id, context=null) {
+        return create_action("remove_all_credentials", {authenticator_id, context});
+    };
+
+    window.test_driver_internal.set_user_verified = function(authenticator_id, uv, context=null) {
+        return create_action("set_user_verified", {authenticator_id, uv, context});
+    };
+})();
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-vendor.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-vendor.js
new file mode 100644
index 0000000..3e88403
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testdriver-vendor.js
@@ -0,0 +1 @@
+// This file intentionally left blank
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharness_runner.html b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharness_runner.html
new file mode 100644
index 0000000..1cc80a2
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharness_runner.html
@@ -0,0 +1,6 @@
+<!doctype html>
+<title></title>
+<script>
+var timeout_multiplier = 1;
+var win = null;
+</script>
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servo.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servo.js
new file mode 100644
index 0000000..a10b69df
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servo.js
@@ -0,0 +1,17 @@
+var props = {output:%(output)d};
+var start_loc = document.createElement('a');
+start_loc.href = location.href;
+setup(props);
+
+add_completion_callback(function (tests, harness_status) {
+    var id = decodeURIComponent(start_loc.pathname) + decodeURIComponent(start_loc.search) + decodeURIComponent(start_loc.hash);
+    console.log("ALERT: RESULT: " + JSON.stringify([
+        id,
+        harness_status.status,
+        harness_status.message,
+        harness_status.stack,
+        tests.map(function(t) {
+            return [t.name, t.status, t.message, t.stack]
+        }),
+    ]));
+});
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js
new file mode 100644
index 0000000..c888413
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport-servodriver.js
@@ -0,0 +1,23 @@
+setup({output:%(output)d});
+
+add_completion_callback(function() {
+    add_completion_callback(function (tests, status) {
+        var subtest_results = tests.map(function(x) {
+            return [x.name, x.status, x.message, x.stack]
+        });
+        var id = location.pathname + location.search + location.hash;
+        var results = JSON.stringify([id,
+                                      status.status,
+                                      status.message,
+                                      status.stack,
+                                      subtest_results]);
+        (function done() {
+            if (window.__wd_results_callback__) {
+                clearTimeout(__wd_results_timer__);
+                __wd_results_callback__(results)
+            } else {
+                setTimeout(done, 20);
+            }
+        })()
+    })
+});
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport.js b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport.js
new file mode 100644
index 0000000..9cd680e1
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testharnessreport.js
@@ -0,0 +1,87 @@
+class MessageQueue {
+  constructor() {
+    this.item_id = 0;
+    this._queue = [];
+  }
+
+  push(item) {
+    let cmd_id = this.item_id++;
+    item.id = cmd_id;
+    this._queue.push(item);
+    __wptrunner_process_next_event();
+    return cmd_id;
+  }
+
+  shift() {
+    return this._queue.shift();
+  }
+}
+
+window.__wptrunner_testdriver_callback = null;
+window.__wptrunner_message_queue = new MessageQueue();
+window.__wptrunner_url = null;
+
+window.__wptrunner_process_next_event = function() {
+  /* This function handles the next testdriver event. The presence of
+     window.testdriver_callback is used as a switch; when that function
+     is present we are able to handle the next event and when is is not
+     present we must wait. Therefore to drive the event processing, this
+     function must be called in two circumstances:
+       * Every time there is a new event that we may be able to handle
+       * Every time we set the callback function
+     This function unsets the callback, so no further testdriver actions
+     will be run until it is reset, which wptrunner does after it has
+     completed handling the current action.
+   */
+
+  if (!window.__wptrunner_testdriver_callback) {
+    return;
+  }
+  var data = window.__wptrunner_message_queue.shift();
+  if (!data) {
+    return;
+  }
+
+  var payload = undefined;
+
+  switch(data.type) {
+  case "complete":
+    var tests = data.tests;
+    var status = data.status;
+
+    var subtest_results = tests.map(function(x) {
+      return [x.name, x.status, x.message, x.stack];
+    });
+    payload = [status.status,
+               status.message,
+               status.stack,
+               subtest_results];
+    clearTimeout(window.__wptrunner_timer);
+    break;
+  case "action":
+    payload = data;
+    break;
+  default:
+    return;
+  }
+  var callback = window.__wptrunner_testdriver_callback;
+  window.__wptrunner_testdriver_callback = null;
+  callback([__wptrunner_url, data.type, payload]);
+};
+
+(function() {
+  var props = {output: %(output)d,
+               timeout_multiplier: %(timeout_multiplier)s,
+               explicit_timeout: %(explicit_timeout)s,
+               message_events: ["completion"]};
+
+  add_completion_callback(function(tests, harness_status) {
+    __wptrunner_message_queue.push({
+      "type": "complete",
+      "tests": tests,
+      "status": harness_status});
+    __wptrunner_process_next_event();
+  });
+  setup(props);
+})();
+
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testloader.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testloader.py
new file mode 100644
index 0000000..e57619b4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testloader.py
@@ -0,0 +1,502 @@
+import hashlib
+import json
+import os
+from six.moves.urllib.parse import urlsplit
+from abc import ABCMeta, abstractmethod
+from six.moves.queue import Empty
+from collections import defaultdict, deque
+from six import ensure_binary, iteritems
+from six.moves import range
+
+from . import manifestinclude
+from . import manifestexpected
+from . import mpcontext
+from . import wpttest
+from mozlog import structured
+
+manifest = None
+manifest_update = None
+download_from_github = None
+
+
+def do_delayed_imports():
+    # This relies on an already loaded module having set the sys.path correctly :(
+    global manifest, manifest_update, download_from_github
+    from manifest import manifest
+    from manifest import update as manifest_update
+    from manifest.download import download_from_github
+
+
+class TestGroupsFile(object):
+    """
+    Mapping object representing {group name: [test ids]}
+    """
+
+    def __init__(self, logger, path):
+        try:
+            with open(path) as f:
+                self._data = json.load(f)
+        except ValueError:
+            logger.critical("test groups file %s not valid json" % path)
+            raise
+
+        self.group_by_test = {}
+        for group, test_ids in iteritems(self._data):
+            for test_id in test_ids:
+                self.group_by_test[test_id] = group
+
+    def __contains__(self, key):
+        return key in self._data
+
+    def __getitem__(self, key):
+        return self._data[key]
+
+
+def update_include_for_groups(test_groups, include):
+    if include is None:
+        # We're just running everything
+        return
+
+    new_include = []
+    for item in include:
+        if item in test_groups:
+            new_include.extend(test_groups[item])
+        else:
+            new_include.append(item)
+    return new_include
+
+
+class TestChunker(object):
+    def __init__(self, total_chunks, chunk_number, **kwargs):
+        self.total_chunks = total_chunks
+        self.chunk_number = chunk_number
+        assert self.chunk_number <= self.total_chunks
+        self.logger = structured.get_default_logger()
+        assert self.logger
+        self.kwargs = kwargs
+
+    def __call__(self, manifest):
+        raise NotImplementedError
+
+
+class Unchunked(TestChunker):
+    def __init__(self, *args, **kwargs):
+        TestChunker.__init__(self, *args, **kwargs)
+        assert self.total_chunks == 1
+
+    def __call__(self, manifest, **kwargs):
+        for item in manifest:
+            yield item
+
+
+class HashChunker(TestChunker):
+    def __call__(self, manifest):
+        chunk_index = self.chunk_number - 1
+        for test_type, test_path, tests in manifest:
+            h = int(hashlib.md5(ensure_binary(test_path)).hexdigest(), 16)
+            if h % self.total_chunks == chunk_index:
+                yield test_type, test_path, tests
+
+
+class DirectoryHashChunker(TestChunker):
+    """Like HashChunker except the directory is hashed.
+
+    This ensures that all tests in the same directory end up in the same
+    chunk.
+    """
+    def __call__(self, manifest):
+        chunk_index = self.chunk_number - 1
+        depth = self.kwargs.get("depth")
+        for test_type, test_path, tests in manifest:
+            if depth:
+                hash_path = os.path.sep.join(os.path.dirname(test_path).split(os.path.sep, depth)[:depth])
+            else:
+                hash_path = os.path.dirname(test_path)
+            h = int(hashlib.md5(ensure_binary(hash_path)).hexdigest(), 16)
+            if h % self.total_chunks == chunk_index:
+                yield test_type, test_path, tests
+
+
+class TestFilter(object):
+    """Callable that restricts the set of tests in a given manifest according
+    to initial criteria"""
+    def __init__(self, test_manifests, include=None, exclude=None, manifest_path=None, explicit=False):
+        if manifest_path is None or include or explicit:
+            self.manifest = manifestinclude.IncludeManifest.create()
+            self.manifest.set_defaults()
+        else:
+            self.manifest = manifestinclude.get_manifest(manifest_path)
+
+        if include or explicit:
+            self.manifest.set("skip", "true")
+
+        if include:
+            for item in include:
+                self.manifest.add_include(test_manifests, item)
+
+        if exclude:
+            for item in exclude:
+                self.manifest.add_exclude(test_manifests, item)
+
+    def __call__(self, manifest_iter):
+        for test_type, test_path, tests in manifest_iter:
+            include_tests = set()
+            for test in tests:
+                if self.manifest.include(test):
+                    include_tests.add(test)
+
+            if include_tests:
+                yield test_type, test_path, include_tests
+
+
+class TagFilter(object):
+    def __init__(self, tags):
+        self.tags = set(tags)
+
+    def __call__(self, test_iter):
+        for test in test_iter:
+            if test.tags & self.tags:
+                yield test
+
+
+class ManifestLoader(object):
+    def __init__(self, test_paths, force_manifest_update=False, manifest_download=False,
+                 types=None):
+        do_delayed_imports()
+        self.test_paths = test_paths
+        self.force_manifest_update = force_manifest_update
+        self.manifest_download = manifest_download
+        self.types = types
+        self.logger = structured.get_default_logger()
+        if self.logger is None:
+            self.logger = structured.structuredlog.StructuredLogger("ManifestLoader")
+
+    def load(self):
+        rv = {}
+        for url_base, paths in iteritems(self.test_paths):
+            manifest_file = self.load_manifest(url_base=url_base,
+                                               **paths)
+            path_data = {"url_base": url_base}
+            path_data.update(paths)
+            rv[manifest_file] = path_data
+        return rv
+
+    def load_manifest(self, tests_path, manifest_path, metadata_path, url_base="/", **kwargs):
+        cache_root = os.path.join(metadata_path, ".cache")
+        if self.manifest_download:
+            download_from_github(manifest_path, tests_path)
+        return manifest.load_and_update(tests_path, manifest_path, url_base,
+                                        cache_root=cache_root, update=self.force_manifest_update,
+                                        types=self.types)
+
+
+def iterfilter(filters, iter):
+    for f in filters:
+        iter = f(iter)
+    for item in iter:
+        yield item
+
+
+class TestLoader(object):
+    """Loads tests according to a WPT manifest and any associated expectation files"""
+    def __init__(self,
+                 test_manifests,
+                 test_types,
+                 run_info,
+                 manifest_filters=None,
+                 chunk_type="none",
+                 total_chunks=1,
+                 chunk_number=1,
+                 include_https=True,
+                 include_h2=True,
+                 include_quic=False,
+                 skip_timeout=False,
+                 skip_implementation_status=None,
+                 chunker_kwargs=None):
+
+        self.test_types = test_types
+        self.run_info = run_info
+
+        self.manifest_filters = manifest_filters if manifest_filters is not None else []
+
+        self.manifests = test_manifests
+        self.tests = None
+        self.disabled_tests = None
+        self.include_https = include_https
+        self.include_h2 = include_h2
+        self.include_quic = include_quic
+        self.skip_timeout = skip_timeout
+        self.skip_implementation_status = skip_implementation_status
+
+        self.chunk_type = chunk_type
+        self.total_chunks = total_chunks
+        self.chunk_number = chunk_number
+
+        if chunker_kwargs is None:
+            chunker_kwargs = {}
+        self.chunker = {"none": Unchunked,
+                        "hash": HashChunker,
+                        "dir_hash": DirectoryHashChunker}[chunk_type](total_chunks,
+                                                                      chunk_number,
+                                                                      **chunker_kwargs)
+
+        self._test_ids = None
+
+        self.directory_manifests = {}
+
+        self._load_tests()
+
+    @property
+    def test_ids(self):
+        if self._test_ids is None:
+            self._test_ids = []
+            for test_dict in [self.disabled_tests, self.tests]:
+                for test_type in self.test_types:
+                    self._test_ids += [item.id for item in test_dict[test_type]]
+        return self._test_ids
+
+    def get_test(self, manifest_file, manifest_test, inherit_metadata, test_metadata):
+        if test_metadata is not None:
+            inherit_metadata.append(test_metadata)
+            test_metadata = test_metadata.get_test(manifest_test.id)
+
+        return wpttest.from_manifest(manifest_file, manifest_test, inherit_metadata, test_metadata)
+
+    def load_dir_metadata(self, test_manifest, metadata_path, test_path):
+        rv = []
+        path_parts = os.path.dirname(test_path).split(os.path.sep)
+        for i in range(len(path_parts) + 1):
+            path = os.path.join(metadata_path, os.path.sep.join(path_parts[:i]), "__dir__.ini")
+            if path not in self.directory_manifests:
+                self.directory_manifests[path] = manifestexpected.get_dir_manifest(path,
+                                                                                   self.run_info)
+            manifest = self.directory_manifests[path]
+            if manifest is not None:
+                rv.append(manifest)
+        return rv
+
+    def load_metadata(self, test_manifest, metadata_path, test_path):
+        inherit_metadata = self.load_dir_metadata(test_manifest, metadata_path, test_path)
+        test_metadata = manifestexpected.get_manifest(
+            metadata_path, test_path, test_manifest.url_base, self.run_info)
+        return inherit_metadata, test_metadata
+
+    def iter_tests(self):
+        manifest_items = []
+        manifests_by_url_base = {}
+
+        for manifest in sorted(self.manifests.keys(), key=lambda x:x.url_base):
+            manifest_iter = iterfilter(self.manifest_filters,
+                                       manifest.itertypes(*self.test_types))
+            manifest_items.extend(manifest_iter)
+            manifests_by_url_base[manifest.url_base] = manifest
+
+        if self.chunker is not None:
+            manifest_items = self.chunker(manifest_items)
+
+        for test_type, test_path, tests in manifest_items:
+            manifest_file = manifests_by_url_base[next(iter(tests)).url_base]
+            metadata_path = self.manifests[manifest_file]["metadata_path"]
+
+            inherit_metadata, test_metadata = self.load_metadata(manifest_file, metadata_path, test_path)
+            for test in tests:
+                yield test_path, test_type, self.get_test(manifest_file, test, inherit_metadata, test_metadata)
+
+    def _load_tests(self):
+        """Read in the tests from the manifest file and add them to a queue"""
+        tests = {"enabled":defaultdict(list),
+                 "disabled":defaultdict(list)}
+
+        for test_path, test_type, test in self.iter_tests():
+            enabled = not test.disabled()
+            if not self.include_https and test.environment["protocol"] == "https":
+                enabled = False
+            if not self.include_h2 and test.environment["protocol"] == "h2":
+                enabled = False
+            if not self.include_quic and test.environment["quic"]:
+                enabled = False
+            if self.skip_timeout and test.expected() == "TIMEOUT":
+                enabled = False
+            if self.skip_implementation_status and test.implementation_status() in self.skip_implementation_status:
+                enabled = False
+            key = "enabled" if enabled else "disabled"
+            tests[key][test_type].append(test)
+
+        self.tests = tests["enabled"]
+        self.disabled_tests = tests["disabled"]
+
+    def groups(self, test_types, chunk_type="none", total_chunks=1, chunk_number=1):
+        groups = set()
+
+        for test_type in test_types:
+            for test in self.tests[test_type]:
+                group = test.url.split("/")[1]
+                groups.add(group)
+
+        return groups
+
+
+def get_test_src(**kwargs):
+    test_source_kwargs = {"processes": kwargs["processes"],
+                          "logger": kwargs["logger"]}
+    chunker_kwargs = {}
+    if kwargs["run_by_dir"] is not False:
+        # A value of None indicates infinite depth
+        test_source_cls = PathGroupedSource
+        test_source_kwargs["depth"] = kwargs["run_by_dir"]
+        chunker_kwargs["depth"] = kwargs["run_by_dir"]
+    elif kwargs["test_groups"]:
+        test_source_cls = GroupFileTestSource
+        test_source_kwargs["test_groups"] = kwargs["test_groups"]
+    else:
+        test_source_cls = SingleTestSource
+    return test_source_cls, test_source_kwargs, chunker_kwargs
+
+
+class TestSource(object):
+    __metaclass__ = ABCMeta
+
+    def __init__(self, test_queue):
+        self.test_queue = test_queue
+        self.current_group = None
+        self.current_metadata = None
+
+    @abstractmethod
+    #@classmethod (doesn't compose with @abstractmethod in < 3.3)
+    def make_queue(cls, tests, **kwargs):  # noqa: N805
+        pass
+
+    @abstractmethod
+    def tests_by_group(cls, tests, **kwargs):  # noqa: N805
+        pass
+
+    @classmethod
+    def group_metadata(cls, state):
+        return {"scope": "/"}
+
+    def group(self):
+        if not self.current_group or len(self.current_group) == 0:
+            try:
+                self.current_group, self.current_metadata = self.test_queue.get(block=False)
+            except Empty:
+                return None, None
+        return self.current_group, self.current_metadata
+
+
+class GroupedSource(TestSource):
+    @classmethod
+    def new_group(cls, state, test, **kwargs):
+        raise NotImplementedError
+
+    @classmethod
+    def make_queue(cls, tests, **kwargs):
+        mp = mpcontext.get_context()
+        test_queue = mp.Queue()
+        groups = []
+
+        state = {}
+
+        for test in tests:
+            if cls.new_group(state, test, **kwargs):
+                group_metadata = cls.group_metadata(state)
+                groups.append((deque(), group_metadata))
+
+            group, metadata = groups[-1]
+            group.append(test)
+            test.update_metadata(metadata)
+
+        for item in groups:
+            test_queue.put(item)
+        return test_queue
+
+    @classmethod
+    def tests_by_group(cls, tests, **kwargs):
+        groups = defaultdict(list)
+        state = {}
+        current = None
+        for test in tests:
+            if cls.new_group(state, test, **kwargs):
+                current = cls.group_metadata(state)['scope']
+            groups[current].append(test.id)
+        return groups
+
+
+class SingleTestSource(TestSource):
+    @classmethod
+    def make_queue(cls, tests, **kwargs):
+        mp = mpcontext.get_context()
+        test_queue = mp.Queue()
+        processes = kwargs["processes"]
+        queues = [deque([]) for _ in range(processes)]
+        metadatas = [cls.group_metadata(None) for _ in range(processes)]
+        for test in tests:
+            idx = hash(test.id) % processes
+            group = queues[idx]
+            metadata = metadatas[idx]
+            group.append(test)
+            test.update_metadata(metadata)
+
+        for item in zip(queues, metadatas):
+            test_queue.put(item)
+
+        return test_queue
+
+    @classmethod
+    def tests_by_group(cls, tests, **kwargs):
+        return {cls.group_metadata(None)['scope']: [t.id for t in tests]}
+
+
+class PathGroupedSource(GroupedSource):
+    @classmethod
+    def new_group(cls, state, test, **kwargs):
+        depth = kwargs.get("depth")
+        if depth is True or depth == 0:
+            depth = None
+        path = urlsplit(test.url).path.split("/")[1:-1][:depth]
+        rv = path != state.get("prev_path")
+        state["prev_path"] = path
+        return rv
+
+    @classmethod
+    def group_metadata(cls, state):
+        return {"scope": "/%s" % "/".join(state["prev_path"])}
+
+
+class GroupFileTestSource(TestSource):
+    @classmethod
+    def make_queue(cls, tests, **kwargs):
+        tests_by_group = cls.tests_by_group(tests, **kwargs)
+
+        ids_to_tests = {test.id: test for test in tests}
+
+        mp = mpcontext.get_context()
+        test_queue = mp.Queue()
+
+        for group_name, test_ids in iteritems(tests_by_group):
+            group_metadata = {"scope": group_name}
+            group = deque()
+
+            for test_id in test_ids:
+                test = ids_to_tests[test_id]
+                group.append(test)
+                test.update_metadata(group_metadata)
+
+            test_queue.put((group, group_metadata))
+
+        return test_queue
+
+    @classmethod
+    def tests_by_group(cls, tests, **kwargs):
+        logger = kwargs["logger"]
+        test_groups = kwargs["test_groups"]
+
+        tests_by_group = defaultdict(list)
+        for test in tests:
+            try:
+                group = test_groups.group_by_test[test.id]
+            except KeyError:
+                logger.error("%s is missing from test groups file" % test.id)
+                raise
+            tests_by_group[group].append(test.id)
+
+        return tests_by_group
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testrunner.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testrunner.py
new file mode 100644
index 0000000..8dd9341
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/testrunner.py
@@ -0,0 +1,927 @@
+from __future__ import unicode_literals
+
+import threading
+import traceback
+from six.moves.queue import Empty
+from collections import namedtuple
+
+from mozlog import structuredlog, capture
+
+from . import mpcontext
+
+# Special value used as a sentinal in various commands
+Stop = object()
+
+
+def release_mozlog_lock():
+    try:
+        from mozlog.structuredlog import StructuredLogger
+        try:
+            StructuredLogger._lock.release()
+        except threading.ThreadError:
+            pass
+    except ImportError:
+        pass
+
+
+class MessageLogger(object):
+    def __init__(self, message_func):
+        self.send_message = message_func
+
+    def _log_data(self, action, **kwargs):
+        self.send_message("log", action, kwargs)
+
+    def process_output(self, process, data, command):
+        self._log_data("process_output", process=process, data=data, command=command)
+
+
+def _log_func(level_name):
+    def log(self, message):
+        self._log_data(level_name.lower(), message=message)
+    log.__doc__ = """Log a message with level %s
+
+:param message: The string message to log
+""" % level_name
+    log.__name__ = str(level_name).lower()
+    return log
+
+# Create all the methods on StructuredLog for debug levels
+for level_name in structuredlog.log_levels:
+    setattr(MessageLogger, level_name.lower(), _log_func(level_name))
+
+
+class TestRunner(object):
+    """Class implementing the main loop for running tests.
+
+    This class delegates the job of actually running a test to the executor
+    that is passed in.
+
+    :param logger: Structured logger
+    :param command_queue: subprocess.Queue used to send commands to the
+                          process
+    :param result_queue: subprocess.Queue used to send results to the
+                         parent TestRunnerManager process
+    :param executor: TestExecutor object that will actually run a test.
+    """
+    def __init__(self, logger, command_queue, result_queue, executor):
+        self.command_queue = command_queue
+        self.result_queue = result_queue
+
+        self.executor = executor
+        self.name = mpcontext.get_context().current_process().name
+        self.logger = logger
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_value, traceback):
+        self.teardown()
+
+    def setup(self):
+        self.logger.debug("Executor setup")
+        try:
+            self.executor.setup(self)
+        except Exception:
+            # The caller is responsible for logging the exception if required
+            self.send_message("init_failed")
+        else:
+            self.send_message("init_succeeded")
+        self.logger.debug("Executor setup done")
+
+    def teardown(self):
+        self.executor.teardown()
+        self.send_message("runner_teardown")
+        self.result_queue = None
+        self.command_queue = None
+        self.browser = None
+
+    def run(self):
+        """Main loop accepting commands over the pipe and triggering
+        the associated methods"""
+        try:
+            self.setup()
+        except Exception:
+            self.logger.warning("An error occured during executor setup:\n%s" %
+                                traceback.format_exc())
+            raise
+        commands = {"run_test": self.run_test,
+                    "reset": self.reset,
+                    "stop": self.stop,
+                    "wait": self.wait}
+        while True:
+            command, args = self.command_queue.get()
+            try:
+                rv = commands[command](*args)
+            except Exception:
+                self.send_message("error",
+                                  "Error running command %s with arguments %r:\n%s" %
+                                  (command, args, traceback.format_exc()))
+            else:
+                if rv is Stop:
+                    break
+
+    def stop(self):
+        return Stop
+
+    def reset(self):
+        self.executor.reset()
+
+    def run_test(self, test):
+        try:
+            return self.executor.run_test(test)
+        except Exception:
+            self.logger.error(traceback.format_exc())
+            raise
+
+    def wait(self):
+        self.executor.wait()
+        self.send_message("wait_finished")
+
+    def send_message(self, command, *args):
+        self.result_queue.put((command, args))
+
+
+def start_runner(runner_command_queue, runner_result_queue,
+                 executor_cls, executor_kwargs,
+                 executor_browser_cls, executor_browser_kwargs,
+                 capture_stdio, stop_flag):
+    """Launch a TestRunner in a new process"""
+
+    def send_message(command, *args):
+        runner_result_queue.put((command, args))
+
+    def handle_error(e):
+        logger.critical(traceback.format_exc())
+        stop_flag.set()
+
+    # Ensure that when we start this in a new process we have the global lock
+    # in the logging module unlocked
+    release_mozlog_lock()
+
+    logger = MessageLogger(send_message)
+
+    with capture.CaptureIO(logger, capture_stdio):
+        try:
+            browser = executor_browser_cls(**executor_browser_kwargs)
+            executor = executor_cls(logger, browser, **executor_kwargs)
+            with TestRunner(logger, runner_command_queue, runner_result_queue, executor) as runner:
+                try:
+                    runner.run()
+                except KeyboardInterrupt:
+                    stop_flag.set()
+                except Exception as e:
+                    handle_error(e)
+        except Exception as e:
+            handle_error(e)
+
+
+manager_count = 0
+
+
+def next_manager_number():
+    global manager_count
+    local = manager_count = manager_count + 1
+    return local
+
+
+class BrowserManager(object):
+    def __init__(self, logger, browser, command_queue, no_timeout=False):
+        self.logger = logger
+        self.browser = browser
+        self.no_timeout = no_timeout
+        self.browser_settings = None
+        self.last_test = None
+
+        self.started = False
+
+        self.init_timer = None
+        self.command_queue = command_queue
+
+    def update_settings(self, test):
+        browser_settings = self.browser.settings(test)
+        restart_required = ((self.browser_settings is not None and
+                             self.browser_settings != browser_settings) or
+                            (self.last_test != test and test.expected() == "CRASH"))
+        self.browser_settings = browser_settings
+        self.last_test = test
+        return restart_required
+
+    def init(self, group_metadata):
+        """Launch the browser that is being tested,
+        and the TestRunner process that will run the tests."""
+        # It seems that this lock is helpful to prevent some race that otherwise
+        # sometimes stops the spawned processes initialising correctly, and
+        # leaves this thread hung
+        if self.init_timer is not None:
+            self.init_timer.cancel()
+
+        self.logger.debug("Init called, starting browser and runner")
+
+        if not self.no_timeout:
+            self.init_timer = threading.Timer(self.browser.init_timeout,
+                                              self.init_timeout)
+        try:
+            if self.init_timer is not None:
+                self.init_timer.start()
+            self.logger.debug("Starting browser with settings %r" % self.browser_settings)
+            self.browser.start(group_metadata=group_metadata, **self.browser_settings)
+            self.browser_pid = self.browser.pid()
+        except Exception:
+            self.logger.warning("Failure during init %s" % traceback.format_exc())
+            if self.init_timer is not None:
+                self.init_timer.cancel()
+            self.logger.error(traceback.format_exc())
+            succeeded = False
+        else:
+            succeeded = True
+            self.started = True
+
+        return succeeded
+
+    def send_message(self, command, *args):
+        self.command_queue.put((command, args))
+
+    def init_timeout(self):
+        # This is called from a separate thread, so we send a message to the
+        # main loop so we get back onto the manager thread
+        self.logger.debug("init_failed called from timer")
+        self.send_message("init_failed")
+
+    def after_init(self):
+        """Callback when we have started the browser, started the remote
+        control connection, and we are ready to start testing."""
+        if self.init_timer is not None:
+            self.init_timer.cancel()
+
+    def stop(self, force=False):
+        self.browser.stop(force=force)
+        self.started = False
+
+    def cleanup(self):
+        if self.init_timer is not None:
+            self.init_timer.cancel()
+
+    def check_crash(self, test_id):
+        return self.browser.check_crash(process=self.browser_pid, test=test_id)
+
+    def is_alive(self):
+        return self.browser.is_alive()
+
+
+class _RunnerManagerState(object):
+    before_init = namedtuple("before_init", [])
+    initializing = namedtuple("initializing_browser",
+                              ["test", "test_group", "group_metadata", "failure_count"])
+    running = namedtuple("running", ["test", "test_group", "group_metadata"])
+    restarting = namedtuple("restarting", ["test", "test_group", "group_metadata"])
+    error = namedtuple("error", [])
+    stop = namedtuple("stop", [])
+
+
+RunnerManagerState = _RunnerManagerState()
+
+
+class TestRunnerManager(threading.Thread):
+    def __init__(self, suite_name, test_queue, test_source_cls, browser_cls, browser_kwargs,
+                 executor_cls, executor_kwargs, stop_flag, rerun=1, pause_after_test=False,
+                 pause_on_unexpected=False, restart_on_unexpected=True, debug_info=None,
+                 capture_stdio=True, recording=None):
+        """Thread that owns a single TestRunner process and any processes required
+        by the TestRunner (e.g. the Firefox binary).
+
+        TestRunnerManagers are responsible for launching the browser process and the
+        runner process, and for logging the test progress. The actual test running
+        is done by the TestRunner. In particular they:
+
+        * Start the binary of the program under test
+        * Start the TestRunner
+        * Tell the TestRunner to start a test, if any
+        * Log that the test started
+        * Log the test results
+        * Take any remedial action required e.g. restart crashed or hung
+          processes
+        """
+        self.suite_name = suite_name
+
+        self.test_source = test_source_cls(test_queue)
+
+        self.browser_cls = browser_cls
+        self.browser_kwargs = browser_kwargs
+
+        self.executor_cls = executor_cls
+        self.executor_kwargs = executor_kwargs
+
+        mp = mpcontext.get_context()
+
+        # Flags used to shut down this thread if we get a sigint
+        self.parent_stop_flag = stop_flag
+        self.child_stop_flag = mp.Event()
+
+        self.rerun = rerun
+        self.run_count = 0
+        self.pause_after_test = pause_after_test
+        self.pause_on_unexpected = pause_on_unexpected
+        self.restart_on_unexpected = restart_on_unexpected
+        self.debug_info = debug_info
+
+        self.manager_number = next_manager_number()
+        assert recording is not None
+        self.recording = recording
+
+        self.command_queue = mp.Queue()
+        self.remote_queue = mp.Queue()
+
+        self.test_runner_proc = None
+
+        threading.Thread.__init__(self, name="TestRunnerManager-%i" % self.manager_number)
+        # This is started in the actual new thread
+        self.logger = None
+
+        self.test_count = 0
+        self.unexpected_count = 0
+
+        # This may not really be what we want
+        self.daemon = True
+
+        self.timer = None
+
+        self.max_restarts = 5
+
+        self.browser = None
+
+        self.capture_stdio = capture_stdio
+
+    def run(self):
+        """Main loop for the TestRunnerManager.
+
+        TestRunnerManagers generally receive commands from their
+        TestRunner updating them on the status of a test. They
+        may also have a stop flag set by the main thread indicating
+        that the manager should shut down the next time the event loop
+        spins."""
+        self.recording.set(["testrunner", "startup"])
+        self.logger = structuredlog.StructuredLogger(self.suite_name)
+        with self.browser_cls(self.logger, **self.browser_kwargs) as browser:
+            self.browser = BrowserManager(self.logger,
+                                          browser,
+                                          self.command_queue,
+                                          no_timeout=self.debug_info is not None)
+            dispatch = {
+                RunnerManagerState.before_init: self.start_init,
+                RunnerManagerState.initializing: self.init,
+                RunnerManagerState.running: self.run_test,
+                RunnerManagerState.restarting: self.restart_runner
+            }
+
+            self.state = RunnerManagerState.before_init()
+            end_states = (RunnerManagerState.stop,
+                          RunnerManagerState.error)
+
+            try:
+                while not isinstance(self.state, end_states):
+                    f = dispatch.get(self.state.__class__)
+                    while f:
+                        self.logger.debug("Dispatch %s" % f.__name__)
+                        if self.should_stop():
+                            return
+                        new_state = f()
+                        if new_state is None:
+                            break
+                        self.state = new_state
+                        self.logger.debug("new state: %s" % self.state.__class__.__name__)
+                        if isinstance(self.state, end_states):
+                            return
+                        f = dispatch.get(self.state.__class__)
+
+                    new_state = None
+                    while new_state is None:
+                        new_state = self.wait_event()
+                        if self.should_stop():
+                            return
+                    self.state = new_state
+                    self.logger.debug("new state: %s" % self.state.__class__.__name__)
+            except Exception:
+                self.logger.error(traceback.format_exc())
+                raise
+            finally:
+                self.logger.debug("TestRunnerManager main loop terminating, starting cleanup")
+                clean = isinstance(self.state, RunnerManagerState.stop)
+                self.stop_runner(force=not clean)
+                self.teardown()
+        self.logger.debug("TestRunnerManager main loop terminated")
+
+    def wait_event(self):
+        dispatch = {
+            RunnerManagerState.before_init: {},
+            RunnerManagerState.initializing:
+            {
+                "init_succeeded": self.init_succeeded,
+                "init_failed": self.init_failed,
+            },
+            RunnerManagerState.running:
+            {
+                "test_ended": self.test_ended,
+                "wait_finished": self.wait_finished,
+            },
+            RunnerManagerState.restarting: {},
+            RunnerManagerState.error: {},
+            RunnerManagerState.stop: {},
+            None: {
+                "runner_teardown": self.runner_teardown,
+                "log": self.log,
+                "error": self.error
+            }
+        }
+        try:
+            command, data = self.command_queue.get(True, 1)
+            self.logger.debug("Got command: %r" % command)
+        except IOError:
+            self.logger.error("Got IOError from poll")
+            return RunnerManagerState.restarting(0)
+        except Empty:
+            if (self.debug_info and self.debug_info.interactive and
+                self.browser.started and not self.browser.is_alive()):
+                self.logger.debug("Debugger exited")
+                return RunnerManagerState.stop()
+
+            if (isinstance(self.state, RunnerManagerState.running) and
+                not self.test_runner_proc.is_alive()):
+                if not self.command_queue.empty():
+                    # We got a new message so process that
+                    return
+
+                # If we got to here the runner presumably shut down
+                # unexpectedly
+                self.logger.info("Test runner process shut down")
+
+                if self.state.test is not None:
+                    # This could happen if the test runner crashed for some other
+                    # reason
+                    # Need to consider the unlikely case where one test causes the
+                    # runner process to repeatedly die
+                    self.logger.critical("Last test did not complete")
+                    return RunnerManagerState.error()
+                self.logger.warning("More tests found, but runner process died, restarting")
+                return RunnerManagerState.restarting(0)
+        else:
+            f = (dispatch.get(self.state.__class__, {}).get(command) or
+                 dispatch.get(None, {}).get(command))
+            if not f:
+                self.logger.warning("Got command %s in state %s" %
+                                    (command, self.state.__class__.__name__))
+                return
+            return f(*data)
+
+    def should_stop(self):
+        return self.child_stop_flag.is_set() or self.parent_stop_flag.is_set()
+
+    def start_init(self):
+        test, test_group, group_metadata = self.get_next_test()
+        self.recording.set(["testrunner", "init"])
+        if test is None:
+            return RunnerManagerState.stop()
+        else:
+            return RunnerManagerState.initializing(test, test_group, group_metadata, 0)
+
+    def init(self):
+        assert isinstance(self.state, RunnerManagerState.initializing)
+        if self.state.failure_count > self.max_restarts:
+            self.logger.critical("Max restarts exceeded")
+            return RunnerManagerState.error()
+
+        self.browser.update_settings(self.state.test)
+
+        result = self.browser.init(self.state.group_metadata)
+        if result is Stop:
+            return RunnerManagerState.error()
+        elif not result:
+            return RunnerManagerState.initializing(self.state.test,
+                                                   self.state.test_group,
+                                                   self.state.group_metadata,
+                                                   self.state.failure_count + 1)
+        else:
+            self.executor_kwargs["group_metadata"] = self.state.group_metadata
+            self.start_test_runner()
+
+    def start_test_runner(self):
+        # Note that we need to be careful to start the browser before the
+        # test runner to ensure that any state set when the browser is started
+        # can be passed in to the test runner.
+        assert isinstance(self.state, RunnerManagerState.initializing)
+        assert self.command_queue is not None
+        assert self.remote_queue is not None
+        self.logger.info("Starting runner")
+        executor_browser_cls, executor_browser_kwargs = self.browser.browser.executor_browser()
+
+        args = (self.remote_queue,
+                self.command_queue,
+                self.executor_cls,
+                self.executor_kwargs,
+                executor_browser_cls,
+                executor_browser_kwargs,
+                self.capture_stdio,
+                self.child_stop_flag)
+
+        mp = mpcontext.get_context()
+        self.test_runner_proc = mp.Process(target=start_runner,
+                                           args=args,
+                                           name="TestRunner-%i" % self.manager_number)
+        self.test_runner_proc.start()
+        self.logger.debug("Test runner started")
+        # Now we wait for either an init_succeeded event or an init_failed event
+
+    def init_succeeded(self):
+        assert isinstance(self.state, RunnerManagerState.initializing)
+        self.browser.after_init()
+        return RunnerManagerState.running(self.state.test,
+                                          self.state.test_group,
+                                          self.state.group_metadata)
+
+    def init_failed(self):
+        assert isinstance(self.state, RunnerManagerState.initializing)
+        self.browser.check_crash(None)
+        self.browser.after_init()
+        self.stop_runner(force=True)
+        return RunnerManagerState.initializing(self.state.test,
+                                               self.state.test_group,
+                                               self.state.group_metadata,
+                                               self.state.failure_count + 1)
+
+    def get_next_test(self, test_group=None):
+        test = None
+        while test is None:
+            while test_group is None or len(test_group) == 0:
+                test_group, group_metadata = self.test_source.group()
+                if test_group is None:
+                    self.logger.info("No more tests")
+                    return None, None, None
+            test = test_group.popleft()
+        self.run_count = 0
+        return test, test_group, group_metadata
+
+    def run_test(self):
+        assert isinstance(self.state, RunnerManagerState.running)
+        assert self.state.test is not None
+
+        if self.browser.update_settings(self.state.test):
+            self.logger.info("Restarting browser for new test environment")
+            return RunnerManagerState.restarting(self.state.test,
+                                                 self.state.test_group,
+                                                 self.state.group_metadata)
+
+        self.recording.set(["testrunner", "test"] + self.state.test.id.split("/")[1:])
+        self.logger.test_start(self.state.test.id)
+        if self.rerun > 1:
+            self.logger.info("Run %d/%d" % (self.run_count, self.rerun))
+            self.send_message("reset")
+        self.run_count += 1
+        if self.debug_info is None:
+            # Factor of 3 on the extra timeout here is based on allowing the executor
+            # at least test.timeout + 2 * extra_timeout to complete,
+            # which in turn is based on having several layers of timeout inside the executor
+            wait_timeout = (self.state.test.timeout * self.executor_kwargs['timeout_multiplier'] +
+                            3 * self.executor_cls.extra_timeout)
+            self.timer = threading.Timer(wait_timeout, self._timeout)
+
+        self.send_message("run_test", self.state.test)
+        if self.timer:
+            self.timer.start()
+
+    def _timeout(self):
+        # This is executed in a different thread (threading.Timer).
+        self.logger.info("Got timeout in harness")
+        test = self.state.test
+        self.inject_message(
+            "test_ended",
+            test,
+            (test.result_cls("EXTERNAL-TIMEOUT",
+                             "TestRunner hit external timeout "
+                             "(this may indicate a hang)"), []),
+        )
+
+    def test_ended(self, test, results):
+        """Handle the end of a test.
+
+        Output the result of each subtest, and the result of the overall
+        harness to the logs.
+        """
+        if ((not isinstance(self.state, RunnerManagerState.running)) or
+            (test != self.state.test)):
+            # Due to inherent race conditions in EXTERNAL-TIMEOUT, we might
+            # receive multiple test_ended for a test (e.g. from both Executor
+            # and TestRunner), in which case we ignore the duplicate message.
+            self.logger.error("Received unexpected test_ended for %s" % test)
+            return
+        if self.timer is not None:
+            self.timer.cancel()
+        # Write the result of each subtest
+        file_result, test_results = results
+        subtest_unexpected = False
+        expect_any_subtest_status = test.expect_any_subtest_status()
+        if expect_any_subtest_status:
+            self.logger.debug("Ignoring subtest statuses for test %s" % test.id)
+        for result in test_results:
+            if test.disabled(result.name):
+                continue
+            if expect_any_subtest_status:
+                expected = result.status
+            else:
+                expected = test.expected(result.name)
+            known_intermittent = test.known_intermittent(result.name)
+            is_unexpected = expected != result.status and result.status not in known_intermittent
+
+            if is_unexpected:
+                self.unexpected_count += 1
+                self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count)
+                subtest_unexpected = True
+            self.logger.test_status(test.id,
+                                    result.name,
+                                    result.status,
+                                    message=result.message,
+                                    expected=expected,
+                                    known_intermittent=known_intermittent,
+                                    stack=result.stack)
+
+        # We have a couple of status codes that are used internally, but not exposed to the
+        # user. These are used to indicate that some possibly-broken state was reached
+        # and we should restart the runner before the next test.
+        # INTERNAL-ERROR indicates a Python exception was caught in the harness
+        # EXTERNAL-TIMEOUT indicates we had to forcibly kill the browser from the harness
+        # because the test didn't return a result after reaching the test-internal timeout
+        status_subns = {"INTERNAL-ERROR": "ERROR",
+                        "EXTERNAL-TIMEOUT": "TIMEOUT"}
+        expected = test.expected()
+        known_intermittent = test.known_intermittent()
+        status = status_subns.get(file_result.status, file_result.status)
+
+        if self.browser.check_crash(test.id) and status != "CRASH":
+            if test.test_type == "crashtest":
+                self.logger.info("Found a crash dump file; changing status to CRASH")
+                status = "CRASH"
+            else:
+                self.logger.warning("Found a crash dump; should change status from %s to CRASH but this causes instability" % (status,))
+
+        self.test_count += 1
+        is_unexpected = expected != status and status not in known_intermittent
+        if is_unexpected:
+            self.unexpected_count += 1
+            self.logger.debug("Unexpected count in this thread %i" % self.unexpected_count)
+
+        if "assertion_count" in file_result.extra:
+            assertion_count = file_result.extra["assertion_count"]
+            if assertion_count is not None and assertion_count > 0:
+                self.logger.assertion_count(test.id,
+                                            int(assertion_count),
+                                            test.min_assertion_count,
+                                            test.max_assertion_count)
+
+        file_result.extra["test_timeout"] = test.timeout * self.executor_kwargs['timeout_multiplier']
+
+        self.logger.test_end(test.id,
+                             status,
+                             message=file_result.message,
+                             expected=expected,
+                             known_intermittent=known_intermittent,
+                             extra=file_result.extra,
+                             stack=file_result.stack)
+
+        restart_before_next = (test.restart_after or
+                               file_result.status in ("CRASH", "EXTERNAL-TIMEOUT", "INTERNAL-ERROR") or
+                               ((subtest_unexpected or is_unexpected) and
+                                self.restart_on_unexpected))
+
+        self.recording.set(["testrunner", "after-test"])
+        if (not file_result.status == "CRASH" and
+            self.pause_after_test or
+            (self.pause_on_unexpected and (subtest_unexpected or is_unexpected))):
+            self.logger.info("Pausing until the browser exits")
+            self.send_message("wait")
+        else:
+            return self.after_test_end(test, restart_before_next)
+
+    def wait_finished(self):
+        assert isinstance(self.state, RunnerManagerState.running)
+        self.logger.debug("Wait finished")
+
+        # The browser should be stopped already, but this ensures we do any
+        # post-stop processing
+        return self.after_test_end(self.state.test, True)
+
+    def after_test_end(self, test, restart):
+        assert isinstance(self.state, RunnerManagerState.running)
+        if self.run_count == self.rerun:
+            test, test_group, group_metadata = self.get_next_test()
+            if test is None:
+                return RunnerManagerState.stop()
+            if test_group is not self.state.test_group:
+                # We are starting a new group of tests, so force a restart
+                self.logger.info("Restarting browser for new test group")
+                restart = True
+        else:
+            test_group = self.state.test_group
+            group_metadata = self.state.group_metadata
+        if restart:
+            return RunnerManagerState.restarting(test, test_group, group_metadata)
+        else:
+            return RunnerManagerState.running(test, test_group, group_metadata)
+
+    def restart_runner(self):
+        """Stop and restart the TestRunner"""
+        assert isinstance(self.state, RunnerManagerState.restarting)
+        self.stop_runner()
+        return RunnerManagerState.initializing(self.state.test, self.state.test_group, self.state.group_metadata, 0)
+
+    def log(self, action, kwargs):
+        getattr(self.logger, action)(**kwargs)
+
+    def error(self, message):
+        self.logger.error(message)
+        self.restart_runner()
+
+    def stop_runner(self, force=False):
+        """Stop the TestRunner and the browser binary."""
+        self.recording.set(["testrunner", "stop_runner"])
+        if self.test_runner_proc is None:
+            return
+
+        if self.test_runner_proc.is_alive():
+            self.send_message("stop")
+        try:
+            self.browser.stop(force=force)
+            self.ensure_runner_stopped()
+        finally:
+            self.cleanup()
+
+    def teardown(self):
+        self.logger.debug("TestRunnerManager teardown")
+        self.test_runner_proc = None
+        self.command_queue.close()
+        self.remote_queue.close()
+        self.command_queue = None
+        self.remote_queue = None
+        self.recording.pause()
+
+    def ensure_runner_stopped(self):
+        self.logger.debug("ensure_runner_stopped")
+        if self.test_runner_proc is None:
+            return
+
+        self.browser.stop(force=True)
+        self.logger.debug("waiting for runner process to end")
+        self.test_runner_proc.join(10)
+        self.logger.debug("After join")
+        mp = mpcontext.get_context()
+        if self.test_runner_proc.is_alive():
+            # This might leak a file handle from the queue
+            self.logger.warning("Forcibly terminating runner process")
+            self.test_runner_proc.terminate()
+
+            # Multiprocessing queues are backed by operating system pipes. If
+            # the pipe in the child process had buffered data at the time of
+            # forced termination, the queue is no longer in a usable state
+            # (subsequent attempts to retrieve items may block indefinitely).
+            # Discard the potentially-corrupted queue and create a new one.
+            self.command_queue.close()
+            self.command_queue = mp.Queue()
+            self.remote_queue.close()
+            self.remote_queue = mp.Queue()
+        else:
+            self.logger.debug("Runner process exited with code %i" % self.test_runner_proc.exitcode)
+
+    def runner_teardown(self):
+        self.ensure_runner_stopped()
+        return RunnerManagerState.stop()
+
+    def send_message(self, command, *args):
+        """Send a message to the remote queue (to Executor)."""
+        self.remote_queue.put((command, args))
+
+    def inject_message(self, command, *args):
+        """Inject a message to the command queue (from Executor)."""
+        self.command_queue.put((command, args))
+
+    def cleanup(self):
+        self.logger.debug("TestRunnerManager cleanup")
+        if self.browser:
+            self.browser.cleanup()
+        while True:
+            try:
+                cmd, data = self.command_queue.get_nowait()
+            except Empty:
+                break
+            else:
+                if cmd == "log":
+                    self.log(*data)
+                elif cmd == "runner_teardown":
+                    # It's OK for the "runner_teardown" message to be left in
+                    # the queue during cleanup, as we will already have tried
+                    # to stop the TestRunner in `stop_runner`.
+                    pass
+                else:
+                    self.logger.warning("Command left in command_queue during cleanup: %r, %r" % (cmd, data))
+        while True:
+            try:
+                cmd, data = self.remote_queue.get_nowait()
+                self.logger.warning("Command left in remote_queue during cleanup: %r, %r" % (cmd, data))
+            except Empty:
+                break
+
+
+def make_test_queue(tests, test_source_cls, **test_source_kwargs):
+    queue = test_source_cls.make_queue(tests, **test_source_kwargs)
+
+    # There is a race condition that means sometimes we continue
+    # before the tests have been written to the underlying pipe.
+    # Polling the pipe for data here avoids that
+    queue._reader.poll(10)
+    assert not queue.empty()
+    return queue
+
+
+class ManagerGroup(object):
+    """Main thread object that owns all the TestRunnerManager threads."""
+    def __init__(self, suite_name, size, test_source_cls, test_source_kwargs,
+                 browser_cls, browser_kwargs,
+                 executor_cls, executor_kwargs,
+                 rerun=1,
+                 pause_after_test=False,
+                 pause_on_unexpected=False,
+                 restart_on_unexpected=True,
+                 debug_info=None,
+                 capture_stdio=True,
+                 recording=None):
+        self.suite_name = suite_name
+        self.size = size
+        self.test_source_cls = test_source_cls
+        self.test_source_kwargs = test_source_kwargs
+        self.browser_cls = browser_cls
+        self.browser_kwargs = browser_kwargs
+        self.executor_cls = executor_cls
+        self.executor_kwargs = executor_kwargs
+        self.pause_after_test = pause_after_test
+        self.pause_on_unexpected = pause_on_unexpected
+        self.restart_on_unexpected = restart_on_unexpected
+        self.debug_info = debug_info
+        self.rerun = rerun
+        self.capture_stdio = capture_stdio
+        self.recording = recording
+        assert recording is not None
+
+        self.pool = set()
+        # Event that is polled by threads so that they can gracefully exit in the face
+        # of sigint
+        self.stop_flag = threading.Event()
+        self.logger = structuredlog.StructuredLogger(suite_name)
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, exc_type, exc_val, exc_tb):
+        self.stop()
+
+    def run(self, test_type, tests):
+        """Start all managers in the group"""
+        self.logger.debug("Using %i processes" % self.size)
+        type_tests = tests[test_type]
+        if not type_tests:
+            self.logger.info("No %s tests to run" % test_type)
+            return
+
+        test_queue = make_test_queue(type_tests, self.test_source_cls, **self.test_source_kwargs)
+
+        for _ in range(self.size):
+            manager = TestRunnerManager(self.suite_name,
+                                        test_queue,
+                                        self.test_source_cls,
+                                        self.browser_cls,
+                                        self.browser_kwargs,
+                                        self.executor_cls,
+                                        self.executor_kwargs,
+                                        self.stop_flag,
+                                        self.rerun,
+                                        self.pause_after_test,
+                                        self.pause_on_unexpected,
+                                        self.restart_on_unexpected,
+                                        self.debug_info,
+                                        self.capture_stdio,
+                                        recording=self.recording)
+            manager.start()
+            self.pool.add(manager)
+        self.wait()
+
+    def wait(self):
+        """Wait for all the managers in the group to finish"""
+        for manager in self.pool:
+            manager.join()
+
+    def stop(self):
+        """Set the stop flag so that all managers in the group stop as soon
+        as possible"""
+        self.stop_flag.set()
+        self.logger.debug("Stop flag set in ManagerGroup")
+
+    def test_count(self):
+        return sum(manager.test_count for manager in self.pool)
+
+    def unexpected_count(self):
+        return sum(manager.unexpected_count for manager in self.pool)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/__init__.py
new file mode 100644
index 0000000..78cda9c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/__init__.py
@@ -0,0 +1,45 @@
+import sys
+
+from mozlog.structured import structuredlog, commandline
+
+from .. import wptcommandline
+
+from .update import WPTUpdate
+
+def remove_logging_args(args):
+    """Take logging args out of the dictionary of command line arguments so
+    they are not passed in as kwargs to the update code. This is particularly
+    necessary here because the arguments are often of type file, which cannot
+    be serialized.
+
+    :param args: Dictionary of command line arguments.
+    """
+    for name in list(args.keys()):
+        if name.startswith("log_"):
+            args.pop(name)
+
+
+def setup_logging(args, defaults):
+    """Use the command line arguments to set up the logger.
+
+    :param args: Dictionary of command line arguments.
+    :param defaults: Dictionary of {formatter_name: stream} to use if
+                     no command line logging is specified"""
+    logger = commandline.setup_logging("web-platform-tests-update", args, defaults)
+
+    remove_logging_args(args)
+
+    return logger
+
+
+def run_update(logger, **kwargs):
+    updater = WPTUpdate(logger, **kwargs)
+    return updater.run()
+
+
+def main():
+    args = wptcommandline.parse_args_update()
+    logger = setup_logging(args, {"mach": sys.stdout})
+    assert structuredlog.get_default_logger() is not None
+    success = run_update(logger, **args)
+    sys.exit(0 if success else 1)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/base.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/base.py
new file mode 100644
index 0000000..547808e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/base.py
@@ -0,0 +1,65 @@
+exit_unclean = object()
+exit_clean = object()
+
+
+class Step(object):
+    provides = []
+
+    def __init__(self, logger):
+        self.logger = logger
+
+    def run(self, step_index, state):
+        """Base class for state-creating steps.
+
+        When a Step is run() the current state is checked to see
+        if the state from this step has already been created. If it
+        has the restore() method is invoked. Otherwise the create()
+        method is invoked with the state object. This is expected to
+        add items with all the keys in __class__.provides to the state
+        object.
+        """
+
+        name = self.__class__.__name__
+
+        try:
+            stored_step = state.steps[step_index]
+        except IndexError:
+            stored_step = None
+
+        if stored_step == name:
+            self.restore(state)
+        elif stored_step is None:
+            self.create(state)
+            assert set(self.provides).issubset(set(state.keys()))
+            state.steps = state.steps + [name]
+        else:
+            raise ValueError("Expected a %s step, got a %s step" % (name, stored_step))
+
+    def create(self, data):
+        raise NotImplementedError
+
+    def restore(self, state):
+        self.logger.debug("Step %s using stored state" % (self.__class__.__name__,))
+        for key in self.provides:
+            assert key in state
+
+
+class StepRunner(object):
+    steps = []
+
+    def __init__(self, logger, state):
+        """Class that runs a specified series of Steps with a common State"""
+        self.state = state
+        self.logger = logger
+        if "steps" not in state:
+            state.steps = []
+
+    def run(self):
+        rv = None
+        for step_index, step in enumerate(self.steps):
+            self.logger.debug("Starting step %s" % step.__name__)
+            rv = step(self.logger).run(step_index, self.state)
+            if rv in (exit_clean, exit_unclean):
+                break
+
+        return rv
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/metadata.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/metadata.py
new file mode 100644
index 0000000..4bc70d31
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/metadata.py
@@ -0,0 +1,68 @@
+import os
+
+from .. import metadata, products
+
+from .base import Step, StepRunner
+
+
+class GetUpdatePropertyList(Step):
+    provides = ["update_properties"]
+
+    def create(self, state):
+        state.update_properties = products.load_product_update(state.config, state.product)
+
+
+class UpdateExpected(Step):
+    """Do the metadata update on the local checkout"""
+
+    def create(self, state):
+        if state.sync_tree is not None:
+            sync_root = state.sync_tree.root
+        else:
+            sync_root = None
+
+        metadata.update_expected(state.paths,
+                                 state.serve_root,
+                                 state.run_log,
+                                 update_properties=state.update_properties,
+                                 rev_old=None,
+                                 full_update=state.full_update,
+                                 sync_root=sync_root,
+                                 disable_intermittent=state.disable_intermittent,
+                                 update_intermittent=state.update_intermittent,
+                                 remove_intermittent=state.remove_intermittent)
+
+
+class CreateMetadataPatch(Step):
+    """Create a patch/commit for the metadata checkout"""
+
+    def create(self, state):
+        if not state.patch:
+            return
+
+        local_tree = state.local_tree
+        sync_tree = state.sync_tree
+
+        if sync_tree is not None:
+            name = "web-platform-tests_update_%s_metadata" % sync_tree.rev
+            message = "Update %s expected data to revision %s" % (state.suite_name, sync_tree.rev)
+        else:
+            name = "web-platform-tests_update_metadata"
+            message = "Update %s expected data" % state.suite_name
+
+        local_tree.create_patch(name, message)
+
+        if not local_tree.is_clean:
+            metadata_paths = [manifest_path["metadata_path"]
+                              for manifest_path in state.paths.itervalues()]
+            for path in metadata_paths:
+                local_tree.add_new(os.path.relpath(path, local_tree.root))
+            local_tree.update_patch(include=metadata_paths)
+            local_tree.commit_patch()
+
+
+class MetadataUpdateRunner(StepRunner):
+    """(Sub)Runner for updating metadata"""
+    steps = [GetUpdatePropertyList,
+             UpdateExpected,
+             CreateMetadataPatch]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/state.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/state.py
new file mode 100644
index 0000000..6b6ff1a
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/state.py
@@ -0,0 +1,157 @@
+import os
+from six.moves import cPickle as pickle  # noqa: N813
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+class BaseState(object):
+    def __new__(cls, logger):
+        rv = cls.load(logger)
+        if rv is not None:
+            logger.debug("Existing state found")
+            return rv
+
+        logger.debug("No existing state found")
+        return super(BaseState, cls).__new__(cls)
+
+    def __init__(self, logger):
+        """Object containing state variables created when running Steps.
+
+        Variables are set and get as attributes e.g. state_obj.spam = "eggs".
+
+        :param parent: Parent State object or None if this is the root object.
+        """
+
+        if hasattr(self, "_data"):
+            return
+
+        self._data = [{}]
+        self._logger = logger
+        self._index = 0
+
+    def __getstate__(self):
+        rv = self.__dict__.copy()
+        del rv["_logger"]
+        return rv
+
+
+    def push(self, init_values):
+        """Push a new clean state dictionary
+
+        :param init_values: List of variable names in the current state dict to copy
+                            into the new state dict."""
+
+        return StateContext(self, init_values)
+
+    def is_empty(self):
+        return len(self._data) == 1 and self._data[0] == {}
+
+    def clear(self):
+        """Remove all state and delete the stored copy."""
+        self._data = [{}]
+
+    def __setattr__(self, key, value):
+        if key.startswith("_"):
+            object.__setattr__(self, key, value)
+        else:
+            self._data[self._index][key] = value
+            self.save()
+
+    def __getattr__(self, key):
+        if key.startswith("_"):
+            raise AttributeError
+        try:
+            return self._data[self._index][key]
+        except KeyError:
+            raise AttributeError
+
+    def __contains__(self, key):
+        return key in self._data[self._index]
+
+    def update(self, items):
+        """Add a dictionary of {name: value} pairs to the state"""
+        self._data[self._index].update(items)
+        self.save()
+
+    def keys(self):
+        return self._data[self._index].keys()
+
+
+    @classmethod
+    def load(cls):
+        raise NotImplementedError
+
+    def save(self):
+        raise NotImplementedError
+
+
+class SavedState(BaseState):
+    """On write the state is serialized to disk, such that it can be restored in
+       the event that the program is interrupted before all steps are complete.
+       Note that this only works well if the values are immutable; mutating an
+       existing value will not cause the data to be serialized."""
+    filename = os.path.join(here, ".wpt-update.lock")
+
+    @classmethod
+    def load(cls, logger):
+        """Load saved state from a file"""
+        try:
+            if not os.path.isfile(cls.filename):
+                return None
+            with open(cls.filename, "rb") as f:
+                try:
+                    rv = pickle.load(f)
+                    logger.debug("Loading data %r" % (rv._data,))
+                    rv._logger = logger
+                    rv._index = 0
+                    return rv
+                except EOFError:
+                    logger.warning("Found empty state file")
+        except IOError:
+            logger.debug("IOError loading stored state")
+
+    def save(self):
+        """Write the state to disk"""
+        with open(self.filename, "wb") as f:
+            pickle.dump(self, f)
+
+    def clear(self):
+        super(SavedState, self).clear()
+        try:
+            os.unlink(self.filename)
+        except OSError:
+            pass
+
+
+class UnsavedState(BaseState):
+    @classmethod
+    def load(cls, logger):
+        return None
+
+    def save(self):
+        return
+
+
+class StateContext(object):
+    def __init__(self, state, init_values):
+        self.state = state
+        self.init_values = init_values
+
+    def __enter__(self):
+        if len(self.state._data) == self.state._index + 1:
+            # This is the case where there is no stored state
+            new_state = {}
+            for key in self.init_values:
+                new_state[key] = self.state._data[self.state._index][key]
+            self.state._data.append(new_state)
+        self.state._index += 1
+        self.state._logger.debug("Incremented index to %s" % self.state._index)
+
+    def __exit__(self, *args, **kwargs):
+        if len(self.state._data) > 1:
+            assert self.state._index == len(self.state._data) - 1
+            self.state._data.pop()
+            self.state._index -= 1
+            self.state._logger.debug("Decremented index to %s" % self.state._index)
+            assert self.state._index >= 0
+        else:
+            raise ValueError("Tried to pop the top state")
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/sync.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/sync.py
new file mode 100644
index 0000000..f878752
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/sync.py
@@ -0,0 +1,148 @@
+import fnmatch
+import os
+import re
+import shutil
+import sys
+import uuid
+
+from .base import Step, StepRunner
+from .tree import Commit
+
+here = os.path.abspath(os.path.dirname(__file__))
+
+
+def copy_wpt_tree(tree, dest, excludes=None, includes=None):
+    """Copy the working copy of a Tree to a destination directory.
+
+    :param tree: The Tree to copy.
+    :param dest: The destination directory"""
+    if os.path.exists(dest):
+        assert os.path.isdir(dest)
+
+    shutil.rmtree(dest)
+
+    os.mkdir(dest)
+
+    if excludes is None:
+        excludes = []
+
+    excludes = [re.compile(fnmatch.translate(item)) for item in excludes]
+
+    if includes is None:
+        includes = []
+
+    includes = [re.compile(fnmatch.translate(item)) for item in includes]
+
+    for tree_path in tree.paths():
+        if (any(item.match(tree_path) for item in excludes) and
+            not any(item.match(tree_path) for item in includes)):
+            continue
+
+        source_path = os.path.join(tree.root, tree_path)
+        dest_path = os.path.join(dest, tree_path)
+
+        dest_dir = os.path.dirname(dest_path)
+        if not os.path.isdir(source_path):
+            if not os.path.exists(dest_dir):
+                os.makedirs(dest_dir)
+            shutil.copy2(source_path, dest_path)
+
+    for source, destination in [("testharness_runner.html", ""),
+                                ("testdriver-vendor.js", "resources/")]:
+        source_path = os.path.join(here, os.pardir, source)
+        dest_path = os.path.join(dest, destination, os.path.basename(source))
+        shutil.copy2(source_path, dest_path)
+
+
+class UpdateCheckout(Step):
+    """Pull changes from upstream into the local sync tree."""
+
+    provides = ["local_branch"]
+
+    def create(self, state):
+        sync_tree = state.sync_tree
+        state.local_branch = uuid.uuid4().hex
+        sync_tree.update(state.sync["remote_url"],
+                         state.sync["branch"],
+                         state.local_branch)
+        sync_path = os.path.abspath(sync_tree.root)
+        if sync_path not in sys.path:
+            from update import setup_paths
+            setup_paths(sync_path)
+
+    def restore(self, state):
+        assert os.path.abspath(state.sync_tree.root) in sys.path
+        Step.restore(self, state)
+
+
+class GetSyncTargetCommit(Step):
+    """Find the commit that we will sync to."""
+
+    provides = ["sync_commit"]
+
+    def create(self, state):
+        if state.target_rev is None:
+            #Use upstream branch HEAD as the base commit
+            state.sync_commit = state.sync_tree.get_remote_sha1(state.sync["remote_url"],
+                                                                state.sync["branch"])
+        else:
+            state.sync_commit = Commit(state.sync_tree, state.rev)
+
+        state.sync_tree.checkout(state.sync_commit.sha1, state.local_branch, force=True)
+        self.logger.debug("New base commit is %s" % state.sync_commit.sha1)
+
+
+class UpdateManifest(Step):
+    """Update the manifest to match the tests in the sync tree checkout"""
+
+    provides = ["manifest_path", "test_manifest"]
+
+    def create(self, state):
+        from manifest import manifest
+        state.manifest_path = os.path.join(state.metadata_path, "MANIFEST.json")
+        state.test_manifest = manifest.load_and_update(state.sync["path"],
+                                                       state.manifest_path,
+                                                       "/",
+                                                       write_manifest=True)
+
+
+class CopyWorkTree(Step):
+    """Copy the sync tree over to the destination in the local tree"""
+
+    def create(self, state):
+        copy_wpt_tree(state.sync_tree,
+                      state.tests_path,
+                      excludes=state.path_excludes,
+                      includes=state.path_includes)
+
+
+class CreateSyncPatch(Step):
+    """Add the updated test files to a commit/patch in the local tree."""
+
+    def create(self, state):
+        if not state.patch:
+            return
+
+        local_tree = state.local_tree
+        sync_tree = state.sync_tree
+
+        local_tree.create_patch("web-platform-tests_update_%s" % sync_tree.rev,
+                                "Update %s to revision %s" % (state.suite_name, sync_tree.rev))
+        test_prefix = os.path.relpath(state.tests_path, local_tree.root)
+        local_tree.add_new(test_prefix)
+        local_tree.add_ignored(sync_tree, test_prefix)
+        updated = local_tree.update_patch(include=[state.tests_path,
+                                                   state.metadata_path])
+        local_tree.commit_patch()
+
+        if not updated:
+            self.logger.info("Nothing to sync")
+
+
+class SyncFromUpstreamRunner(StepRunner):
+    """(Sub)Runner for doing an upstream sync"""
+    steps = [UpdateCheckout,
+             GetSyncTargetCommit,
+             UpdateManifest,
+             CopyWorkTree,
+             CreateSyncPatch]
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/tree.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/tree.py
new file mode 100644
index 0000000..f362770
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/tree.py
@@ -0,0 +1,407 @@
+import os
+import re
+import subprocess
+import tempfile
+
+from six.moves import range
+
+from .. import vcs
+from ..vcs import git, hg
+
+
+def get_unique_name(existing, initial):
+    """Get a name either equal to initial or of the form initial_N, for some
+    integer N, that is not in the set existing.
+
+
+    :param existing: Set of names that must not be chosen.
+    :param initial: Name, or name prefix, to use"""
+    if initial not in existing:
+        return initial
+    for i in range(len(existing) + 1):
+        test = "%s_%s" % (initial, i + 1)
+        if test not in existing:
+            return test
+    assert False
+
+class NoVCSTree(object):
+    name = "non-vcs"
+
+    def __init__(self, root=None):
+        if root is None:
+            root = os.path.abspath(os.curdir)
+        self.root = root
+
+    @classmethod
+    def is_type(cls, path=None):
+        return True
+
+    @property
+    def is_clean(self):
+        return True
+
+    def add_new(self, prefix=None):
+        pass
+
+    def add_ignored(self, sync_tree, prefix):
+        pass
+
+    def create_patch(self, patch_name, message):
+        pass
+
+    def update_patch(self, include=None):
+        pass
+
+    def commit_patch(self):
+        pass
+
+
+class HgTree(object):
+    name = "mercurial"
+
+    def __init__(self, root=None):
+        if root is None:
+            root = hg("root").strip()
+        self.root = root
+        self.hg = vcs.bind_to_repo(hg, self.root)
+
+    def __getstate__(self):
+        rv = self.__dict__.copy()
+        del rv['hg']
+        return rv
+
+    def __setstate__(self, dict):
+        self.__dict__.update(dict)
+        self.hg = vcs.bind_to_repo(vcs.hg, self.root)
+
+    @classmethod
+    def is_type(cls, path=None):
+        kwargs = {"log_error": False}
+        if path is not None:
+            kwargs["repo"] = path
+        try:
+            hg("root", **kwargs)
+        except Exception:
+            return False
+        return True
+
+    @property
+    def is_clean(self):
+        return self.hg("status").strip() == ""
+
+    def add_new(self, prefix=None):
+        if prefix is not None:
+            args = ("-I", prefix)
+        else:
+            args = ()
+        self.hg("add", *args)
+
+    def add_ignored(self, sync_tree, prefix):
+        pass
+
+    def create_patch(self, patch_name, message):
+        try:
+            self.hg("qinit", log_error=False)
+        except subprocess.CalledProcessError:
+            pass
+
+        patch_names = [item.strip() for item in self.hg("qseries").split("\n") if item.strip()]
+
+        suffix = 0
+        test_name = patch_name
+        while test_name in patch_names:
+            suffix += 1
+            test_name = "%s-%i" % (patch_name, suffix)
+
+        self.hg("qnew", test_name, "-X", self.root, "-m", message)
+
+    def update_patch(self, include=None):
+        if include is not None:
+            args = []
+            for item in include:
+                args.extend(["-I", item])
+        else:
+            args = ()
+
+        self.hg("qrefresh", *args)
+        return True
+
+    def commit_patch(self):
+        self.hg("qfinish")
+
+    def contains_commit(self, commit):
+        try:
+            self.hg("identify", "-r", commit.sha1)
+            return True
+        except subprocess.CalledProcessError:
+            return False
+
+
+class GitTree(object):
+    name = "git"
+
+    def __init__(self, root=None, log_error=True):
+        if root is None:
+            root = git("rev-parse", "--show-toplevel", log_error=log_error).strip()
+        self.root = root
+        self.git = vcs.bind_to_repo(git, self.root, log_error=log_error)
+        self.message = None
+        self.commit_cls = Commit
+
+    def __getstate__(self):
+        rv = self.__dict__.copy()
+        del rv['git']
+        return rv
+
+    def __setstate__(self, dict):
+        self.__dict__.update(dict)
+        self.git = vcs.bind_to_repo(vcs.git, self.root)
+
+    @classmethod
+    def is_type(cls, path=None):
+        kwargs = {"log_error": False}
+        if path is not None:
+            kwargs["repo"] = path
+        try:
+            git("rev-parse", "--show-toplevel", **kwargs)
+        except Exception:
+            return False
+        return True
+
+    @property
+    def rev(self):
+        """Current HEAD revision"""
+        if vcs.is_git_root(self.root):
+            return self.git("rev-parse", "HEAD").strip()
+        else:
+            return None
+
+    @property
+    def is_clean(self):
+        return self.git("status").strip() == ""
+
+    def add_new(self, prefix=None):
+        """Add files to the staging area.
+
+        :param prefix: None to include all files or a path prefix to
+                       add all files under that path.
+        """
+        if prefix is None:
+            args = ["-a"]
+        else:
+            args = ["--no-ignore-removal", prefix]
+        self.git("add", *args)
+
+    def add_ignored(self, sync_tree, prefix):
+        """Add files to the staging area that are explicitly ignored by git.
+
+        :param prefix: None to include all files or a path prefix to
+                       add all files under that path.
+        """
+        with tempfile.TemporaryFile() as f:
+            sync_tree.git("ls-tree", "-z", "-r", "--name-only", "HEAD", stdout=f)
+            f.seek(0)
+            ignored_files = sync_tree.git("check-ignore", "--no-index", "--stdin", "-z", stdin=f)
+        args = []
+        for entry in ignored_files.split('\0'):
+            args.append(os.path.join(prefix, entry))
+        if args:
+            self.git("add", "--force", *args)
+
+    def list_refs(self, ref_filter=None):
+        """Get a list of sha1, name tuples for references in a repository.
+
+        :param ref_filter: Pattern that reference name must match (from the end,
+                           matching whole /-delimited segments only
+        """
+        args = []
+        if ref_filter is not None:
+            args.append(ref_filter)
+        data = self.git("show-ref", *args)
+        rv = []
+        for line in data.split("\n"):
+            if not line.strip():
+                continue
+            sha1, ref = line.split()
+            rv.append((sha1, ref))
+        return rv
+
+    def list_remote(self, remote, ref_filter=None):
+        """Return a list of (sha1, name) tupes for references in a remote.
+
+        :param remote: URL of the remote to list.
+        :param ref_filter: Pattern that the reference name must match.
+        """
+        args = []
+        if ref_filter is not None:
+            args.append(ref_filter)
+        data = self.git("ls-remote", remote, *args)
+        rv = []
+        for line in data.split("\n"):
+            if not line.strip():
+                continue
+            sha1, ref = line.split()
+            rv.append((sha1, ref))
+        return rv
+
+    def get_remote_sha1(self, remote, branch):
+        """Return the SHA1 of a particular branch in a remote.
+
+        :param remote: the remote URL
+        :param branch: the branch name"""
+        for sha1, ref in self.list_remote(remote, branch):
+            if ref == "refs/heads/%s" % branch:
+                return self.commit_cls(self, sha1)
+        assert False
+
+    def create_patch(self, patch_name, message):
+        # In git a patch is actually a commit
+        self.message = message
+
+    def update_patch(self, include=None):
+        """Commit the staged changes, or changes to listed files.
+
+        :param include: Either None, to commit staged changes, or a list
+                        of filenames (which must already be in the repo)
+                        to commit
+        """
+        if include is not None:
+            args = tuple(include)
+        else:
+            args = ()
+
+        if self.git("status", "-uno", "-z", *args).strip():
+            self.git("add", *args)
+            return True
+        return False
+
+    def commit_patch(self):
+        assert self.message is not None
+
+        if self.git("diff", "--name-only", "--staged", "-z").strip():
+            self.git("commit", "-m", self.message)
+            return True
+
+        return False
+
+    def init(self):
+        self.git("init")
+        assert vcs.is_git_root(self.root)
+
+    def checkout(self, rev, branch=None, force=False):
+        """Checkout a particular revision, optionally into a named branch.
+
+        :param rev: Revision identifier (e.g. SHA1) to checkout
+        :param branch: Branch name to use
+        :param force: Force-checkout
+        """
+        assert rev is not None
+
+        args = []
+        if branch:
+            branches = [ref[len("refs/heads/"):] for sha1, ref in self.list_refs()
+                        if ref.startswith("refs/heads/")]
+            branch = get_unique_name(branches, branch)
+
+            args += ["-b", branch]
+
+        if force:
+            args.append("-f")
+        args.append(rev)
+        self.git("checkout", *args)
+
+    def update(self, remote, remote_branch, local_branch):
+        """Fetch from the remote and checkout into a local branch.
+
+        :param remote: URL to the remote repository
+        :param remote_branch: Branch on the remote repository to check out
+        :param local_branch: Local branch name to check out into
+        """
+        if not vcs.is_git_root(self.root):
+            self.init()
+        self.git("clean", "-xdf")
+        self.git("fetch", remote, "%s:%s" % (remote_branch, local_branch))
+        self.checkout(local_branch)
+        self.git("submodule", "update", "--init", "--recursive")
+
+    def clean(self):
+        self.git("checkout", self.rev)
+        self.git("branch", "-D", self.local_branch)
+
+    def paths(self):
+        """List paths in the tree"""
+        repo_paths = [self.root] + [os.path.join(self.root, path)
+                                    for path in self.submodules()]
+
+        rv = []
+
+        for repo_path in repo_paths:
+            paths = vcs.git("ls-tree", "-r", "--name-only", "HEAD", repo=repo_path).split("\n")
+            rv.extend(os.path.relpath(os.path.join(repo_path, item), self.root) for item in paths
+                      if item.strip())
+        return rv
+
+    def submodules(self):
+        """List submodule directories"""
+        output = self.git("submodule", "status", "--recursive")
+        rv = []
+        for line in output.split("\n"):
+            line = line.strip()
+            if not line:
+                continue
+            parts = line.split(" ")
+            rv.append(parts[1])
+        return rv
+
+    def contains_commit(self, commit):
+        try:
+            self.git("rev-parse", "--verify", commit.sha1)
+            return True
+        except subprocess.CalledProcessError:
+            return False
+
+
+class CommitMessage(object):
+    def __init__(self, text):
+        self.text = text
+        self._parse_message()
+
+    def __str__(self):
+        return self.text
+
+    def _parse_message(self):
+        lines = self.text.splitlines()
+        self.full_summary = lines[0]
+        self.body = "\n".join(lines[1:])
+
+
+class Commit(object):
+    msg_cls = CommitMessage
+
+    _sha1_re = re.compile("^[0-9a-f]{40}$")
+
+    def __init__(self, tree, sha1):
+        """Object representing a commit in a specific GitTree.
+
+        :param tree: GitTree to which this commit belongs.
+        :param sha1: Full sha1 string for the commit
+        """
+        assert self._sha1_re.match(sha1)
+
+        self.tree = tree
+        self.git = tree.git
+        self.sha1 = sha1
+        self.author, self.email, self.message = self._get_meta()
+
+    def __getstate__(self):
+        rv = self.__dict__.copy()
+        del rv['git']
+        return rv
+
+    def __setstate__(self, dict):
+        self.__dict__.update(dict)
+        self.git = self.tree.git
+
+    def _get_meta(self):
+        author, email, message = self.git("show", "-s", "--format=format:%an\n%ae\n%B", self.sha1).split("\n", 2)
+        return author, email, self.msg_cls(message)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/update.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/update.py
new file mode 100644
index 0000000..80e509d
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/update/update.py
@@ -0,0 +1,191 @@
+import os
+import sys
+
+from six import itervalues
+
+from .metadata import MetadataUpdateRunner
+from .sync import SyncFromUpstreamRunner
+from .tree import GitTree, HgTree, NoVCSTree
+
+from .base import Step, StepRunner, exit_clean, exit_unclean
+from .state import SavedState, UnsavedState
+
+def setup_paths(sync_path):
+    sys.path.insert(0, os.path.abspath(sync_path))
+    from tools import localpaths  # noqa: F401
+
+class LoadConfig(Step):
+    """Step for loading configuration from the ini file and kwargs."""
+
+    provides = ["sync", "paths", "metadata_path", "tests_path"]
+
+    def create(self, state):
+        state.sync = {"remote_url": state.kwargs["remote_url"],
+                      "branch": state.kwargs["branch"],
+                      "path": state.kwargs["sync_path"]}
+
+        state.paths = state.kwargs["test_paths"]
+        state.tests_path = state.paths["/"]["tests_path"]
+        state.metadata_path = state.paths["/"]["metadata_path"]
+
+        assert os.path.isabs(state.tests_path)
+
+
+class LoadTrees(Step):
+    """Step for creating a Tree for the local copy and a GitTree for the
+    upstream sync."""
+
+    provides = ["local_tree", "sync_tree"]
+
+    def create(self, state):
+        if os.path.exists(state.sync["path"]):
+            sync_tree = GitTree(root=state.sync["path"])
+        else:
+            sync_tree = None
+
+        if GitTree.is_type():
+            local_tree = GitTree()
+        elif HgTree.is_type():
+            local_tree = HgTree()
+        else:
+            local_tree = NoVCSTree()
+
+        state.update({"local_tree": local_tree,
+                      "sync_tree": sync_tree})
+
+
+class SyncFromUpstream(Step):
+    """Step that synchronises a local copy of the code with upstream."""
+
+    def create(self, state):
+        if not state.kwargs["sync"]:
+            return
+
+        if not state.sync_tree:
+            os.mkdir(state.sync["path"])
+            state.sync_tree = GitTree(root=state.sync["path"])
+
+        kwargs = state.kwargs
+        with state.push(["sync", "paths", "metadata_path", "tests_path", "local_tree",
+                         "sync_tree"]):
+            state.target_rev = kwargs["rev"]
+            state.patch = kwargs["patch"]
+            state.suite_name = kwargs["suite_name"]
+            state.path_excludes = kwargs["exclude"]
+            state.path_includes = kwargs["include"]
+            runner = SyncFromUpstreamRunner(self.logger, state)
+            runner.run()
+
+
+class UpdateMetadata(Step):
+    """Update the expectation metadata from a set of run logs"""
+
+    def create(self, state):
+        if not state.kwargs["run_log"]:
+            return
+
+        kwargs = state.kwargs
+        with state.push(["local_tree", "sync_tree", "paths", "serve_root"]):
+            state.run_log = kwargs["run_log"]
+            state.disable_intermittent = kwargs["disable_intermittent"]
+            state.update_intermittent = kwargs["update_intermittent"]
+            state.remove_intermittent = kwargs["remove_intermittent"]
+            state.patch = kwargs["patch"]
+            state.suite_name = kwargs["suite_name"]
+            state.product = kwargs["product"]
+            state.config = kwargs["config"]
+            state.full_update = kwargs["full"]
+            state.extra_properties = kwargs["extra_property"]
+            runner = MetadataUpdateRunner(self.logger, state)
+            runner.run()
+
+
+class RemoveObsolete(Step):
+    """Remove metadata files that don't corespond to an existing test file"""
+
+    def create(self, state):
+        if not state.kwargs["remove_obsolete"]:
+            return
+
+        paths = state.kwargs["test_paths"]
+        state.tests_path = state.paths["/"]["tests_path"]
+        state.metadata_path = state.paths["/"]["metadata_path"]
+
+        for url_paths in itervalues(paths):
+            tests_path = url_paths["tests_path"]
+            metadata_path = url_paths["metadata_path"]
+            for dirpath, dirnames, filenames in os.walk(metadata_path):
+                for filename in filenames:
+                    if filename == "__dir__.ini":
+                        continue
+                    if filename.endswith(".ini"):
+                        full_path = os.path.join(dirpath, filename)
+                        rel_path = os.path.relpath(full_path, metadata_path)
+                        test_path = os.path.join(tests_path, rel_path[:-4])
+                        if not os.path.exists(test_path):
+                            os.unlink(full_path)
+
+
+class UpdateRunner(StepRunner):
+    """Runner for doing an overall update."""
+    steps = [LoadConfig,
+             LoadTrees,
+             SyncFromUpstream,
+             RemoveObsolete,
+             UpdateMetadata]
+
+
+class WPTUpdate(object):
+    def __init__(self, logger, runner_cls=UpdateRunner, **kwargs):
+        """Object that controls the running of a whole wptupdate.
+
+        :param runner_cls: Runner subclass holding the overall list of
+                           steps to run.
+        :param kwargs: Command line arguments
+        """
+        self.runner_cls = runner_cls
+        self.serve_root = kwargs["test_paths"]["/"]["tests_path"]
+
+        if not kwargs["sync"]:
+            setup_paths(self.serve_root)
+        else:
+            if os.path.exists(kwargs["sync_path"]):
+                # If the sync path doesn't exist we defer this until it does
+                setup_paths(kwargs["sync_path"])
+
+        if kwargs.get("store_state", False):
+            self.state = SavedState(logger)
+        else:
+            self.state = UnsavedState(logger)
+        self.kwargs = kwargs
+        self.logger = logger
+
+    def run(self, **kwargs):
+        if self.kwargs["abort"]:
+            self.abort()
+            return exit_clean
+
+        if not self.kwargs["continue"] and not self.state.is_empty():
+            self.logger.critical("Found existing state. Run with --continue to resume or --abort to clear state")
+            return exit_unclean
+
+        if self.kwargs["continue"]:
+            if self.state.is_empty():
+                self.logger.error("No sync in progress?")
+                return exit_clean
+
+            self.kwargs = self.state.kwargs
+        else:
+            self.state.kwargs = self.kwargs
+
+        self.state.serve_root = self.serve_root
+
+        update_runner = self.runner_cls(self.logger, self.state)
+        rv = update_runner.run()
+        if rv in (exit_clean, None):
+            self.state.clear()
+
+        return rv
+
+    def abort(self):
+        self.state.clear()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/vcs.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/vcs.py
new file mode 100644
index 0000000..896d8a0
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/vcs.py
@@ -0,0 +1,64 @@
+import subprocess
+from functools import partial
+
+from mozlog import get_default_logger
+
+from wptserve.utils import isomorphic_decode
+
+logger = None
+
+def vcs(bin_name):
+    def inner(command, *args, **kwargs):
+        global logger
+
+        if logger is None:
+            logger = get_default_logger("vcs")
+
+        repo = kwargs.pop("repo", None)
+        log_error = kwargs.pop("log_error", True)
+        stdout = kwargs.pop("stdout", None)
+        stdin = kwargs.pop("stdin", None)
+        if kwargs:
+            raise TypeError(kwargs)
+
+        args = list(args)
+
+        proc_kwargs = {}
+        if repo is not None:
+            # Make sure `cwd` is str type to work in different sub-versions of Python 3.
+            # Before 3.8, bytes were not accepted on Windows for `cwd`.
+            proc_kwargs["cwd"] = isomorphic_decode(repo)
+        if stdout is not None:
+            proc_kwargs["stdout"] = stdout
+        if stdin is not None:
+            proc_kwargs["stdin"] = stdin
+
+        command_line = [bin_name, command] + args
+        logger.debug(" ".join(command_line))
+        try:
+            func = subprocess.check_output if not stdout else subprocess.check_call
+            return func(command_line, stderr=subprocess.STDOUT, **proc_kwargs)
+        except OSError as e:
+            if log_error:
+                logger.error(e)
+            raise
+        except subprocess.CalledProcessError as e:
+            if log_error:
+                logger.error(e.output)
+            raise
+    return inner
+
+git = vcs("git")
+hg = vcs("hg")
+
+
+def bind_to_repo(vcs_func, repo, log_error=True):
+    return partial(vcs_func, repo=repo, log_error=log_error)
+
+
+def is_git_root(path, log_error=True):
+    try:
+        rv = git("rev-parse", "--show-cdup", repo=path, log_error=log_error)
+    except subprocess.CalledProcessError:
+        return False
+    return rv == b"\n"
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/webdriver_server.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/webdriver_server.py
new file mode 100644
index 0000000..dfae057f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/webdriver_server.py
@@ -0,0 +1,284 @@
+import abc
+import errno
+import os
+import platform
+import socket
+import time
+import traceback
+
+import mozprocess
+
+from .process import cast_env
+
+
+__all__ = ["SeleniumServer", "ChromeDriverServer", "CWTChromeDriverServer",
+           "EdgeChromiumDriverServer", "OperaDriverServer", "GeckoDriverServer",
+           "InternetExplorerDriverServer", "EdgeDriverServer",
+           "ServoDriverServer", "WebKitDriverServer", "WebDriverServer"]
+
+
+class WebDriverServer(object):
+    __metaclass__ = abc.ABCMeta
+
+    default_base_path = "/"
+
+    def __init__(self, logger, binary, host="127.0.0.1", port=None,
+                 base_path="", env=None, args=None):
+        if binary is None:
+            raise ValueError("WebDriver server binary must be given "
+                             "to --webdriver-binary argument")
+
+        self.logger = logger
+        self.binary = binary
+        self.host = host
+        if base_path == "":
+            self.base_path = self.default_base_path
+        else:
+            self.base_path = base_path
+        self.env = os.environ.copy() if env is None else env
+
+        self._port = port
+        self._cmd = None
+        self._args = args if args is not None else []
+        self._proc = None
+
+    @abc.abstractmethod
+    def make_command(self):
+        """Returns the full command for starting the server process as a list."""
+
+    def start(self, block=False):
+        try:
+            self._run(block)
+        except KeyboardInterrupt:
+            self.stop()
+
+    def _run(self, block):
+        self._cmd = self.make_command()
+        self._proc = mozprocess.ProcessHandler(
+            self._cmd,
+            processOutputLine=self.on_output,
+            env=cast_env(self.env),
+            storeOutput=False)
+
+        self.logger.debug("Starting WebDriver: %s" % ' '.join(self._cmd))
+        try:
+            self._proc.run()
+        except OSError as e:
+            if e.errno == errno.ENOENT:
+                raise IOError(
+                    "WebDriver executable not found: %s" % self.binary)
+            raise
+
+        self.logger.debug(
+            "Waiting for WebDriver to become accessible: %s" % self.url)
+        try:
+            wait_for_service((self.host, self.port))
+        except Exception:
+            self.logger.error(
+                "WebDriver was not accessible "
+                "within the timeout:\n%s" % traceback.format_exc())
+            raise
+
+        if block:
+            self._proc.wait()
+
+    def stop(self, force=False):
+        self.logger.debug("Stopping WebDriver")
+        if self.is_alive():
+            kill_result = self._proc.kill()
+            if force and kill_result != 0:
+                return self._proc.kill(9)
+            return kill_result
+        return not self.is_alive()
+
+    def is_alive(self):
+        return hasattr(self._proc, "proc") and self._proc.poll() is None
+
+    def on_output(self, line):
+        self.logger.process_output(self.pid,
+                                   line.decode("utf8", "replace"),
+                                   command=" ".join(self._cmd))
+
+    @property
+    def pid(self):
+        if self._proc is not None:
+            return self._proc.pid
+
+    @property
+    def url(self):
+        return "http://%s:%i%s" % (self.host, self.port, self.base_path)
+
+    @property
+    def port(self):
+        if self._port is None:
+            self._port = get_free_port()
+        return self._port
+
+
+class SeleniumServer(WebDriverServer):
+    default_base_path = "/wd/hub"
+
+    def make_command(self):
+        return ["java", "-jar", self.binary, "-port", str(self.port)] + self._args
+
+
+class ChromeDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="chromedriver", port=None,
+                 base_path="", args=None):
+        WebDriverServer.__init__(
+            self, logger, binary, port=port, base_path=base_path, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                cmd_arg("port", str(self.port)),
+                cmd_arg("url-base", self.base_path) if self.base_path else "",
+                cmd_arg("enable-chrome-logs")] + self._args
+
+class CWTChromeDriverServer(WebDriverServer):
+    def __init__(self, logger, binary, port=None, args=None):
+        WebDriverServer.__init__(self, logger, binary, port=port, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                "--port=%s" % str(self.port)] + self._args
+
+class EdgeChromiumDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="msedgedriver", port=None,
+                 base_path="", args=None):
+        WebDriverServer.__init__(
+            self, logger, binary, port=port, base_path=base_path, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                cmd_arg("port", str(self.port)),
+                cmd_arg("url-base", self.base_path) if self.base_path else ""] + self._args
+
+class EdgeDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="microsoftwebdriver.exe", port=None,
+                 base_path="", host="localhost", args=None):
+        WebDriverServer.__init__(
+            self, logger, binary, host=host, port=port, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                "--port=%s" % str(self.port)] + self._args
+
+class OperaDriverServer(ChromeDriverServer):
+    def __init__(self, logger, binary="operadriver", port=None,
+                 base_path="", args=None):
+        ChromeDriverServer.__init__(
+            self, logger, binary, port=port, base_path=base_path, args=args)
+
+
+class InternetExplorerDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="IEDriverServer.exe", port=None,
+                 base_path="", host="localhost", args=None):
+        WebDriverServer.__init__(
+            self, logger, binary, host=host, port=port, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                "--port=%s" % str(self.port)] + self._args
+
+
+class GeckoDriverServer(WebDriverServer):
+    def __init__(self, logger, marionette_port=2828, binary="geckodriver",
+                 host="127.0.0.1", port=None, args=None):
+        env = os.environ.copy()
+        env["RUST_BACKTRACE"] = "1"
+        WebDriverServer.__init__(self, logger, binary,
+                                 host=host,
+                                 port=port,
+                                 env=cast_env(env),
+                                 args=args)
+        self.marionette_port = marionette_port
+
+    def make_command(self):
+        return [self.binary,
+                "--marionette-port", str(self.marionette_port),
+                "--host", self.host,
+                "--port", str(self.port)] + self._args
+
+
+class SafariDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="safaridriver", port=None, args=None):
+        WebDriverServer.__init__(
+            self, logger, binary, port=port, args=args)
+
+    def make_command(self):
+        return [self.binary,
+                "--port=%s" % str(self.port)] + self._args
+
+
+class ServoDriverServer(WebDriverServer):
+    def __init__(self, logger, binary="servo", binary_args=None, host="127.0.0.1",
+                 port=None, args=None):
+        env = os.environ.copy()
+        env["RUST_BACKTRACE"] = "1"
+        WebDriverServer.__init__(self, logger, binary,
+                                 host=host,
+                                 port=port,
+                                 env=cast_env(env),
+                                 args=args)
+        self.binary_args = binary_args
+
+    def make_command(self):
+        command = [self.binary,
+                   "--webdriver=%s" % self.port,
+                   "--hard-fail",
+                   "--headless"] + self._args
+        if self.binary_args:
+            command += self.binary_args
+        return command
+
+
+class WebKitDriverServer(WebDriverServer):
+    def __init__(self, logger, binary=None, port=None, args=None):
+        WebDriverServer.__init__(self, logger, binary, port=port, args=args)
+
+    def make_command(self):
+        return [self.binary, "--port=%s" % str(self.port)] + self._args
+
+
+def cmd_arg(name, value=None):
+    prefix = "-" if platform.system() == "Windows" else "--"
+    rv = prefix + name
+    if value is not None:
+        rv += "=" + value
+    return rv
+
+
+def get_free_port():
+    """Get a random unbound port"""
+    while True:
+        s = socket.socket()
+        try:
+            s.bind(("127.0.0.1", 0))
+        except socket.error:
+            continue
+        else:
+            return s.getsockname()[1]
+        finally:
+            s.close()
+
+
+def wait_for_service(addr, timeout=60):
+    """Waits until network service given as a tuple of (host, port) becomes
+    available or the `timeout` duration is reached, at which point
+    ``socket.error`` is raised."""
+    end = time.time() + timeout
+    while end > time.time():
+        so = socket.socket()
+        try:
+            so.connect(addr)
+        except socket.timeout:
+            pass
+        except socket.error as e:
+            if e.errno != errno.ECONNREFUSED:
+                raise
+        else:
+            return True
+        finally:
+            so.close()
+        time.sleep(0.5)
+    raise socket.error("Service is unavailable: %s:%i" % addr)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptcommandline.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptcommandline.py
new file mode 100644
index 0000000..bfd6491
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptcommandline.py
@@ -0,0 +1,710 @@
+from __future__ import absolute_import, print_function
+import argparse
+import os
+import sys
+from collections import OrderedDict
+from distutils.spawn import find_executable
+from datetime import timedelta
+from six import ensure_text, iterkeys, itervalues, iteritems
+
+from . import config
+from . import wpttest
+from .formatters import chromium, wptreport, wptscreenshot
+
+def abs_path(path):
+    return os.path.abspath(os.path.expanduser(path))
+
+
+def url_or_path(path):
+    from six.moves.urllib.parse import urlparse
+
+    parsed = urlparse(path)
+    if len(parsed.scheme) > 2:
+        return path
+    else:
+        return abs_path(path)
+
+
+def require_arg(kwargs, name, value_func=None):
+    if value_func is None:
+        value_func = lambda x: x is not None
+
+    if name not in kwargs or not value_func(kwargs[name]):
+        print("Missing required argument %s" % name, file=sys.stderr)
+        sys.exit(1)
+
+
+def create_parser(product_choices=None):
+    from mozlog import commandline
+
+    from . import products
+
+    if product_choices is None:
+        config_data = config.load()
+        product_choices = products.products_enabled(config_data)
+
+    parser = argparse.ArgumentParser(description="""Runner for web-platform-tests tests.""",
+                                     usage="""%(prog)s [OPTION]... [TEST]...
+
+TEST is either the full path to a test file to run, or the URL of a test excluding
+scheme host and port.""")
+    parser.add_argument("--manifest-update", action="store_true", default=None,
+                        help="Regenerate the test manifest.")
+    parser.add_argument("--no-manifest-update", action="store_false", dest="manifest_update",
+                        help="Prevent regeneration of the test manifest.")
+    parser.add_argument("--manifest-download", action="store_true", default=None,
+                        help="Attempt to download a preexisting manifest when updating.")
+    parser.add_argument("--no-manifest-download", action="store_false", dest="manifest_download",
+                        help="Prevent download of the test manifest.")
+
+    parser.add_argument("--timeout-multiplier", action="store", type=float, default=None,
+                        help="Multiplier relative to standard test timeout to use")
+    parser.add_argument("--run-by-dir", type=int, nargs="?", default=False,
+                        help="Split run into groups by directories. With a parameter,"
+                        "limit the depth of splits e.g. --run-by-dir=1 to split by top-level"
+                        "directory")
+    parser.add_argument("--processes", action="store", type=int, default=None,
+                        help="Number of simultaneous processes to use")
+
+    parser.add_argument("--no-capture-stdio", action="store_true", default=False,
+                        help="Don't capture stdio and write to logging")
+    parser.add_argument("--no-fail-on-unexpected", action="store_false",
+                        default=True,
+                        dest="fail_on_unexpected",
+                        help="Exit with status code 0 when test expectations are violated")
+
+    mode_group = parser.add_argument_group("Mode")
+    mode_group.add_argument("--list-test-groups", action="store_true",
+                            default=False,
+                            help="List the top level directories containing tests that will run.")
+    mode_group.add_argument("--list-disabled", action="store_true",
+                            default=False,
+                            help="List the tests that are disabled on the current platform")
+    mode_group.add_argument("--list-tests", action="store_true",
+                            default=False,
+                            help="List all tests that will run")
+    stability_group = mode_group.add_mutually_exclusive_group()
+    stability_group.add_argument("--verify", action="store_true",
+                                 default=False,
+                                 help="Run a stability check on the selected tests")
+    stability_group.add_argument("--stability", action="store_true",
+                                 default=False,
+                                 help=argparse.SUPPRESS)
+    mode_group.add_argument("--verify-log-full", action="store_true",
+                            default=False,
+                            help="Output per-iteration test results when running verify")
+    mode_group.add_argument("--verify-repeat-loop", action="store",
+                            default=10,
+                            help="Number of iterations for a run that reloads each test without restart.",
+                            type=int)
+    mode_group.add_argument("--verify-repeat-restart", action="store",
+                            default=5,
+                            help="Number of iterations, for a run that restarts the runner between each iteration",
+                            type=int)
+    chaos_mode_group = mode_group.add_mutually_exclusive_group()
+    chaos_mode_group.add_argument("--verify-no-chaos-mode", action="store_false",
+                                  default=True,
+                                  dest="verify_chaos_mode",
+                                  help="Disable chaos mode when running on Firefox")
+    chaos_mode_group.add_argument("--verify-chaos-mode", action="store_true",
+                                  default=True,
+                                  dest="verify_chaos_mode",
+                                  help="Enable chaos mode when running on Firefox")
+    mode_group.add_argument("--verify-max-time", action="store",
+                            default=None,
+                            help="The maximum number of minutes for the job to run",
+                            type=lambda x: timedelta(minutes=float(x)))
+    output_results_group = mode_group.add_mutually_exclusive_group()
+    output_results_group.add_argument("--verify-no-output-results", action="store_false",
+                                      dest="verify_output_results",
+                                      default=True,
+                                      help="Prints individuals test results and messages")
+    output_results_group.add_argument("--verify-output-results", action="store_true",
+                                      dest="verify_output_results",
+                                      default=True,
+                                      help="Disable printing individuals test results and messages")
+
+    test_selection_group = parser.add_argument_group("Test Selection")
+    test_selection_group.add_argument("--test-types", action="store",
+                                      nargs="*", default=wpttest.enabled_tests,
+                                      choices=wpttest.enabled_tests,
+                                      help="Test types to run")
+    test_selection_group.add_argument("--include", action="append",
+                                      help="URL prefix to include")
+    test_selection_group.add_argument("--exclude", action="append",
+                                      help="URL prefix to exclude")
+    test_selection_group.add_argument("--include-manifest", type=abs_path,
+                                      help="Path to manifest listing tests to include")
+    test_selection_group.add_argument("--test-groups", dest="test_groups_file", type=abs_path,
+                                      help="Path to json file containing a mapping {group_name: [test_ids]}")
+    test_selection_group.add_argument("--skip-timeout", action="store_true",
+                                      help="Skip tests that are expected to time out")
+    test_selection_group.add_argument("--skip-implementation-status",
+                                      action="append",
+                                      choices=["not-implementing", "backlog", "implementing"],
+                                      help="Skip tests that have the given implementation status")
+    # TODO: Remove this when QUIC is enabled by default.
+    test_selection_group.add_argument("--enable-quic", action="store_true", default=False,
+                                      help="Enable tests that require QUIC server (default: false)")
+
+    test_selection_group.add_argument("--tag", action="append", dest="tags",
+                                      help="Labels applied to tests to include in the run. "
+                                           "Labels starting dir: are equivalent to top-level directories.")
+    test_selection_group.add_argument("--default-exclude", action="store_true",
+                                      default=False,
+                                      help="Only run the tests explicitly given in arguments. "
+                                           "No tests will run if the list is empty, and the "
+                                           "program will exit with status code 0.")
+
+    debugging_group = parser.add_argument_group("Debugging")
+    debugging_group.add_argument('--debugger', const="__default__", nargs="?",
+                                 help="run under a debugger, e.g. gdb or valgrind")
+    debugging_group.add_argument('--debugger-args', help="arguments to the debugger")
+    debugging_group.add_argument("--rerun", action="store", type=int, default=1,
+                                 help="Number of times to re run each test without restarts")
+    debugging_group.add_argument("--repeat", action="store", type=int, default=1,
+                                 help="Number of times to run the tests, restarting between each run")
+    debugging_group.add_argument("--repeat-until-unexpected", action="store_true", default=None,
+                                 help="Run tests in a loop until one returns an unexpected result")
+    debugging_group.add_argument('--pause-after-test', action="store_true", default=None,
+                                 help="Halt the test runner after each test (this happens by default if only a single test is run)")
+    debugging_group.add_argument('--no-pause-after-test', dest="pause_after_test", action="store_false",
+                                 help="Don't halt the test runner irrespective of the number of tests run")
+
+    debugging_group.add_argument('--pause-on-unexpected', action="store_true",
+                                 help="Halt the test runner when an unexpected result is encountered")
+    debugging_group.add_argument('--no-restart-on-unexpected', dest="restart_on_unexpected",
+                                 default=True, action="store_false",
+                                 help="Don't restart on an unexpected result")
+
+    debugging_group.add_argument("--symbols-path", action="store", type=url_or_path,
+                                 help="Path or url to symbols file used to analyse crash minidumps.")
+    debugging_group.add_argument("--stackwalk-binary", action="store", type=abs_path,
+                                 help="Path to stackwalker program used to analyse minidumps.")
+
+    debugging_group.add_argument("--pdb", action="store_true",
+                                 help="Drop into pdb on python exception")
+
+    config_group = parser.add_argument_group("Configuration")
+    config_group.add_argument("--binary", action="store",
+                              type=abs_path, help="Desktop binary to run tests against")
+    config_group.add_argument('--binary-arg',
+                              default=[], action="append", dest="binary_args",
+                              help="Extra argument for the binary")
+    config_group.add_argument("--webdriver-binary", action="store", metavar="BINARY",
+                              type=abs_path, help="WebDriver server binary to use")
+    config_group.add_argument('--webdriver-arg',
+                              default=[], action="append", dest="webdriver_args",
+                              help="Extra argument for the WebDriver binary")
+    config_group.add_argument("--adb-binary", action="store",
+                              help="Path to adb binary to use")
+    config_group.add_argument("--package-name", action="store",
+                              help="Android package name to run tests against")
+    config_group.add_argument("--device-serial", action="store",
+                              help="Running Android instance to connect to, if not emulator-5554")
+    config_group.add_argument("--metadata", action="store", type=abs_path, dest="metadata_root",
+                              help="Path to root directory containing test metadata"),
+    config_group.add_argument("--tests", action="store", type=abs_path, dest="tests_root",
+                              help="Path to root directory containing test files"),
+    config_group.add_argument("--manifest", action="store", type=abs_path, dest="manifest_path",
+                              help="Path to test manifest (default is ${metadata_root}/MANIFEST.json)")
+    config_group.add_argument("--run-info", action="store", type=abs_path,
+                              help="Path to directory containing extra json files to add to run info")
+    config_group.add_argument("--product", action="store", choices=product_choices,
+                              default=None, help="Browser against which to run tests")
+    config_group.add_argument("--browser-version", action="store",
+                              default=None, help="Informative string detailing the browser "
+                              "release version. This is included in the run_info data.")
+    config_group.add_argument("--browser-channel", action="store",
+                              default=None, help="Informative string detailing the browser "
+                              "release channel. This is included in the run_info data.")
+    config_group.add_argument("--config", action="store", type=abs_path, dest="config",
+                              help="Path to config file")
+    config_group.add_argument("--install-fonts", action="store_true",
+                              default=None,
+                              help="Install additional system fonts on your system")
+    config_group.add_argument("--no-install-fonts", dest="install_fonts", action="store_false",
+                              help="Do not install additional system fonts on your system")
+    config_group.add_argument("--font-dir", action="store", type=abs_path, dest="font_dir",
+                              help="Path to local font installation directory", default=None)
+    config_group.add_argument("--headless", action="store_true",
+                              help="Run browser in headless mode", default=None)
+    config_group.add_argument("--no-headless", action="store_false", dest="headless",
+                              help="Don't run browser in headless mode")
+    config_group.add_argument("--instrument-to-file", action="store",
+                              help="Path to write instrumentation logs to")
+
+    build_type = parser.add_mutually_exclusive_group()
+    build_type.add_argument("--debug-build", dest="debug", action="store_true",
+                            default=None,
+                            help="Build is a debug build (overrides any mozinfo file)")
+    build_type.add_argument("--release-build", dest="debug", action="store_false",
+                            default=None,
+                            help="Build is a release (overrides any mozinfo file)")
+
+    chunking_group = parser.add_argument_group("Test Chunking")
+    chunking_group.add_argument("--total-chunks", action="store", type=int, default=1,
+                                help="Total number of chunks to use")
+    chunking_group.add_argument("--this-chunk", action="store", type=int, default=1,
+                                help="Chunk number to run")
+    chunking_group.add_argument("--chunk-type", action="store", choices=["none", "hash", "dir_hash"],
+                                default=None, help="Chunking type to use")
+
+    ssl_group = parser.add_argument_group("SSL/TLS")
+    ssl_group.add_argument("--ssl-type", action="store", default=None,
+                           choices=["openssl", "pregenerated", "none"],
+                           help="Type of ssl support to enable (running without ssl may lead to spurious errors)")
+
+    ssl_group.add_argument("--openssl-binary", action="store",
+                           help="Path to openssl binary", default="openssl")
+    ssl_group.add_argument("--certutil-binary", action="store",
+                           help="Path to certutil binary for use with Firefox + ssl")
+
+    ssl_group.add_argument("--ca-cert-path", action="store", type=abs_path,
+                           help="Path to ca certificate when using pregenerated ssl certificates")
+    ssl_group.add_argument("--host-key-path", action="store", type=abs_path,
+                           help="Path to host private key when using pregenerated ssl certificates")
+    ssl_group.add_argument("--host-cert-path", action="store", type=abs_path,
+                           help="Path to host certificate when using pregenerated ssl certificates")
+
+    gecko_group = parser.add_argument_group("Gecko-specific")
+    gecko_group.add_argument("--prefs-root", dest="prefs_root", action="store", type=abs_path,
+                             help="Path to the folder containing browser prefs")
+    gecko_group.add_argument("--preload-browser", dest="preload_browser", action="store_true",
+                             default=None, help="Preload a gecko instance for faster restarts")
+    gecko_group.add_argument("--no-preload-browser", dest="preload_browser", action="store_false",
+                             default=None, help="Don't preload a gecko instance for faster restarts")
+    gecko_group.add_argument("--disable-e10s", dest="gecko_e10s", action="store_false", default=True,
+                             help="Run tests without electrolysis preferences")
+    gecko_group.add_argument("--enable-webrender", dest="enable_webrender", action="store_true", default=None,
+                             help="Enable the WebRender compositor in Gecko (defaults to disabled).")
+    gecko_group.add_argument("--no-enable-webrender", dest="enable_webrender", action="store_false",
+                             help="Disable the WebRender compositor in Gecko.")
+    gecko_group.add_argument("--enable-fission", dest="enable_fission", action="store_true", default=None,
+                             help="Enable fission in Gecko (defaults to disabled).")
+    gecko_group.add_argument("--no-enable-fission", dest="enable_fission", action="store_false",
+                             help="Disable fission in Gecko.")
+    gecko_group.add_argument("--stackfix-dir", dest="stackfix_dir", action="store",
+                             help="Path to directory containing assertion stack fixing scripts")
+    gecko_group.add_argument("--specialpowers-path", action="store",
+                             help="Path to specialPowers extension xpi file")
+    gecko_group.add_argument("--setpref", dest="extra_prefs", action='append',
+                             default=[], metavar="PREF=VALUE",
+                             help="Defines an extra user preference (overrides those in prefs_root)")
+    gecko_group.add_argument("--leak-check", dest="leak_check", action="store_true", default=None,
+                             help="Enable leak checking (enabled by default for debug builds, "
+                             "silently ignored for opt, mobile)")
+    gecko_group.add_argument("--no-leak-check", dest="leak_check", action="store_false", default=None,
+                             help="Disable leak checking")
+    gecko_group.add_argument("--stylo-threads", action="store", type=int, default=1,
+                             help="Number of parallel threads to use for stylo")
+    gecko_group.add_argument("--reftest-internal", dest="reftest_internal", action="store_true",
+                             default=None, help="Enable reftest runner implemented inside Marionette")
+    gecko_group.add_argument("--reftest-external", dest="reftest_internal", action="store_false",
+                             help="Disable reftest runner implemented inside Marionette")
+    gecko_group.add_argument("--reftest-screenshot", dest="reftest_screenshot", action="store",
+                             choices=["always", "fail", "unexpected"], default=None,
+                             help="With --reftest-internal, when to take a screenshot")
+    gecko_group.add_argument("--chaos", dest="chaos_mode_flags", action="store",
+                             nargs="?", const=0xFFFFFFFF, type=int,
+                             help="Enable chaos mode with the specified feature flag "
+                             "(see http://searchfox.org/mozilla-central/source/mfbt/ChaosMode.h for "
+                             "details). If no value is supplied, all features are activated")
+
+    servo_group = parser.add_argument_group("Servo-specific")
+    servo_group.add_argument("--user-stylesheet",
+                             default=[], action="append", dest="user_stylesheets",
+                             help="Inject a user CSS stylesheet into every test.")
+
+    servo_group = parser.add_argument_group("Chrome-specific")
+    servo_group.add_argument("--enable-mojojs", action="store_true", default=False,
+                             help="Enable MojoJS for testing. Note that this flag is usally "
+                             "enabled automatically by `wpt run`, if it succeeds in downloading "
+                             "the right version of mojojs.zip or if --mojojs-path is specified.")
+    servo_group.add_argument("--mojojs-path",
+                             help="Path to mojojs gen/ directory. If it is not specified, `wpt run` "
+                             "will download and extract mojojs.zip into _venv2/mojojs/gen.")
+
+    sauce_group = parser.add_argument_group("Sauce Labs-specific")
+    sauce_group.add_argument("--sauce-browser", dest="sauce_browser",
+                             help="Sauce Labs browser name")
+    sauce_group.add_argument("--sauce-platform", dest="sauce_platform",
+                             help="Sauce Labs OS platform")
+    sauce_group.add_argument("--sauce-version", dest="sauce_version",
+                             help="Sauce Labs browser version")
+    sauce_group.add_argument("--sauce-build", dest="sauce_build",
+                             help="Sauce Labs build identifier")
+    sauce_group.add_argument("--sauce-tags", dest="sauce_tags", nargs="*",
+                             help="Sauce Labs identifying tag", default=[])
+    sauce_group.add_argument("--sauce-tunnel-id", dest="sauce_tunnel_id",
+                             help="Sauce Connect tunnel identifier")
+    sauce_group.add_argument("--sauce-user", dest="sauce_user",
+                             help="Sauce Labs user name")
+    sauce_group.add_argument("--sauce-key", dest="sauce_key",
+                             default=os.environ.get("SAUCE_ACCESS_KEY"),
+                             help="Sauce Labs access key")
+    sauce_group.add_argument("--sauce-connect-binary",
+                             dest="sauce_connect_binary",
+                             help="Path to Sauce Connect binary")
+    sauce_group.add_argument("--sauce-init-timeout", action="store",
+                             type=int, default=30,
+                             help="Number of seconds to wait for Sauce "
+                                  "Connect tunnel to be available before "
+                                  "aborting")
+    sauce_group.add_argument("--sauce-connect-arg", action="append",
+                             default=[], dest="sauce_connect_args",
+                             help="Command-line argument to forward to the "
+                                  "Sauce Connect binary (repeatable)")
+
+    taskcluster_group = parser.add_argument_group("Taskcluster-specific")
+    taskcluster_group.add_argument("--github-checks-text-file",
+                                   type=ensure_text,
+                                   help="Path to GitHub checks output file")
+
+    webkit_group = parser.add_argument_group("WebKit-specific")
+    webkit_group.add_argument("--webkit-port", dest="webkit_port",
+                              help="WebKit port")
+
+    parser.add_argument("test_list", nargs="*",
+                        help="List of URLs for tests to run, or paths including tests to run. "
+                             "(equivalent to --include)")
+
+    def screenshot_api_wrapper(formatter, api):
+        formatter.api = api
+        return formatter
+
+    commandline.fmt_options["api"] = (screenshot_api_wrapper,
+                                      "Cache API (default: %s)" % wptscreenshot.DEFAULT_API,
+                                      {"wptscreenshot"}, "store")
+
+    commandline.log_formatters["chromium"] = (chromium.ChromiumFormatter, "Chromium Layout Tests format")
+    commandline.log_formatters["wptreport"] = (wptreport.WptreportFormatter, "wptreport format")
+    commandline.log_formatters["wptscreenshot"] = (wptscreenshot.WptscreenshotFormatter, "wpt.fyi screenshots")
+
+    commandline.add_logging_group(parser)
+    return parser
+
+
+def set_from_config(kwargs):
+    if kwargs["config"] is None:
+        config_path = config.path()
+    else:
+        config_path = kwargs["config"]
+
+    kwargs["config_path"] = config_path
+
+    kwargs["config"] = config.read(kwargs["config_path"])
+
+    keys = {"paths": [("prefs", "prefs_root", True),
+                      ("run_info", "run_info", True)],
+            "web-platform-tests": [("remote_url", "remote_url", False),
+                                   ("branch", "branch", False),
+                                   ("sync_path", "sync_path", True)],
+            "SSL": [("openssl_binary", "openssl_binary", True),
+                    ("certutil_binary", "certutil_binary", True),
+                    ("ca_cert_path", "ca_cert_path", True),
+                    ("host_cert_path", "host_cert_path", True),
+                    ("host_key_path", "host_key_path", True)]}
+
+    for section, values in iteritems(keys):
+        for config_value, kw_value, is_path in values:
+            if kw_value in kwargs and kwargs[kw_value] is None:
+                if not is_path:
+                    new_value = kwargs["config"].get(section, config.ConfigDict({})).get(config_value)
+                else:
+                    new_value = kwargs["config"].get(section, config.ConfigDict({})).get_path(config_value)
+                kwargs[kw_value] = new_value
+
+    kwargs["test_paths"] = get_test_paths(kwargs["config"])
+
+    if kwargs["tests_root"]:
+        if "/" not in kwargs["test_paths"]:
+            kwargs["test_paths"]["/"] = {}
+        kwargs["test_paths"]["/"]["tests_path"] = kwargs["tests_root"]
+
+    if kwargs["metadata_root"]:
+        if "/" not in kwargs["test_paths"]:
+            kwargs["test_paths"]["/"] = {}
+        kwargs["test_paths"]["/"]["metadata_path"] = kwargs["metadata_root"]
+
+    if kwargs.get("manifest_path"):
+        if "/" not in kwargs["test_paths"]:
+            kwargs["test_paths"]["/"] = {}
+        kwargs["test_paths"]["/"]["manifest_path"] = kwargs["manifest_path"]
+
+    kwargs["suite_name"] = kwargs["config"].get("web-platform-tests", {}).get("name", "web-platform-tests")
+
+
+    check_paths(kwargs)
+
+
+def get_test_paths(config):
+    # Set up test_paths
+    test_paths = OrderedDict()
+
+    for section in iterkeys(config):
+        if section.startswith("manifest:"):
+            manifest_opts = config.get(section)
+            url_base = manifest_opts.get("url_base", "/")
+            test_paths[url_base] = {
+                "tests_path": manifest_opts.get_path("tests"),
+                "metadata_path": manifest_opts.get_path("metadata"),
+            }
+            if "manifest" in manifest_opts:
+                test_paths[url_base]["manifest_path"] = manifest_opts.get_path("manifest")
+
+    return test_paths
+
+
+def exe_path(name):
+    if name is None:
+        return
+
+    path = find_executable(name)
+    if path and os.access(path, os.X_OK):
+        return path
+    else:
+        return None
+
+
+def check_paths(kwargs):
+    for test_paths in itervalues(kwargs["test_paths"]):
+        if not ("tests_path" in test_paths and
+                "metadata_path" in test_paths):
+            print("Fatal: must specify both a test path and metadata path")
+            sys.exit(1)
+        if "manifest_path" not in test_paths:
+            test_paths["manifest_path"] = os.path.join(test_paths["metadata_path"],
+                                                       "MANIFEST.json")
+        for key, path in iteritems(test_paths):
+            name = key.split("_", 1)[0]
+
+            if name == "manifest":
+                # For the manifest we can create it later, so just check the path
+                # actually exists
+                path = os.path.dirname(path)
+
+            if not os.path.exists(path):
+                print("Fatal: %s path %s does not exist" % (name, path))
+                sys.exit(1)
+
+            if not os.path.isdir(path):
+                print("Fatal: %s path %s is not a directory" % (name, path))
+                sys.exit(1)
+
+
+def check_args(kwargs):
+    set_from_config(kwargs)
+
+    if kwargs["product"] is None:
+        kwargs["product"] = "firefox"
+
+    if kwargs["manifest_update"] is None:
+        kwargs["manifest_update"] = True
+
+    if "sauce" in kwargs["product"]:
+        kwargs["pause_after_test"] = False
+
+    if kwargs["test_list"]:
+        if kwargs["include"] is not None:
+            kwargs["include"].extend(kwargs["test_list"])
+        else:
+            kwargs["include"] = kwargs["test_list"]
+
+    if kwargs["run_info"] is None:
+        kwargs["run_info"] = kwargs["config_path"]
+
+    if kwargs["this_chunk"] > 1:
+        require_arg(kwargs, "total_chunks", lambda x: x >= kwargs["this_chunk"])
+
+    if kwargs["chunk_type"] is None:
+        if kwargs["total_chunks"] > 1:
+            kwargs["chunk_type"] = "dir_hash"
+        else:
+            kwargs["chunk_type"] = "none"
+
+    if kwargs["test_groups_file"] is not None:
+        if kwargs["run_by_dir"] is not False:
+            print("Can't pass --test-groups and --run-by-dir")
+            sys.exit(1)
+        if not os.path.exists(kwargs["test_groups_file"]):
+            print("--test-groups file %s not found" % kwargs["test_groups_file"])
+            sys.exit(1)
+
+    if kwargs["processes"] is None:
+        kwargs["processes"] = 1
+
+    if kwargs["debugger"] is not None:
+        import mozdebug
+        if kwargs["debugger"] == "__default__":
+            kwargs["debugger"] = mozdebug.get_default_debugger_name()
+        debug_info = mozdebug.get_debugger_info(kwargs["debugger"],
+                                                kwargs["debugger_args"])
+        if debug_info and debug_info.interactive:
+            if kwargs["processes"] != 1:
+                kwargs["processes"] = 1
+            kwargs["no_capture_stdio"] = True
+        kwargs["debug_info"] = debug_info
+    else:
+        kwargs["debug_info"] = None
+
+    if kwargs["binary"] is not None:
+        if not os.path.exists(kwargs["binary"]):
+            print("Binary path %s does not exist" % kwargs["binary"], file=sys.stderr)
+            sys.exit(1)
+
+    if kwargs["ssl_type"] is None:
+        if None not in (kwargs["ca_cert_path"], kwargs["host_cert_path"], kwargs["host_key_path"]):
+            kwargs["ssl_type"] = "pregenerated"
+        elif exe_path(kwargs["openssl_binary"]) is not None:
+            kwargs["ssl_type"] = "openssl"
+        else:
+            kwargs["ssl_type"] = "none"
+
+    if kwargs["ssl_type"] == "pregenerated":
+        require_arg(kwargs, "ca_cert_path", lambda x:os.path.exists(x))
+        require_arg(kwargs, "host_cert_path", lambda x:os.path.exists(x))
+        require_arg(kwargs, "host_key_path", lambda x:os.path.exists(x))
+
+    elif kwargs["ssl_type"] == "openssl":
+        path = exe_path(kwargs["openssl_binary"])
+        if path is None:
+            print("openssl-binary argument missing or not a valid executable", file=sys.stderr)
+            sys.exit(1)
+        kwargs["openssl_binary"] = path
+
+    if kwargs["ssl_type"] != "none" and kwargs["product"] == "firefox" and kwargs["certutil_binary"]:
+        path = exe_path(kwargs["certutil_binary"])
+        if path is None:
+            print("certutil-binary argument missing or not a valid executable", file=sys.stderr)
+            sys.exit(1)
+        kwargs["certutil_binary"] = path
+
+    if kwargs['extra_prefs']:
+        missing = any('=' not in prefarg for prefarg in kwargs['extra_prefs'])
+        if missing:
+            print("Preferences via --setpref must be in key=value format", file=sys.stderr)
+            sys.exit(1)
+        kwargs['extra_prefs'] = [tuple(prefarg.split('=', 1)) for prefarg in
+                                 kwargs['extra_prefs']]
+
+    if kwargs["reftest_internal"] is None:
+        kwargs["reftest_internal"] = True
+
+    if kwargs["reftest_screenshot"] is None:
+        kwargs["reftest_screenshot"] = "unexpected"
+
+    if kwargs["enable_webrender"] is None:
+        kwargs["enable_webrender"] = False
+
+    if kwargs["preload_browser"] is None:
+        # Default to preloading a gecko instance if we're only running a single process
+        kwargs["preload_browser"] = kwargs["processes"] == 1
+
+    return kwargs
+
+
+def check_args_update(kwargs):
+    set_from_config(kwargs)
+
+    if kwargs["product"] is None:
+        kwargs["product"] = "firefox"
+    if kwargs["patch"] is None:
+        kwargs["patch"] = kwargs["sync"]
+
+    for item in kwargs["run_log"]:
+        if os.path.isdir(item):
+            print("Log file %s is a directory" % item, file=sys.stderr)
+            sys.exit(1)
+
+    return kwargs
+
+
+def create_parser_update(product_choices=None):
+    from mozlog.structured import commandline
+
+    from . import products
+
+    if product_choices is None:
+        config_data = config.load()
+        product_choices = products.products_enabled(config_data)
+
+    parser = argparse.ArgumentParser("web-platform-tests-update",
+                                     description="Update script for web-platform-tests tests.")
+    parser.add_argument("--product", action="store", choices=product_choices,
+                        default=None, help="Browser for which metadata is being updated")
+    parser.add_argument("--config", action="store", type=abs_path, help="Path to config file")
+    parser.add_argument("--metadata", action="store", type=abs_path, dest="metadata_root",
+                        help="Path to the folder containing test metadata"),
+    parser.add_argument("--tests", action="store", type=abs_path, dest="tests_root",
+                        help="Path to web-platform-tests"),
+    parser.add_argument("--manifest", action="store", type=abs_path, dest="manifest_path",
+                        help="Path to test manifest (default is ${metadata_root}/MANIFEST.json)")
+    parser.add_argument("--sync-path", action="store", type=abs_path,
+                        help="Path to store git checkout of web-platform-tests during update"),
+    parser.add_argument("--remote_url", action="store",
+                        help="URL of web-platfrom-tests repository to sync against"),
+    parser.add_argument("--branch", action="store", type=abs_path,
+                        help="Remote branch to sync against")
+    parser.add_argument("--rev", action="store", help="Revision to sync to")
+    parser.add_argument("--patch", action="store_true", dest="patch", default=None,
+                        help="Create a VCS commit containing the changes.")
+    parser.add_argument("--no-patch", action="store_false", dest="patch",
+                        help="Don't create a VCS commit containing the changes.")
+    parser.add_argument("--sync", dest="sync", action="store_true", default=False,
+                        help="Sync the tests with the latest from upstream (implies --patch)")
+    parser.add_argument("--full", action="store_true", default=False,
+                        help=("For all tests that are updated, remove any existing conditions and missing subtests"))
+    parser.add_argument("--disable-intermittent", nargs="?", action="store", const="unstable", default=None,
+        help=("Reason for disabling tests. When updating test results, disable tests that have "
+              "inconsistent results across many runs with the given reason."))
+    parser.add_argument("--update-intermittent", action="store_true", default=False,
+                        help=("Update test metadata with expected intermittent statuses."))
+    parser.add_argument("--remove-intermittent", action="store_true", default=False,
+                        help=("Remove obsolete intermittent statuses from expected statuses."))
+    parser.add_argument("--no-remove-obsolete", action="store_false", dest="remove_obsolete", default=True,
+                        help=("Don't remove metadata files that no longer correspond to a test file"))
+    parser.add_argument("--no-store-state", action="store_false", dest="store_state",
+                        help="Store state so that steps can be resumed after failure")
+    parser.add_argument("--continue", action="store_true",
+                        help="Continue a previously started run of the update script")
+    parser.add_argument("--abort", action="store_true",
+                        help="Clear state from a previous incomplete run of the update script")
+    parser.add_argument("--exclude", action="store", nargs="*",
+                        help="List of glob-style paths to exclude when syncing tests")
+    parser.add_argument("--include", action="store", nargs="*",
+                        help="List of glob-style paths to include which would otherwise be excluded when syncing tests")
+    parser.add_argument("--extra-property", action="append", default=[],
+                        help="Extra property from run_info.json to use in metadata update")
+    # Should make this required iff run=logfile
+    parser.add_argument("run_log", nargs="*", type=abs_path,
+                        help="Log file from run of tests")
+    commandline.add_logging_group(parser)
+    return parser
+
+
+def create_parser_reduce(product_choices=None):
+    parser = create_parser(product_choices)
+    parser.add_argument("target", action="store", help="Test id that is unstable")
+    return parser
+
+
+def parse_args():
+    parser = create_parser()
+    rv = vars(parser.parse_args())
+    check_args(rv)
+    return rv
+
+
+def parse_args_update():
+    parser = create_parser_update()
+    rv = vars(parser.parse_args())
+    check_args_update(rv)
+    return rv
+
+
+def parse_args_reduce():
+    parser = create_parser_reduce()
+    rv = vars(parser.parse_args())
+    check_args(rv)
+    return rv
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptlogging.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptlogging.py
new file mode 100644
index 0000000..444d1d9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptlogging.py
@@ -0,0 +1,67 @@
+import logging
+
+from mozlog import commandline, stdadapter, set_default_logger
+from mozlog.structuredlog import StructuredLogger, log_levels
+
+
+def setup(args, defaults, formatter_defaults=None):
+    logger = args.pop('log', None)
+    if logger:
+        set_default_logger(logger)
+        StructuredLogger._logger_states["web-platform-tests"] = logger._state
+    else:
+        logger = commandline.setup_logging("web-platform-tests", args, defaults,
+                                           formatter_defaults=formatter_defaults)
+    setup_stdlib_logger()
+
+    for name in list(args.keys()):
+        if name.startswith("log_"):
+            args.pop(name)
+
+    return logger
+
+
+def setup_stdlib_logger():
+    logging.root.handlers = []
+    logging.root = stdadapter.std_logging_adapter(logging.root)
+
+
+class LogLevelRewriter(object):
+    """Filter that replaces log messages at specified levels with messages
+    at a different level.
+
+    This can be used to e.g. downgrade log messages from ERROR to WARNING
+    in some component where ERRORs are not critical.
+
+    :param inner: Handler to use for messages that pass this filter
+    :param from_levels: List of levels which should be affected
+    :param to_level: Log level to set for the affected messages
+    """
+    def __init__(self, inner, from_levels, to_level):
+        self.inner = inner
+        self.from_levels = [item.upper() for item in from_levels]
+        self.to_level = to_level.upper()
+
+    def __call__(self, data):
+        if data["action"] == "log" and data["level"].upper() in self.from_levels:
+            data = data.copy()
+            data["level"] = self.to_level
+        return self.inner(data)
+
+
+class LoggedAboveLevelHandler(object):
+    """Filter that records whether any log message above a certain level has been
+    seen.
+
+    :param min_level: Minimum level to record as a str (e.g., "CRITICAL")
+
+    """
+    def __init__(self, min_level):
+        self.min_level = log_levels[min_level.upper()]
+        self.has_log = False
+
+    def __call__(self, data):
+        if (data["action"] == "log" and
+            not self.has_log and
+            log_levels[data["level"]] <= self.min_level):
+            self.has_log = True
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/__init__.py
new file mode 100644
index 0000000..e354d5f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/__init__.py
@@ -0,0 +1,5 @@
+# flake8: noqa (not ideal, but nicer than adding noqa: F401 to every line!)
+from .serializer import serialize
+from .parser import parse
+from .backends.static import compile as compile_static
+from .backends.conditional import compile as compile_condition
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/__init__.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py
new file mode 100644
index 0000000..c539d43
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/base.py
@@ -0,0 +1,223 @@
+import abc
+from six import iteritems, iterkeys, itervalues
+
+from ..node import NodeVisitor
+from ..parser import parse
+
+
+class Compiler(NodeVisitor):
+    __metaclass__ = abc.ABCMeta
+
+    def compile(self, tree, data_cls_getter=None, **kwargs):
+        self._kwargs = kwargs
+        return self._compile(tree, data_cls_getter, **kwargs)
+
+    def _compile(self, tree, data_cls_getter=None, **kwargs):
+        """Compile a raw AST into a form where conditional expressions
+        are represented by ConditionalValue objects that can be evaluated
+        at runtime.
+
+        tree - The root node of the wptmanifest AST to compile
+
+        data_cls_getter - A function taking two parameters; the previous
+                          output node and the current ast node and returning
+                          the class of the output node to use for the current
+                          ast node
+        """
+        if data_cls_getter is None:
+            self.data_cls_getter = lambda x, y: ManifestItem
+        else:
+            self.data_cls_getter = data_cls_getter
+
+        self.tree = tree
+        self.output_node = self._initial_output_node(tree, **kwargs)
+        self.visit(tree)
+        if hasattr(self.output_node, "set_defaults"):
+            self.output_node.set_defaults()
+        assert self.output_node is not None
+        return self.output_node
+
+    def _initial_output_node(self, node, **kwargs):
+        return self.data_cls_getter(None, None)(node, **kwargs)
+
+    def visit_DataNode(self, node):
+        if node != self.tree:
+            output_parent = self.output_node
+            self.output_node = self.data_cls_getter(self.output_node, node)(node, **self._kwargs)
+        else:
+            output_parent = None
+
+        assert self.output_node is not None
+
+        for child in node.children:
+            self.visit(child)
+
+        if output_parent is not None:
+            # Append to the parent *after* processing all the node data
+            output_parent.append(self.output_node)
+            self.output_node = self.output_node.parent
+
+        assert self.output_node is not None
+
+    @abc.abstractmethod
+    def visit_KeyValueNode(self, node):
+        pass
+
+    def visit_ListNode(self, node):
+        return [self.visit(child) for child in node.children]
+
+    def visit_ValueNode(self, node):
+        return node.data
+
+    def visit_AtomNode(self, node):
+        return node.data
+
+    @abc.abstractmethod
+    def visit_ConditionalNode(self, node):
+        pass
+
+    def visit_StringNode(self, node):
+        indexes = [self.visit(child) for child in node.children]
+
+        def value(x):
+            rv = node.data
+            for index in indexes:
+                rv = rv[index(x)]
+            return rv
+        return value
+
+    def visit_NumberNode(self, node):
+        if "." in node.data:
+            return float(node.data)
+        else:
+            return int(node.data)
+
+    def visit_VariableNode(self, node):
+        indexes = [self.visit(child) for child in node.children]
+
+        def value(x):
+            data = x[node.data]
+            for index in indexes:
+                data = data[index(x)]
+            return data
+        return value
+
+    def visit_IndexNode(self, node):
+        assert len(node.children) == 1
+        return self.visit(node.children[0])
+
+    @abc.abstractmethod
+    def visit_UnaryExpressionNode(self, node):
+        pass
+
+    @abc.abstractmethod
+    def visit_BinaryExpressionNode(self, node):
+        pass
+
+    @abc.abstractmethod
+    def visit_UnaryOperatorNode(self, node):
+        pass
+
+    @abc.abstractmethod
+    def visit_BinaryOperatorNode(self, node):
+        pass
+
+
+class ManifestItem(object):
+    def __init__(self, node, **kwargs):
+        self.parent = None
+        self.node = node
+        self.children = []
+        self._data = {}
+
+    def __repr__(self):
+        return "<%s %s>" % (self.__class__, self.node.data)
+
+    def __str__(self):
+        rv = [repr(self)]
+        for item in self.children:
+            rv.extend("  %s" % line for line in str(item).split("\n"))
+        return "\n".join(rv)
+
+    def set_defaults(self):
+        pass
+
+    @property
+    def is_empty(self):
+        if self._data:
+            return False
+        return all(child.is_empty for child in self.children)
+
+    @property
+    def root(self):
+        node = self
+        while node.parent is not None:
+            node = node.parent
+        return node
+
+    @property
+    def name(self):
+        return self.node.data
+
+    def get(self, key):
+        for node in [self, self.root]:
+            if key in node._data:
+                return node._data[key]
+        raise KeyError
+
+    def set(self, name, value):
+        self._data[name] = value
+
+    def remove(self):
+        if self.parent:
+            self.parent.children.remove(self)
+            self.parent = None
+
+    def iterchildren(self, name=None):
+        for item in self.children:
+            if item.name == name or name is None:
+                yield item
+
+    def has_key(self, key):
+        for node in [self, self.root]:
+            if key in node._data:
+                return True
+        return False
+
+    def _flatten(self):
+        rv = {}
+        for node in [self, self.root]:
+            for name, value in iteritems(node._data):
+                if name not in rv:
+                    rv[name] = value
+        return rv
+
+    def iteritems(self):
+        for item in iteritems(self._flatten()):
+            yield item
+
+    def iterkeys(self):
+        for item in iterkeys(self._flatten()):
+            yield item
+
+    def itervalues(self):
+        for item in itervalues(self._flatten()):
+            yield item
+
+    def append(self, child):
+        child.parent = self
+        self.children.append(child)
+        return child
+
+
+def compile_ast(compiler, ast, data_cls_getter=None, **kwargs):
+    return compiler().compile(ast,
+                              data_cls_getter=data_cls_getter,
+                              **kwargs)
+
+
+def compile(compiler, stream, data_cls_getter=None, **kwargs):
+    return compile_ast(compiler,
+                       parse(stream),
+                       data_cls_getter=data_cls_getter,
+                       **kwargs)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py
new file mode 100644
index 0000000..3b11e83
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/conditional.py
@@ -0,0 +1,407 @@
+import operator
+from six import ensure_text, iteritems, iterkeys, text_type
+
+from ..node import NodeVisitor, DataNode, ConditionalNode, KeyValueNode, ListNode, ValueNode, BinaryExpressionNode, VariableNode
+from ..parser import parse
+
+
+class ConditionalValue(object):
+    def __init__(self, node, condition_func):
+        self.node = node
+        assert callable(condition_func)
+        self.condition_func = condition_func
+        if isinstance(node, ConditionalNode):
+            assert len(node.children) == 2
+            self.condition_node = self.node.children[0]
+            assert isinstance(node.children[1], (ValueNode, ListNode))
+            self.value_node = self.node.children[1]
+        else:
+            assert isinstance(node, (ValueNode, ListNode))
+            self.condition_node = None
+            self.value_node = self.node
+
+    @property
+    def value(self):
+        if isinstance(self.value_node, ValueNode):
+            return self.value_node.data
+        else:
+            return [item.data for item in self.value_node.children]
+
+    @value.setter
+    def value(self, value):
+        if isinstance(self.value_node, ValueNode):
+            self.value_node.data = value
+        else:
+            assert(isinstance(self.value_node, ListNode))
+            while self.value_node.children:
+                self.value_node.children[0].remove()
+            assert len(self.value_node.children) == 0
+            for list_value in value:
+                self.value_node.append(ValueNode(list_value))
+
+    def __call__(self, run_info):
+        return self.condition_func(run_info)
+
+    def set_value(self, value):
+        self.value = ensure_text(value)
+
+    def value_as(self, type_func):
+        """Get value and convert to a given type.
+
+        This is unfortunate, but we don't currently have a good way to specify that
+        specific properties should have their data returned as specific types"""
+        value = self.value
+        if type_func is not None:
+            value = type_func(value)
+        return value
+
+    def remove(self):
+        if len(self.node.parent.children) == 1:
+            self.node.parent.remove()
+        self.node.remove()
+
+    @property
+    def variables(self):
+        rv = set()
+        if self.condition_node is None:
+            return rv
+        stack = [self.condition_node]
+        while stack:
+            node = stack.pop()
+            if isinstance(node, VariableNode):
+                rv.add(node.data)
+            for child in reversed(node.children):
+                stack.append(child)
+        return rv
+
+
+class Compiler(NodeVisitor):
+    def compile(self, tree, data_cls_getter=None, **kwargs):
+        """Compile a raw AST into a form where conditional expressions
+        are represented by ConditionalValue objects that can be evaluated
+        at runtime.
+
+        tree - The root node of the wptmanifest AST to compile
+
+        data_cls_getter - A function taking two parameters; the previous
+                          output node and the current ast node and returning
+                          the class of the output node to use for the current
+                          ast node
+        """
+        if data_cls_getter is None:
+            self.data_cls_getter = lambda x, y: ManifestItem
+        else:
+            self.data_cls_getter = data_cls_getter
+
+        self.tree = tree
+        self.output_node = self._initial_output_node(tree, **kwargs)
+        self.visit(tree)
+        if hasattr(self.output_node, "set_defaults"):
+            self.output_node.set_defaults()
+        assert self.output_node is not None
+        return self.output_node
+
+    def compile_condition(self, condition):
+        """Compile a ConditionalNode into a ConditionalValue.
+
+        condition: A ConditionalNode"""
+        data_node = DataNode()
+        key_value_node = KeyValueNode()
+        key_value_node.append(condition.copy())
+        data_node.append(key_value_node)
+        manifest_item = self.compile(data_node)
+        return manifest_item._data[None][0]
+
+    def _initial_output_node(self, node, **kwargs):
+        return self.data_cls_getter(None, None)(node, **kwargs)
+
+    def visit_DataNode(self, node):
+        if node != self.tree:
+            output_parent = self.output_node
+            self.output_node = self.data_cls_getter(self.output_node, node)(node)
+        else:
+            output_parent = None
+
+        assert self.output_node is not None
+
+        for child in node.children:
+            self.visit(child)
+
+        if output_parent is not None:
+            # Append to the parent *after* processing all the node data
+            output_parent.append(self.output_node)
+            self.output_node = self.output_node.parent
+
+        assert self.output_node is not None
+
+    def visit_KeyValueNode(self, node):
+        key_values = []
+        for child in node.children:
+            condition, value = self.visit(child)
+            key_values.append(ConditionalValue(child, condition))
+
+        self.output_node._add_key_value(node, key_values)
+
+    def visit_ListNode(self, node):
+        return (lambda x:True, [self.visit(child) for child in node.children])
+
+    def visit_ValueNode(self, node):
+        return (lambda x: True, node.data)
+
+    def visit_AtomNode(self, node):
+        return (lambda x: True, node.data)
+
+    def visit_ConditionalNode(self, node):
+        return self.visit(node.children[0]), self.visit(node.children[1])
+
+    def visit_StringNode(self, node):
+        indexes = [self.visit(child) for child in node.children]
+
+        def value(x):
+            rv = node.data
+            for index in indexes:
+                rv = rv[index(x)]
+            return rv
+        return value
+
+    def visit_NumberNode(self, node):
+        if "." in node.data:
+            return lambda x: float(node.data)
+        else:
+            return lambda x: int(node.data)
+
+    def visit_VariableNode(self, node):
+        indexes = [self.visit(child) for child in node.children]
+
+        def value(x):
+            data = x[node.data]
+            for index in indexes:
+                data = data[index(x)]
+            return data
+        return value
+
+    def visit_IndexNode(self, node):
+        assert len(node.children) == 1
+        return self.visit(node.children[0])
+
+    def visit_UnaryExpressionNode(self, node):
+        assert len(node.children) == 2
+        operator = self.visit(node.children[0])
+        operand = self.visit(node.children[1])
+
+        return lambda x: operator(operand(x))
+
+    def visit_BinaryExpressionNode(self, node):
+        assert len(node.children) == 3
+        operator = self.visit(node.children[0])
+        operand_0 = self.visit(node.children[1])
+        operand_1 = self.visit(node.children[2])
+
+        assert operand_0 is not None
+        assert operand_1 is not None
+
+        return lambda x: operator(operand_0(x), operand_1(x))
+
+    def visit_UnaryOperatorNode(self, node):
+        return {"not": operator.not_}[node.data]
+
+    def visit_BinaryOperatorNode(self, node):
+        assert isinstance(node.parent, BinaryExpressionNode)
+        return {"and": operator.and_,
+                "or": operator.or_,
+                "==": operator.eq,
+                "!=": operator.ne}[node.data]
+
+
+class ManifestItem(object):
+    def __init__(self, node=None, **kwargs):
+        self.node = node
+        self.parent = None
+        self.children = []
+        self._data = {}
+
+    def __repr__(self):
+        return "<conditional.ManifestItem %s>" % (self.node.data)
+
+    def __str__(self):
+        rv = [repr(self)]
+        for item in self.children:
+            rv.extend("  %s" % line for line in str(item).split("\n"))
+        return "\n".join(rv)
+
+    def __contains__(self, key):
+        return key in self._data
+
+    def __iter__(self):
+        yield self
+        for child in self.children:
+            for node in child:
+                yield node
+
+    @property
+    def is_empty(self):
+        if self._data:
+            return False
+        return all(child.is_empty for child in self.children)
+
+    @property
+    def root(self):
+        node = self
+        while node.parent is not None:
+            node = node.parent
+        return node
+
+    @property
+    def name(self):
+        return self.node.data
+
+    def has_key(self, key):
+        for node in [self, self.root]:
+            if key in node._data:
+                return True
+        return False
+
+    def get(self, key, run_info=None):
+        if run_info is None:
+            run_info = {}
+
+        for node in [self, self.root]:
+            if key in node._data:
+                for cond_value in node._data[key]:
+                    try:
+                        matches = cond_value(run_info)
+                    except KeyError:
+                        matches = False
+                    if matches:
+                        return cond_value.value
+        raise KeyError
+
+    def set(self, key, value, condition=None):
+        # First try to update the existing value
+        if key in self._data:
+            cond_values = self._data[key]
+            for cond_value in cond_values:
+                if cond_value.condition_node == condition:
+                    cond_value.value = value
+                    return
+            # If there isn't a conditional match reuse the existing KeyValueNode as the
+            # parent
+            node = None
+            for child in self.node.children:
+                if child.data == key:
+                    node = child
+                    break
+            assert node is not None
+
+        else:
+            node = KeyValueNode(key)
+            self.node.append(node)
+
+        if isinstance(value, list):
+            value_node = ListNode()
+            for item in value:
+                value_node.append(ValueNode(text_type(item)))
+        else:
+            value_node = ValueNode(text_type(value))
+        if condition is not None:
+            if not isinstance(condition, ConditionalNode):
+                conditional_node = ConditionalNode()
+                conditional_node.append(condition)
+                conditional_node.append(value_node)
+            else:
+                conditional_node = condition
+            node.append(conditional_node)
+            cond_value = Compiler().compile_condition(conditional_node)
+        else:
+            node.append(value_node)
+            cond_value = ConditionalValue(value_node, lambda x: True)
+
+        # Update the cache of child values. This is pretty annoying and maybe
+        # it should just work directly on the tree
+        if key not in self._data:
+            self._data[key] = []
+        if self._data[key] and self._data[key][-1].condition_node is None:
+            self._data[key].insert(len(self._data[key]) - 1, cond_value)
+        else:
+            self._data[key].append(cond_value)
+
+    def clear(self, key):
+        """Clear all the expected data for this node"""
+        if key in self._data:
+            for child in self.node.children:
+                if (isinstance(child, KeyValueNode) and
+                    child.data == key):
+                    child.remove()
+                    del self._data[key]
+                    break
+
+    def get_conditions(self, property_name):
+        if property_name in self._data:
+            return self._data[property_name]
+        return []
+
+    def _add_key_value(self, node, values):
+        """Called during construction to set a key-value node"""
+        self._data[node.data] = values
+
+    def append(self, child):
+        self.children.append(child)
+        child.parent = self
+        if child.node.parent != self.node:
+            self.node.append(child.node)
+        return child
+
+    def remove(self):
+        if self.parent:
+            self.parent._remove_child(self)
+
+    def _remove_child(self, child):
+        self.children.remove(child)
+        child.parent = None
+        child.node.remove()
+
+    def iterchildren(self, name=None):
+        for item in self.children:
+            if item.name == name or name is None:
+                yield item
+
+    def _flatten(self):
+        rv = {}
+        for node in [self, self.root]:
+            for name, value in iteritems(node._data):
+                if name not in rv:
+                    rv[name] = value
+        return rv
+
+    def iteritems(self):
+        for item in iteritems(self._flatten()):
+            yield item
+
+    def iterkeys(self):
+        for item in iterkeys(self._flatten()):
+            yield item
+
+    def iter_properties(self):
+        for item in self._data:
+            yield item, self._data[item]
+
+    def remove_value(self, key, value):
+        if key not in self._data:
+            return
+        try:
+            self._data[key].remove(value)
+        except ValueError:
+            return
+        if not self._data[key]:
+            del self._data[key]
+        value.remove()
+
+
+def compile_ast(ast, data_cls_getter=None, **kwargs):
+    return Compiler().compile(ast, data_cls_getter=data_cls_getter, **kwargs)
+
+
+def compile(stream, data_cls_getter=None, **kwargs):
+    return compile_ast(parse(stream),
+                       data_cls_getter=data_cls_getter,
+                       **kwargs)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/static.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/static.py
new file mode 100644
index 0000000..6efad1c
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/backends/static.py
@@ -0,0 +1,100 @@
+import operator
+
+from . import base
+from ..parser import parse
+
+
+class Compiler(base.Compiler):
+    """Compiler backend that evaluates conditional expressions
+    to give static output"""
+
+    def compile(self, tree, expr_data, data_cls_getter=None, **kwargs):
+        """Compile a raw AST into a form with conditional expressions
+        evaluated.
+
+        tree - The root node of the wptmanifest AST to compile
+
+        expr_data - A dictionary of key / value pairs to use when
+                    evaluating conditional expressions
+
+        data_cls_getter - A function taking two parameters; the previous
+                          output node and the current ast node and returning
+                          the class of the output node to use for the current
+                          ast node
+        """
+
+        self._kwargs = kwargs
+        self.expr_data = expr_data
+
+        return self._compile(tree, data_cls_getter, **kwargs)
+
+    def visit_KeyValueNode(self, node):
+        key_name = node.data
+        key_value = None
+        for child in node.children:
+            value = self.visit(child)
+            if value is not None:
+                key_value = value
+                break
+        if key_value is not None:
+            self.output_node.set(key_name, key_value)
+
+    def visit_ConditionalNode(self, node):
+        assert len(node.children) == 2
+        if self.visit(node.children[0]):
+            return self.visit(node.children[1])
+
+    def visit_StringNode(self, node):
+        value = node.data
+        for child in node.children:
+            value = self.visit(child)(value)
+        return value
+
+    def visit_VariableNode(self, node):
+        value = self.expr_data[node.data]
+        for child in node.children:
+            value = self.visit(child)(value)
+        return value
+
+    def visit_IndexNode(self, node):
+        assert len(node.children) == 1
+        index = self.visit(node.children[0])
+        return lambda x: x[index]
+
+    def visit_UnaryExpressionNode(self, node):
+        assert len(node.children) == 2
+        operator = self.visit(node.children[0])
+        operand = self.visit(node.children[1])
+
+        return operator(operand)
+
+    def visit_BinaryExpressionNode(self, node):
+        assert len(node.children) == 3
+        operator = self.visit(node.children[0])
+        operand_0 = self.visit(node.children[1])
+        operand_1 = self.visit(node.children[2])
+
+        return operator(operand_0, operand_1)
+
+    def visit_UnaryOperatorNode(self, node):
+        return {"not": operator.not_}[node.data]
+
+    def visit_BinaryOperatorNode(self, node):
+        return {"and": operator.and_,
+                "or": operator.or_,
+                "==": operator.eq,
+                "!=": operator.ne}[node.data]
+
+
+def compile_ast(ast, expr_data, data_cls_getter=None, **kwargs):
+    return Compiler().compile(ast,
+                              expr_data,
+                              data_cls_getter=data_cls_getter,
+                              **kwargs)
+
+
+def compile(stream, expr_data, data_cls_getter=None, **kwargs):
+    return compile_ast(parse(stream),
+                       expr_data,
+                       data_cls_getter=data_cls_getter,
+                       **kwargs)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py
new file mode 100644
index 0000000..0f82d70
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/node.py
@@ -0,0 +1,172 @@
+from six.moves import range
+
+class NodeVisitor(object):
+    def visit(self, node):
+        # This is ugly as hell, but we don't have multimethods and
+        # they aren't trivial to fake without access to the class
+        # object from the class body
+        func = getattr(self, "visit_%s" % (node.__class__.__name__))
+        return func(node)
+
+
+class Node(object):
+    def __init__(self, data=None):
+        self.data = data
+        self.parent = None
+        self.children = []
+
+    def append(self, other):
+        other.parent = self
+        self.children.append(other)
+
+    def remove(self):
+        self.parent.children.remove(self)
+
+    def __repr__(self):
+        return "<%s %s>" % (self.__class__.__name__, self.data)
+
+    def __str__(self):
+        rv = [repr(self)]
+        for item in self.children:
+            rv.extend("  %s" % line for line in str(item).split("\n"))
+        return "\n".join(rv)
+
+    def __eq__(self, other):
+        if not (self.__class__ == other.__class__ and
+                self.data == other.data and
+                len(self.children) == len(other.children)):
+            return False
+        for child, other_child in zip(self.children, other.children):
+            if not child == other_child:
+                return False
+        return True
+
+    def copy(self):
+        new = self.__class__(self.data)
+        for item in self.children:
+            new.append(item.copy())
+        return new
+
+
+class DataNode(Node):
+    def append(self, other):
+        # Append that retains the invariant that child data nodes
+        # come after child nodes of other types
+        other.parent = self
+        if isinstance(other, DataNode):
+            self.children.append(other)
+        else:
+            index = len(self.children)
+            while index > 0 and isinstance(self.children[index - 1], DataNode):
+                index -= 1
+            for i in range(index):
+                if other.data == self.children[i].data:
+                    raise ValueError("Duplicate key %s" % self.children[i].data)
+            self.children.insert(index, other)
+
+
+class KeyValueNode(Node):
+    def append(self, other):
+        # Append that retains the invariant that conditional nodes
+        # come before unconditional nodes
+        other.parent = self
+        if not isinstance(other, (ListNode, ValueNode, ConditionalNode)):
+            raise TypeError
+        if isinstance(other, (ListNode, ValueNode)):
+            if self.children:
+                assert not isinstance(self.children[-1], (ListNode, ValueNode))
+            self.children.append(other)
+        else:
+            if self.children and isinstance(self.children[-1], ValueNode):
+                self.children.insert(len(self.children) - 1, other)
+            else:
+                self.children.append(other)
+
+
+class ListNode(Node):
+    def append(self, other):
+        other.parent = self
+        self.children.append(other)
+
+
+class ValueNode(Node):
+    def append(self, other):
+        raise TypeError
+
+
+class AtomNode(ValueNode):
+    pass
+
+
+class ConditionalNode(Node):
+    def append(self, other):
+        if not len(self.children):
+            if not isinstance(other, (BinaryExpressionNode, UnaryExpressionNode, VariableNode)):
+                raise TypeError
+        else:
+            if len(self.children) > 1:
+                raise ValueError
+            if not isinstance(other, (ListNode, ValueNode)):
+                raise TypeError
+        other.parent = self
+        self.children.append(other)
+
+
+class UnaryExpressionNode(Node):
+    def __init__(self, operator, operand):
+        Node.__init__(self)
+        self.append(operator)
+        self.append(operand)
+
+    def append(self, other):
+        Node.append(self, other)
+        assert len(self.children) <= 2
+
+    def copy(self):
+        new = self.__class__(self.children[0].copy(),
+                             self.children[1].copy())
+        return new
+
+
+class BinaryExpressionNode(Node):
+    def __init__(self, operator, operand_0, operand_1):
+        Node.__init__(self)
+        self.append(operator)
+        self.append(operand_0)
+        self.append(operand_1)
+
+    def append(self, other):
+        Node.append(self, other)
+        assert len(self.children) <= 3
+
+    def copy(self):
+        new = self.__class__(self.children[0].copy(),
+                             self.children[1].copy(),
+                             self.children[2].copy())
+        return new
+
+
+class UnaryOperatorNode(Node):
+    def append(self, other):
+        raise TypeError
+
+
+class BinaryOperatorNode(Node):
+    def append(self, other):
+        raise TypeError
+
+
+class IndexNode(Node):
+    pass
+
+
+class VariableNode(Node):
+    pass
+
+
+class StringNode(Node):
+    pass
+
+
+class NumberNode(ValueNode):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py
new file mode 100644
index 0000000..911efac80
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/parser.py
@@ -0,0 +1,789 @@
+#default_value:foo
+#include: other.manifest
+#
+#[test_name.js]
+#  expected: ERROR
+#
+#  [subtest 1]
+#    expected:
+#      os == win: FAIL #This is a comment
+#      PASS
+#
+
+# TODO: keep comments in the tree
+
+from __future__ import unicode_literals
+
+from six import binary_type, text_type, BytesIO, unichr
+from six.moves import range
+
+from .node import (Node, AtomNode, BinaryExpressionNode, BinaryOperatorNode,
+                   ConditionalNode, DataNode, IndexNode, KeyValueNode, ListNode,
+                   NumberNode, StringNode, UnaryExpressionNode,
+                   UnaryOperatorNode, ValueNode, VariableNode)
+
+
+class ParseError(Exception):
+    def __init__(self, filename, line, detail):
+        self.line = line
+        self.filename = filename
+        self.detail = detail
+        self.message = "%s: %s line %s" % (self.detail, self.filename, self.line)
+        Exception.__init__(self, self.message)
+
+eol = object
+group_start = object
+group_end = object
+digits = "0123456789"
+open_parens = "[("
+close_parens = "])"
+parens = open_parens + close_parens
+operator_chars = "=!"
+
+unary_operators = ["not"]
+binary_operators = ["==", "!=", "and", "or"]
+
+operators = ["==", "!=", "not", "and", "or"]
+
+atoms = {"True": True,
+         "False": False,
+         "Reset": object()}
+
+def decode(s):
+    assert isinstance(s, text_type)
+    return s
+
+
+def precedence(operator_node):
+    return len(operators) - operators.index(operator_node.data)
+
+
+class TokenTypes(object):
+    def __init__(self):
+        for type in ["group_start", "group_end", "paren", "list_start", "list_end", "separator", "ident", "string", "number", "atom", "eof"]:
+            setattr(self, type, type)
+
+token_types = TokenTypes()
+
+
+class Tokenizer(object):
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.indent_levels = [0]
+        self.state = self.line_start_state
+        self.next_state = self.data_line_state
+        self.line_number = 0
+        self.filename = ""
+
+    def tokenize(self, stream):
+        self.reset()
+        assert not isinstance(stream, text_type)
+        if isinstance(stream, bytes):
+            stream = BytesIO(stream)
+        if not hasattr(stream, "name"):
+            self.filename = ""
+        else:
+            self.filename = stream.name
+
+        self.next_line_state = self.line_start_state
+        for i, line in enumerate(stream):
+            assert isinstance(line, binary_type)
+            self.state = self.next_line_state
+            assert self.state is not None
+            states = []
+            self.next_line_state = None
+            self.line_number = i + 1
+            self.index = 0
+            self.line = line.decode('utf-8').rstrip()
+            assert isinstance(self.line, text_type)
+            while self.state != self.eol_state:
+                states.append(self.state)
+                tokens = self.state()
+                if tokens:
+                    for token in tokens:
+                        yield token
+            self.state()
+        while True:
+            yield (token_types.eof, None)
+
+    def char(self):
+        if self.index == len(self.line):
+            return eol
+        return self.line[self.index]
+
+    def consume(self):
+        if self.index < len(self.line):
+            self.index += 1
+
+    def peek(self, length):
+        return self.line[self.index:self.index + length]
+
+    def skip_whitespace(self):
+        while self.char() == " ":
+            self.consume()
+
+    def eol_state(self):
+        if self.next_line_state is None:
+            self.next_line_state = self.line_start_state
+
+    def line_start_state(self):
+        self.skip_whitespace()
+        if self.char() == eol:
+            self.state = self.eol_state
+            return
+        if self.index > self.indent_levels[-1]:
+            self.indent_levels.append(self.index)
+            yield (token_types.group_start, None)
+        else:
+            if self.index < self.indent_levels[-1]:
+                while self.index < self.indent_levels[-1]:
+                    self.indent_levels.pop()
+                    yield (token_types.group_end, None)
+                # This is terrible; if we were parsing an expression
+                # then the next_state will be expr_or_value but when we deindent
+                # it must always be a heading or key next so we go back to data_line_state
+                self.next_state = self.data_line_state
+            if self.index != self.indent_levels[-1]:
+                raise ParseError(self.filename, self.line_number, "Unexpected indent")
+
+        self.state = self.next_state
+
+    def data_line_state(self):
+        if self.char() == "[":
+            yield (token_types.paren, self.char())
+            self.consume()
+            self.state = self.heading_state
+        else:
+            self.state = self.key_state
+
+    def heading_state(self):
+        rv = ""
+        while True:
+            c = self.char()
+            if c == "\\":
+                rv += self.consume_escape()
+            elif c == "]":
+                break
+            elif c == eol:
+                raise ParseError(self.filename, self.line_number, "EOL in heading")
+            else:
+                rv += c
+                self.consume()
+
+        yield (token_types.string, decode(rv))
+        yield (token_types.paren, "]")
+        self.consume()
+        self.state = self.line_end_state
+        self.next_state = self.data_line_state
+
+    def key_state(self):
+        rv = ""
+        while True:
+            c = self.char()
+            if c == " ":
+                self.skip_whitespace()
+                if self.char() != ":":
+                    raise ParseError(self.filename, self.line_number, "Space in key name")
+                break
+            elif c == ":":
+                break
+            elif c == eol:
+                raise ParseError(self.filename, self.line_number, "EOL in key name (missing ':'?)")
+            elif c == "\\":
+                rv += self.consume_escape()
+            else:
+                rv += c
+                self.consume()
+        yield (token_types.string, decode(rv))
+        yield (token_types.separator, ":")
+        self.consume()
+        self.state = self.after_key_state
+
+    def after_key_state(self):
+        self.skip_whitespace()
+        c = self.char()
+        if c == "#":
+            self.next_state = self.expr_or_value_state
+            self.state = self.comment_state
+        elif c == eol:
+            self.next_state = self.expr_or_value_state
+            self.state = self.eol_state
+        elif c == "[":
+            self.state = self.list_start_state
+        else:
+            self.state = self.value_state
+
+    def after_expr_state(self):
+        self.skip_whitespace()
+        c = self.char()
+        if c == "#":
+            self.next_state = self.after_expr_state
+            self.state = self.comment_state
+        elif c == eol:
+            self.next_state = self.after_expr_state
+            self.state = self.eol_state
+        elif c == "[":
+            self.state = self.list_start_state
+        else:
+            self.state = self.value_state
+
+    def list_start_state(self):
+        yield (token_types.list_start, "[")
+        self.consume()
+        self.state = self.list_value_start_state
+
+    def list_value_start_state(self):
+        self.skip_whitespace()
+        if self.char() == "]":
+            self.state = self.list_end_state
+        elif self.char() in ("'", '"'):
+            quote_char = self.char()
+            self.consume()
+            yield (token_types.string, self.consume_string(quote_char))
+            self.skip_whitespace()
+            if self.char() == "]":
+                self.state = self.list_end_state
+            elif self.char() != ",":
+                raise ParseError(self.filename, self.line_number, "Junk after quoted string")
+            self.consume()
+        elif self.char() == "#":
+            self.state = self.comment_state
+            self.next_line_state = self.list_value_start_state
+        elif self.char() == eol:
+            self.next_line_state = self.list_value_start_state
+            self.state = self.eol_state
+        elif self.char() == ",":
+            raise ParseError(self.filename, self.line_number, "List item started with separator")
+        elif self.char() == "@":
+            self.state = self.list_value_atom_state
+        else:
+            self.state = self.list_value_state
+
+    def list_value_state(self):
+        rv = ""
+        spaces = 0
+        while True:
+            c = self.char()
+            if c == "\\":
+                escape = self.consume_escape()
+                rv += escape
+            elif c == eol:
+                raise ParseError(self.filename, self.line_number, "EOL in list value")
+            elif c == "#":
+                raise ParseError(self.filename, self.line_number, "EOL in list value (comment)")
+            elif c == ",":
+                self.state = self.list_value_start_state
+                self.consume()
+                break
+            elif c == " ":
+                spaces += 1
+                self.consume()
+            elif c == "]":
+                self.state = self.list_end_state
+                self.consume()
+                break
+            else:
+                rv += " " * spaces
+                spaces = 0
+                rv += c
+                self.consume()
+
+        if rv:
+            yield (token_types.string, decode(rv))
+
+    def list_value_atom_state(self):
+        self.consume()
+        for _, value in self.list_value_state():
+            yield token_types.atom, value
+
+    def list_end_state(self):
+        self.consume()
+        yield (token_types.list_end, "]")
+        self.state = self.line_end_state
+
+    def value_state(self):
+        self.skip_whitespace()
+        c = self.char()
+        if c in ("'", '"'):
+            quote_char = self.char()
+            self.consume()
+            yield (token_types.string, self.consume_string(quote_char))
+            if self.char() == "#":
+                self.state = self.comment_state
+            else:
+                self.state = self.line_end_state
+        elif c == "@":
+            self.consume()
+            for _, value in self.value_inner_state():
+                yield token_types.atom, value
+        elif c == "[":
+            self.state = self.list_start_state
+        else:
+            self.state = self.value_inner_state
+
+    def value_inner_state(self):
+        rv = ""
+        spaces = 0
+        while True:
+            c = self.char()
+            if c == "\\":
+                rv += self.consume_escape()
+            elif c == "#":
+                self.state = self.comment_state
+                break
+            elif c == " ":
+                # prevent whitespace before comments from being included in the value
+                spaces += 1
+                self.consume()
+            elif c == eol:
+                self.state = self.line_end_state
+                break
+            else:
+                rv += " " * spaces
+                spaces = 0
+                rv += c
+                self.consume()
+        rv = decode(rv)
+        if rv.startswith("if "):
+            # Hack to avoid a problem where people write
+            # disabled: if foo
+            # and expect that to disable conditionally
+            raise ParseError(self.filename, self.line_number, "Strings starting 'if ' must be quoted "
+                             "(expressions must start on a newline and be indented)")
+        yield (token_types.string, rv)
+
+    def comment_state(self):
+        while self.char() is not eol:
+            self.consume()
+        self.state = self.eol_state
+
+    def line_end_state(self):
+        self.skip_whitespace()
+        c = self.char()
+        if c == "#":
+            self.state = self.comment_state
+        elif c == eol:
+            self.state = self.eol_state
+        else:
+            raise ParseError(self.filename, self.line_number, "Junk before EOL %s" % c)
+
+    def consume_string(self, quote_char):
+        rv = ""
+        while True:
+            c = self.char()
+            if c == "\\":
+                rv += self.consume_escape()
+            elif c == quote_char:
+                self.consume()
+                break
+            elif c == eol:
+                raise ParseError(self.filename, self.line_number, "EOL in quoted string")
+            else:
+                rv += c
+                self.consume()
+
+        return decode(rv)
+
+    def expr_or_value_state(self):
+        if self.peek(3) == "if ":
+            self.state = self.expr_state
+        else:
+            self.state = self.value_state
+
+    def expr_state(self):
+        self.skip_whitespace()
+        c = self.char()
+        if c == eol:
+            raise ParseError(self.filename, self.line_number, "EOL in expression")
+        elif c in "'\"":
+            self.consume()
+            yield (token_types.string, self.consume_string(c))
+        elif c == "#":
+            raise ParseError(self.filename, self.line_number, "Comment before end of expression")
+        elif c == ":":
+            yield (token_types.separator, c)
+            self.consume()
+            self.state = self.after_expr_state
+        elif c in parens:
+            self.consume()
+            yield (token_types.paren, c)
+        elif c in ("!", "="):
+            self.state = self.operator_state
+        elif c in digits:
+            self.state = self.digit_state
+        else:
+            self.state = self.ident_state
+
+    def operator_state(self):
+        # Only symbolic operators
+        index_0 = self.index
+        while True:
+            c = self.char()
+            if c == eol:
+                break
+            elif c in operator_chars:
+                self.consume()
+            else:
+                self.state = self.expr_state
+                break
+        yield (token_types.ident, self.line[index_0:self.index])
+
+    def digit_state(self):
+        index_0 = self.index
+        seen_dot = False
+        while True:
+            c = self.char()
+            if c == eol:
+                break
+            elif c in digits:
+                self.consume()
+            elif c == ".":
+                if seen_dot:
+                    raise ParseError(self.filename, self.line_number, "Invalid number")
+                self.consume()
+                seen_dot = True
+            elif c in parens:
+                break
+            elif c in operator_chars:
+                break
+            elif c == " ":
+                break
+            elif c == ":":
+                break
+            else:
+                raise ParseError(self.filename, self.line_number, "Invalid character in number")
+
+        self.state = self.expr_state
+        yield (token_types.number, self.line[index_0:self.index])
+
+    def ident_state(self):
+        index_0 = self.index
+        while True:
+            c = self.char()
+            if c == eol:
+                break
+            elif c == ".":
+                break
+            elif c in parens:
+                break
+            elif c in operator_chars:
+                break
+            elif c == " ":
+                break
+            elif c == ":":
+                break
+            else:
+                self.consume()
+        self.state = self.expr_state
+        yield (token_types.ident, self.line[index_0:self.index])
+
+    def consume_escape(self):
+        assert self.char() == "\\"
+        self.consume()
+        c = self.char()
+        self.consume()
+        if c == "x":
+            return self.decode_escape(2)
+        elif c == "u":
+            return self.decode_escape(4)
+        elif c == "U":
+            return self.decode_escape(6)
+        elif c in ["a", "b", "f", "n", "r", "t", "v"]:
+            return eval(r"'\%s'" % c)
+        elif c is eol:
+            raise ParseError(self.filename, self.line_number, "EOL in escape")
+        else:
+            return c
+
+    def decode_escape(self, length):
+        value = 0
+        for i in range(length):
+            c = self.char()
+            value *= 16
+            value += self.escape_value(c)
+            self.consume()
+
+        return unichr(value)
+
+    def escape_value(self, c):
+        if '0' <= c <= '9':
+            return ord(c) - ord('0')
+        elif 'a' <= c <= 'f':
+            return ord(c) - ord('a') + 10
+        elif 'A' <= c <= 'F':
+            return ord(c) - ord('A') + 10
+        else:
+            raise ParseError(self.filename, self.line_number, "Invalid character escape")
+
+
+class Parser(object):
+    def __init__(self):
+        self.reset()
+
+    def reset(self):
+        self.token = None
+        self.unary_operators = "!"
+        self.binary_operators = frozenset(["&&", "||", "=="])
+        self.tokenizer = Tokenizer()
+        self.token_generator = None
+        self.tree = Treebuilder(DataNode(None))
+        self.expr_builder = None
+        self.expr_builders = []
+
+    def parse(self, input):
+        try:
+            self.reset()
+            self.token_generator = self.tokenizer.tokenize(input)
+            self.consume()
+            self.manifest()
+            return self.tree.node
+        except Exception as e:
+            if not isinstance(e, ParseError):
+                raise ParseError(self.tokenizer.filename,
+                                 self.tokenizer.line_number,
+                                 str(e))
+            raise
+
+    def consume(self):
+        self.token = next(self.token_generator)
+
+    def expect(self, type, value=None):
+        if self.token[0] != type:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number,
+                             "Token '{}' doesn't equal expected type '{}'".format(self.token[0], type))
+        if value is not None:
+            if self.token[1] != value:
+                raise ParseError(self.tokenizer.filename, self.tokenizer.line_number,
+                                 "Token '{}' doesn't equal expected value '{}'".format(self.token[1], value))
+
+        self.consume()
+
+    def manifest(self):
+        self.data_block()
+        self.expect(token_types.eof)
+
+    def data_block(self):
+        while self.token[0] == token_types.string:
+            self.tree.append(KeyValueNode(self.token[1]))
+            self.consume()
+            self.expect(token_types.separator)
+            self.value_block()
+            self.tree.pop()
+
+        while self.token == (token_types.paren, "["):
+            self.consume()
+            if self.token[0] != token_types.string:
+                raise ParseError(self.tokenizer.filename, self.tokenizer.line_number,
+                                 "Token '{}' is not a string".format(self.token[0]))
+            self.tree.append(DataNode(self.token[1]))
+            self.consume()
+            self.expect(token_types.paren, "]")
+            if self.token[0] == token_types.group_start:
+                self.consume()
+                self.data_block()
+                self.eof_or_end_group()
+            self.tree.pop()
+
+    def eof_or_end_group(self):
+        if self.token[0] != token_types.eof:
+            self.expect(token_types.group_end)
+
+    def value_block(self):
+        if self.token[0] == token_types.list_start:
+            self.consume()
+            self.list_value()
+        elif self.token[0] == token_types.string:
+            self.value()
+        elif self.token[0] == token_types.group_start:
+            self.consume()
+            self.expression_values()
+            if self.token[0] == token_types.string:
+                self.value()
+            elif self.token[0] == token_types.list_start:
+                self.consume()
+                self.list_value()
+            self.eof_or_end_group()
+        elif self.token[0] == token_types.atom:
+            self.atom()
+        else:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number,
+                             "Token '{}' is not a known type".format(self.token[0]))
+
+    def list_value(self):
+        self.tree.append(ListNode())
+        while self.token[0] in (token_types.atom, token_types.string):
+            if self.token[0] == token_types.atom:
+                self.atom()
+            else:
+                self.value()
+        self.expect(token_types.list_end)
+        self.tree.pop()
+
+    def expression_values(self):
+        while self.token == (token_types.ident, "if"):
+            self.consume()
+            self.tree.append(ConditionalNode())
+            self.expr_start()
+            self.expect(token_types.separator)
+            self.value_block()
+            self.tree.pop()
+
+    def value(self):
+        self.tree.append(ValueNode(self.token[1]))
+        self.consume()
+        self.tree.pop()
+
+    def atom(self):
+        if self.token[1] not in atoms:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Unrecognised symbol @%s" % self.token[1])
+        self.tree.append(AtomNode(atoms[self.token[1]]))
+        self.consume()
+        self.tree.pop()
+
+    def expr_start(self):
+        self.expr_builder = ExpressionBuilder(self.tokenizer)
+        self.expr_builders.append(self.expr_builder)
+        self.expr()
+        expression = self.expr_builder.finish()
+        self.expr_builders.pop()
+        self.expr_builder = self.expr_builders[-1] if self.expr_builders else None
+        if self.expr_builder:
+            self.expr_builder.operands[-1].children[-1].append(expression)
+        else:
+            self.tree.append(expression)
+            self.tree.pop()
+
+    def expr(self):
+        self.expr_operand()
+        while (self.token[0] == token_types.ident and self.token[1] in binary_operators):
+            self.expr_bin_op()
+            self.expr_operand()
+
+    def expr_operand(self):
+        if self.token == (token_types.paren, "("):
+            self.consume()
+            self.expr_builder.left_paren()
+            self.expr()
+            self.expect(token_types.paren, ")")
+            self.expr_builder.right_paren()
+        elif self.token[0] == token_types.ident and self.token[1] in unary_operators:
+            self.expr_unary_op()
+            self.expr_operand()
+        elif self.token[0] in [token_types.string, token_types.ident]:
+            self.expr_value()
+        elif self.token[0] == token_types.number:
+            self.expr_number()
+        else:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Unrecognised operand")
+
+    def expr_unary_op(self):
+        if self.token[1] in unary_operators:
+            self.expr_builder.push_operator(UnaryOperatorNode(self.token[1]))
+            self.consume()
+        else:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Expected unary operator")
+
+    def expr_bin_op(self):
+        if self.token[1] in binary_operators:
+            self.expr_builder.push_operator(BinaryOperatorNode(self.token[1]))
+            self.consume()
+        else:
+            raise ParseError(self.tokenizer.filename, self.tokenizer.line_number, "Expected binary operator")
+
+    def expr_value(self):
+        node_type = {token_types.string: StringNode,
+                     token_types.ident: VariableNode}[self.token[0]]
+        self.expr_builder.push_operand(node_type(self.token[1]))
+        self.consume()
+        if self.token == (token_types.paren, "["):
+            self.consume()
+            self.expr_builder.operands[-1].append(IndexNode())
+            self.expr_start()
+            self.expect(token_types.paren, "]")
+
+    def expr_number(self):
+        self.expr_builder.push_operand(NumberNode(self.token[1]))
+        self.consume()
+
+
+class Treebuilder(object):
+    def __init__(self, root):
+        self.root = root
+        self.node = root
+
+    def append(self, node):
+        assert isinstance(node, Node)
+        self.node.append(node)
+        self.node = node
+        assert self.node is not None
+        return node
+
+    def pop(self):
+        node = self.node
+        self.node = self.node.parent
+        assert self.node is not None
+        return node
+
+
+class ExpressionBuilder(object):
+    def __init__(self, tokenizer):
+        self.operands = []
+        self.operators = [None]
+        self.tokenizer = tokenizer
+
+    def finish(self):
+        while self.operators[-1] is not None:
+            self.pop_operator()
+        rv = self.pop_operand()
+        assert self.is_empty()
+        return rv
+
+    def left_paren(self):
+        self.operators.append(None)
+
+    def right_paren(self):
+        while self.operators[-1] is not None:
+            self.pop_operator()
+            if not self.operators:
+                raise ParseError(self.tokenizer.filename, self.tokenizer.line,
+                                 "Unbalanced parens")
+
+        assert self.operators.pop() is None
+
+    def push_operator(self, operator):
+        assert operator is not None
+        while self.precedence(self.operators[-1]) > self.precedence(operator):
+            self.pop_operator()
+
+        self.operators.append(operator)
+
+    def pop_operator(self):
+        operator = self.operators.pop()
+        if isinstance(operator, BinaryOperatorNode):
+            operand_1 = self.operands.pop()
+            operand_0 = self.operands.pop()
+            self.operands.append(BinaryExpressionNode(operator, operand_0, operand_1))
+        else:
+            operand_0 = self.operands.pop()
+            self.operands.append(UnaryExpressionNode(operator, operand_0))
+
+    def push_operand(self, node):
+        self.operands.append(node)
+
+    def pop_operand(self):
+        return self.operands.pop()
+
+    def is_empty(self):
+        return len(self.operands) == 0 and all(item is None for item in self.operators)
+
+    def precedence(self, operator):
+        if operator is None:
+            return 0
+        return precedence(operator)
+
+
+def parse(stream):
+    p = Parser()
+    return p.parse(stream)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/serializer.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/serializer.py
new file mode 100644
index 0000000..ec8d80e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/serializer.py
@@ -0,0 +1,145 @@
+from __future__ import unicode_literals
+from six import ensure_text
+
+from .node import NodeVisitor, ValueNode, ListNode, BinaryExpressionNode
+from .parser import atoms, precedence
+
+atom_names = {v: "@%s" % k for (k,v) in atoms.items()}
+
+named_escapes = {"\a", "\b", "\f", "\n", "\r", "\t", "\v"}
+
+def escape(string, extras=""):
+    # Assumes input bytes are either UTF8 bytes or unicode.
+    rv = ""
+    for c in string:
+        if c in named_escapes:
+            rv += c.encode("unicode_escape").decode()
+        elif c == "\\":
+            rv += "\\\\"
+        elif c < '\x20':
+            rv += "\\x%02x" % ord(c)
+        elif c in extras:
+            rv += "\\" + c
+        else:
+            rv += c
+    return ensure_text(rv)
+
+
+class ManifestSerializer(NodeVisitor):
+    def __init__(self, skip_empty_data=False):
+        self.skip_empty_data = skip_empty_data
+
+    def serialize(self, root):
+        self.indent = 2
+        rv = "\n".join(self.visit(root))
+        if not rv:
+            return rv
+        if rv[-1] != "\n":
+            rv = rv + "\n"
+        return rv
+
+    def visit_DataNode(self, node):
+        rv = []
+        if not self.skip_empty_data or node.children:
+            if node.data:
+                rv.append("[%s]" % escape(node.data, extras="]"))
+                indent = self.indent * " "
+            else:
+                indent = ""
+
+            for child in node.children:
+                rv.extend("%s%s" % (indent if item else "", item) for item in self.visit(child))
+
+            if node.parent:
+                rv.append("")
+
+        return rv
+
+    def visit_KeyValueNode(self, node):
+        rv = [escape(node.data, ":") + ":"]
+        indent = " " * self.indent
+
+        if len(node.children) == 1 and isinstance(node.children[0], (ValueNode, ListNode)):
+            rv[0] += " %s" % self.visit(node.children[0])[0]
+        else:
+            for child in node.children:
+                rv.append(indent + self.visit(child)[0])
+
+        return rv
+
+    def visit_ListNode(self, node):
+        rv = ["["]
+        rv.extend(", ".join(self.visit(child)[0] for child in node.children))
+        rv.append("]")
+        return ["".join(rv)]
+
+    def visit_ValueNode(self, node):
+        data = ensure_text(node.data)
+        if ("#" in data or
+            data.startswith("if ") or
+            (isinstance(node.parent, ListNode) and
+             ("," in data or "]" in data))):
+            if "\"" in data:
+                quote = "'"
+            else:
+                quote = "\""
+        else:
+            quote = ""
+        return [quote + escape(data, extras=quote) + quote]
+
+    def visit_AtomNode(self, node):
+        return [atom_names[node.data]]
+
+    def visit_ConditionalNode(self, node):
+        return ["if %s: %s" % tuple(self.visit(item)[0] for item in node.children)]
+
+    def visit_StringNode(self, node):
+        rv = ["\"%s\"" % escape(node.data, extras="\"")]
+        for child in node.children:
+            rv[0] += self.visit(child)[0]
+        return rv
+
+    def visit_NumberNode(self, node):
+        return [ensure_text(node.data)]
+
+    def visit_VariableNode(self, node):
+        rv = escape(node.data)
+        for child in node.children:
+            rv += self.visit(child)
+        return [rv]
+
+    def visit_IndexNode(self, node):
+        assert len(node.children) == 1
+        return ["[%s]" % self.visit(node.children[0])[0]]
+
+    def visit_UnaryExpressionNode(self, node):
+        children = []
+        for child in node.children:
+            child_str = self.visit(child)[0]
+            if isinstance(child, BinaryExpressionNode):
+                child_str = "(%s)" % child_str
+            children.append(child_str)
+        return [" ".join(children)]
+
+    def visit_BinaryExpressionNode(self, node):
+        assert len(node.children) == 3
+        children = []
+        for child_index in [1, 0, 2]:
+            child = node.children[child_index]
+            child_str = self.visit(child)[0]
+            if (isinstance(child, BinaryExpressionNode) and
+                precedence(node.children[0]) < precedence(child.children[0])):
+                child_str = "(%s)" % child_str
+            children.append(child_str)
+        return [" ".join(children)]
+
+    def visit_UnaryOperatorNode(self, node):
+        return [ensure_text(node.data)]
+
+    def visit_BinaryOperatorNode(self, node):
+        return [ensure_text(node.data)]
+
+
+def serialize(tree, *args, **kwargs):
+    s = ManifestSerializer(*args, **kwargs)
+    return s.serialize(tree)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/__init__.py
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py
new file mode 100644
index 0000000..af4d996
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_conditional.py
@@ -0,0 +1,141 @@
+import unittest
+
+from ..backends import conditional
+from ..node import BinaryExpressionNode, BinaryOperatorNode, VariableNode, NumberNode
+
+
+class TestConditional(unittest.TestCase):
+    def compile(self, input_text):
+        return conditional.compile(input_text)
+
+    def test_get_0(self):
+        data = b"""
+key: value
+
+[Heading 1]
+  other_key:
+    if a == 1: value_1
+    if a == 2: value_2
+    value_3
+"""
+
+        manifest = self.compile(data)
+
+        self.assertEqual(manifest.get("key"), "value")
+        children = list(item for item in manifest.iterchildren())
+        self.assertEqual(len(children), 1)
+        section = children[0]
+        self.assertEqual(section.name, "Heading 1")
+
+        self.assertEqual(section.get("other_key", {"a": 1}), "value_1")
+        self.assertEqual(section.get("other_key", {"a": 2}), "value_2")
+        self.assertEqual(section.get("other_key", {"a": 7}), "value_3")
+        self.assertEqual(section.get("key"), "value")
+
+    def test_get_1(self):
+        data = b"""
+key: value
+
+[Heading 1]
+  other_key:
+    if a == "1": value_1
+    if a == 2: value_2
+    value_3
+"""
+
+        manifest = self.compile(data)
+
+        children = list(item for item in manifest.iterchildren())
+        section = children[0]
+
+        self.assertEqual(section.get("other_key", {"a": "1"}), "value_1")
+        self.assertEqual(section.get("other_key", {"a": 1}), "value_3")
+
+    def test_get_2(self):
+        data = b"""
+key:
+  if a[1] == "b": value_1
+  if a[1] == 2: value_2
+  value_3
+"""
+
+        manifest = self.compile(data)
+
+        self.assertEqual(manifest.get("key", {"a": "ab"}), "value_1")
+        self.assertEqual(manifest.get("key", {"a": [1, 2]}), "value_2")
+
+    def test_get_3(self):
+        data = b"""
+key:
+  if a[1] == "ab"[1]: value_1
+  if a[1] == 2: value_2
+  value_3
+"""
+
+        manifest = self.compile(data)
+
+        self.assertEqual(manifest.get("key", {"a": "ab"}), "value_1")
+        self.assertEqual(manifest.get("key", {"a": [1, 2]}), "value_2")
+
+    def test_set_0(self):
+        data = b"""
+key:
+  if a == "a": value_1
+  if a == "b": value_2
+  value_3
+"""
+        manifest = self.compile(data)
+
+        manifest.set("new_key", "value_new")
+
+        self.assertEqual(manifest.get("new_key"), "value_new")
+
+    def test_set_1(self):
+        data = b"""
+key:
+  if a == "a": value_1
+  if a == "b": value_2
+  value_3
+"""
+
+        manifest = self.compile(data)
+
+        manifest.set("key", "value_new")
+
+        self.assertEqual(manifest.get("key"), "value_new")
+        self.assertEqual(manifest.get("key", {"a": "a"}), "value_1")
+
+    def test_set_2(self):
+        data = b"""
+key:
+  if a == "a": value_1
+  if a == "b": value_2
+  value_3
+"""
+
+        manifest = self.compile(data)
+
+        expr = BinaryExpressionNode(BinaryOperatorNode("=="),
+                                    VariableNode("a"),
+                                    NumberNode("1"))
+
+        manifest.set("key", "value_new", expr)
+
+        self.assertEqual(manifest.get("key", {"a": 1}), "value_new")
+        self.assertEqual(manifest.get("key", {"a": "a"}), "value_1")
+
+    def test_api_0(self):
+        data = b"""
+key:
+  if a == 1.5: value_1
+  value_2
+key_1: other_value
+"""
+        manifest = self.compile(data)
+
+        self.assertFalse(manifest.is_empty)
+        self.assertEqual(manifest.root, manifest)
+        self.assertTrue(manifest.has_key("key_1"))
+        self.assertFalse(manifest.has_key("key_2"))
+
+        self.assertEqual(set(manifest.iterkeys()), {"key", "key_1"})
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py
new file mode 100644
index 0000000..23beb2b
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_parser.py
@@ -0,0 +1,153 @@
+import unittest
+
+from .. import parser
+
+# There aren't many tests here because it turns out to be way more convenient to
+# use test_serializer for the majority of cases
+
+
+class TestExpression(unittest.TestCase):
+    def setUp(self):
+        self.parser = parser.Parser()
+
+    def parse(self, input_str):
+        return self.parser.parse(input_str)
+
+    def compare(self, input_text, expected):
+        actual = self.parse(input_text)
+        self.match(expected, actual)
+
+    def match(self, expected_node, actual_node):
+        self.assertEqual(expected_node[0], actual_node.__class__.__name__)
+        self.assertEqual(expected_node[1], actual_node.data)
+        self.assertEqual(len(expected_node[2]), len(actual_node.children))
+        for expected_child, actual_child in zip(expected_node[2], actual_node.children):
+            self.match(expected_child, actual_child)
+
+    def test_expr_0(self):
+        self.compare(
+            b"""
+key:
+  if x == 1 : value""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "==", []],
+                    ["VariableNode", "x", []],
+                       ["NumberNode", "1", []]
+                    ]],
+                     ["ValueNode", "value", []],
+                  ]]]]]]
+        )
+
+    def test_expr_1(self):
+        self.compare(
+            b"""
+key:
+  if not x and y : value""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "and", []],
+                    ["UnaryExpressionNode", None,
+                       [["UnaryOperatorNode", "not", []],
+                        ["VariableNode", "x", []]
+                        ]],
+                       ["VariableNode", "y", []]
+                    ]],
+                     ["ValueNode", "value", []],
+                  ]]]]]]
+        )
+
+    def test_expr_2(self):
+        self.compare(
+            b"""
+key:
+  if x == 1 : [value1, value2]""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "==", []],
+                    ["VariableNode", "x", []],
+                       ["NumberNode", "1", []]
+                    ]],
+                  ["ListNode", None,
+                   [["ValueNode", "value1", []],
+                    ["ValueNode", "value2", []]]],
+                  ]]]]]]
+        )
+
+    def test_expr_3(self):
+        self.compare(
+            b"""
+key:
+  if x == 1: 'if b: value'""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "==", []],
+                    ["VariableNode", "x", []],
+                       ["NumberNode", "1", []]
+                    ]],
+                     ["ValueNode", "if b: value", []],
+                  ]]]]]]
+        )
+
+    def test_atom_0(self):
+        with self.assertRaises(parser.ParseError):
+            self.parse(b"key: @Unknown")
+
+    def test_atom_1(self):
+        with self.assertRaises(parser.ParseError):
+            self.parse(b"key: @true")
+
+    def test_list_expr(self):
+        self.compare(
+            b"""
+key:
+  if x == 1: [a]
+  [b]""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "==", []],
+                    ["VariableNode", "x", []],
+                       ["NumberNode", "1", []]
+                    ]],
+                     ["ListNode", None,
+                      [["ValueNode", "a", []]]],
+                  ]],
+                ["ListNode", None,
+                 [["ValueNode", "b", []]]]]]]])
+
+    def test_list_heading(self):
+        self.compare(
+            b"""
+key:
+  if x == 1: [a]
+[b]""",
+            ["DataNode", None,
+             [["KeyValueNode", "key",
+               [["ConditionalNode", None,
+                 [["BinaryExpressionNode", None,
+                   [["BinaryOperatorNode", "==", []],
+                    ["VariableNode", "x", []],
+                       ["NumberNode", "1", []]
+                    ]],
+                     ["ListNode", None,
+                      [["ValueNode", "a", []]]],
+                  ]]]],
+              ["DataNode", "b", []]]])
+
+    def test_if_1(self):
+        with self.assertRaises(parser.ParseError):
+            self.parse(b"key: if foo")
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py
new file mode 100644
index 0000000..b2478558
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_serializer.py
@@ -0,0 +1,237 @@
+import sys
+import unittest
+
+import pytest
+
+from .. import parser, serializer
+
+
+class TokenizerTest(unittest.TestCase):
+    def setUp(self):
+        self.serializer = serializer.ManifestSerializer()
+        self.parser = parser.Parser()
+
+    def serialize(self, input_str):
+        return self.serializer.serialize(self.parser.parse(input_str))
+
+    def compare(self, input_str, expected=None):
+        if expected is None:
+            expected = input_str.decode("utf-8")
+        actual = self.serialize(input_str)
+        self.assertEqual(actual, expected)
+
+    def test_0(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key: other_value
+""")
+
+    def test_1(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a or b: other_value
+""")
+
+    def test_2(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a or b: other_value
+    fallback_value
+""")
+
+    def test_3(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a == 1: other_value
+    fallback_value
+""")
+
+    def test_4(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a == "1": other_value
+    fallback_value
+""")
+
+    def test_5(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a == "abc"[1]: other_value
+    fallback_value
+""")
+
+    def test_6(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a == "abc"[c]: other_value
+    fallback_value
+""")
+
+    def test_7(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if (a or b) and c: other_value
+    fallback_value
+""",
+"""key: value
+[Heading 1]
+  other_key:
+    if a or b and c: other_value
+    fallback_value
+""")
+
+    def test_8(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if a or (b and c): other_value
+    fallback_value
+""")
+
+    def test_9(self):
+        self.compare(b"""key: value
+[Heading 1]
+  other_key:
+    if not (a and b): other_value
+    fallback_value
+""")
+
+    def test_10(self):
+        self.compare(b"""key: value
+[Heading 1]
+  some_key: some_value
+
+[Heading 2]
+  other_key: other_value
+""")
+
+    def test_11(self):
+        self.compare(b"""key:
+  if not a and b and c and d: true
+""")
+
+    def test_12(self):
+        self.compare(b"""[Heading 1]
+  key: [a:1, b:2]
+""")
+
+    def test_13(self):
+        self.compare(b"""key: [a:1, "b:#"]
+""")
+
+    def test_14(self):
+        self.compare(b"""key: [","]
+""")
+
+    def test_15(self):
+        self.compare(b"""key: ,
+""")
+
+    def test_16(self):
+        self.compare(b"""key: ["]", b]
+""")
+
+    def test_17(self):
+        self.compare(b"""key: ]
+""")
+
+    def test_18(self):
+        self.compare(br"""key: \]
+        """, """key: ]
+""")
+
+    def test_escape_0(self):
+        self.compare(br"""k\t\:y: \a\b\f\n\r\t\v""",
+                     r"""k\t\:y: \x07\x08\x0c\n\r\t\x0b
+""")
+
+    def test_escape_1(self):
+        self.compare(br"""k\x00: \x12A\x45""",
+                     r"""k\x00: \x12AE
+""")
+
+    def test_escape_2(self):
+        self.compare(br"""k\u0045y: \u1234A\uABc6""",
+                     u"""kEy: \u1234A\uabc6
+""")
+
+    def test_escape_3(self):
+        self.compare(br"""k\u0045y: \u1234A\uABc6""",
+                     u"""kEy: \u1234A\uabc6
+""")
+
+    def test_escape_4(self):
+        self.compare(br"""key: '\u1234A\uABc6'""",
+                     u"""key: \u1234A\uabc6
+""")
+
+    def test_escape_5(self):
+        self.compare(br"""key: [\u1234A\uABc6]""",
+                     u"""key: [\u1234A\uabc6]
+""")
+
+    def test_escape_6(self):
+        self.compare(br"""key: [\u1234A\uABc6\,]""",
+                     u"""key: ["\u1234A\uabc6,"]
+""")
+
+    def test_escape_7(self):
+        self.compare(br"""key: [\,\]\#]""",
+                     r"""key: [",]#"]
+""")
+
+    def test_escape_8(self):
+        self.compare(br"""key: \#""",
+                     r"""key: "#"
+""")
+
+    @pytest.mark.xfail(sys.maxunicode == 0xFFFF, reason="narrow unicode")
+    def test_escape_9(self):
+        self.compare(br"""key: \U10FFFFabc""",
+                     u"""key: \U0010FFFFabc
+""")
+
+    def test_escape_10(self):
+        self.compare(br"""key: \u10FFab""",
+                     u"""key: \u10FFab
+""")
+
+    def test_escape_11(self):
+        self.compare(br"""key: \\ab
+""")
+
+    def test_atom_1(self):
+        self.compare(br"""key: @True
+""")
+
+    def test_atom_2(self):
+        self.compare(br"""key: @False
+""")
+
+    def test_atom_3(self):
+        self.compare(br"""key: @Reset
+""")
+
+    def test_atom_4(self):
+        self.compare(br"""key: [a, @Reset, b]
+""")
+
+    def test_conditional_1(self):
+        self.compare(b"""foo:
+  if a or b: [1, 2]
+""")
+
+    def test_if_string_0(self):
+        self.compare(b"""foo: "if bar"
+""")
+
+    def test_non_ascii_1(self):
+        self.compare(b"""[\xf0\x9f\x99\x84]
+""")
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py
new file mode 100644
index 0000000..e811a2b42
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_static.py
@@ -0,0 +1,96 @@
+import unittest
+
+from ..backends import static
+
+# There aren't many tests here because it turns out to be way more convenient to
+# use test_serializer for the majority of cases
+
+
+class TestStatic(unittest.TestCase):
+    def compile(self, input_text, input_data):
+        return static.compile(input_text, input_data)
+
+    def test_get_0(self):
+        data = b"""
+key: value
+
+[Heading 1]
+  other_key:
+    if a == 1: value_1
+    if a == 2: value_2
+    value_3
+"""
+
+        manifest = self.compile(data, {"a": 2})
+
+        self.assertEqual(manifest.get("key"), "value")
+        children = list(item for item in manifest.iterchildren())
+        self.assertEqual(len(children), 1)
+        section = children[0]
+        self.assertEqual(section.name, "Heading 1")
+
+        self.assertEqual(section.get("other_key"), "value_2")
+        self.assertEqual(section.get("key"), "value")
+
+    def test_get_1(self):
+        data = b"""
+key: value
+
+[Heading 1]
+  other_key:
+    if a == 1: value_1
+    if a == 2: value_2
+    value_3
+"""
+        manifest = self.compile(data, {"a": 3})
+
+        children = list(item for item in manifest.iterchildren())
+        section = children[0]
+        self.assertEqual(section.get("other_key"), "value_3")
+
+    def test_get_3(self):
+        data = b"""key:
+  if a == "1": value_1
+  if a[0] == "ab"[0]: value_2
+"""
+        manifest = self.compile(data, {"a": "1"})
+        self.assertEqual(manifest.get("key"), "value_1")
+
+        manifest = self.compile(data, {"a": "ac"})
+        self.assertEqual(manifest.get("key"), "value_2")
+
+    def test_get_4(self):
+        data = b"""key:
+  if not a: value_1
+  value_2
+"""
+        manifest = self.compile(data, {"a": True})
+        self.assertEqual(manifest.get("key"), "value_2")
+
+        manifest = self.compile(data, {"a": False})
+        self.assertEqual(manifest.get("key"), "value_1")
+
+    def test_api(self):
+        data = b"""key:
+  if a == 1.5: value_1
+  value_2
+key_1: other_value
+"""
+        manifest = self.compile(data, {"a": 1.5})
+
+        self.assertFalse(manifest.is_empty)
+        self.assertEqual(manifest.root, manifest)
+        self.assertTrue(manifest.has_key("key_1"))
+        self.assertFalse(manifest.has_key("key_2"))
+
+        self.assertEqual(set(manifest.iterkeys()), {"key", "key_1"})
+        self.assertEqual(set(manifest.itervalues()), {"value_1", "other_value"})
+
+    def test_is_empty_1(self):
+        data = b"""
+[Section]
+  [Subsection]
+"""
+        manifest = self.compile(data, {})
+
+        self.assertTrue(manifest.is_empty)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py
new file mode 100644
index 0000000..66b5805
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptmanifest/tests/test_tokenizer.py
@@ -0,0 +1,335 @@
+import unittest
+
+from .. import parser
+from ..parser import token_types
+
+class TokenizerTest(unittest.TestCase):
+    def setUp(self):
+        self.tokenizer = parser.Tokenizer()
+
+    def tokenize(self, input_str):
+        rv = []
+        for item in self.tokenizer.tokenize(input_str):
+            rv.append(item)
+            if item[0] == token_types.eof:
+                break
+        return rv
+
+    def compare(self, input_text, expected):
+        expected = expected + [(token_types.eof, None)]
+        actual = self.tokenize(input_text)
+        self.assertEqual(actual, expected)
+
+    def test_heading_0(self):
+        self.compare(b"""[Heading text]""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading text"),
+                      (token_types.paren, "]")])
+
+    def test_heading_1(self):
+        self.compare(br"""[Heading [text\]]""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading [text]"),
+                      (token_types.paren, "]")])
+
+    def test_heading_2(self):
+        self.compare(b"""[Heading #text]""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading #text"),
+                      (token_types.paren, "]")])
+
+    def test_heading_3(self):
+        self.compare(br"""[Heading [\]text]""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading []text"),
+                      (token_types.paren, "]")])
+
+    def test_heading_4(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"[Heading")
+
+    def test_heading_5(self):
+        self.compare(br"""[Heading [\]text] #comment""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading []text"),
+                      (token_types.paren, "]")])
+
+    def test_heading_6(self):
+        self.compare(br"""[Heading \ttext]""",
+                     [(token_types.paren, "["),
+                      (token_types.string, "Heading \ttext"),
+                      (token_types.paren, "]")])
+
+    def test_key_0(self):
+        self.compare(b"""key:value""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "value")])
+
+    def test_key_1(self):
+        self.compare(b"""key  :  value""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "value")])
+
+    def test_key_2(self):
+        self.compare(b"""key  :  val ue""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "val ue")])
+
+    def test_key_3(self):
+        self.compare(b"""key: value#comment""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "value")])
+
+    def test_key_4(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""ke y: value""")
+
+    def test_key_5(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key""")
+
+    def test_key_6(self):
+        self.compare(b"""key: "value\"""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "value")])
+
+    def test_key_7(self):
+        self.compare(b"""key: 'value'""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "value")])
+
+    def test_key_8(self):
+        self.compare(b"""key: "#value\"""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "#value")])
+
+    def test_key_9(self):
+        self.compare(b"""key: '#value\'""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, "#value")])
+
+    def test_key_10(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: "value""")
+
+    def test_key_11(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: 'value""")
+
+    def test_key_12(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: 'value""")
+
+    def test_key_13(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: 'value' abc""")
+
+    def test_key_14(self):
+        self.compare(br"""key: \\nb""",
+                     [(token_types.string, "key"),
+                      (token_types.separator, ":"),
+                      (token_types.string, r"\nb")])
+
+    def test_list_0(self):
+        self.compare(b"""
+key: []""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.list_start, "["),
+             (token_types.list_end, "]")])
+
+    def test_list_1(self):
+        self.compare(b"""
+key: [a, "b"]""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.list_start, "["),
+             (token_types.string, "a"),
+             (token_types.string, "b"),
+             (token_types.list_end, "]")])
+
+    def test_list_2(self):
+        self.compare(b"""
+key: [a,
+      b]""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.list_start, "["),
+             (token_types.string, "a"),
+             (token_types.string, "b"),
+             (token_types.list_end, "]")])
+
+    def test_list_3(self):
+        self.compare(b"""
+key: [a, #b]
+      c]""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.list_start, "["),
+             (token_types.string, "a"),
+             (token_types.string, "c"),
+             (token_types.list_end, "]")])
+
+    def test_list_4(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: [a #b]
+            c]""")
+
+    def test_list_5(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""key: [a \\
+            c]""")
+
+    def test_list_6(self):
+        self.compare(b"""key: [a , b]""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.list_start, "["),
+             (token_types.string, "a"),
+             (token_types.string, "b"),
+             (token_types.list_end, "]")])
+
+    def test_expr_0(self):
+        self.compare(b"""
+key:
+  if cond == 1: value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.number, "1"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_1(self):
+        self.compare(b"""
+key:
+  if cond == 1: value1
+  value2""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.number, "1"),
+             (token_types.separator, ":"),
+             (token_types.string, "value1"),
+             (token_types.string, "value2")])
+
+    def test_expr_2(self):
+        self.compare(b"""
+key:
+  if cond=="1": value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.string, "1"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_3(self):
+        self.compare(b"""
+key:
+  if cond==1.1: value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.number, "1.1"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_4(self):
+        self.compare(b"""
+key:
+  if cond==1.1 and cond2 == "a": value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.number, "1.1"),
+             (token_types.ident, "and"),
+             (token_types.ident, "cond2"),
+             (token_types.ident, "=="),
+             (token_types.string, "a"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_5(self):
+        self.compare(b"""
+key:
+  if (cond==1.1 ): value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.paren, "("),
+             (token_types.ident, "cond"),
+             (token_types.ident, "=="),
+             (token_types.number, "1.1"),
+             (token_types.paren, ")"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_6(self):
+        self.compare(b"""
+key:
+  if "\\ttest": value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.string, "\ttest"),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+    def test_expr_7(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""
+key:
+  if 1A: value""")
+
+    def test_expr_8(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""
+key:
+  if 1a: value""")
+
+    def test_expr_9(self):
+        with self.assertRaises(parser.ParseError):
+            self.tokenize(b"""
+key:
+  if 1.1.1: value""")
+
+    def test_expr_10(self):
+        self.compare(b"""
+key:
+  if 1.: value""",
+            [(token_types.string, "key"),
+             (token_types.separator, ":"),
+             (token_types.group_start, None),
+             (token_types.ident, "if"),
+             (token_types.number, "1."),
+             (token_types.separator, ":"),
+             (token_types.string, "value")])
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptrunner.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptrunner.py
new file mode 100644
index 0000000..3fc9e39
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wptrunner.py
@@ -0,0 +1,433 @@
+from __future__ import print_function, unicode_literals
+
+import json
+import os
+import sys
+
+from six import iteritems, itervalues
+
+import wptserve
+from wptserve import sslutils
+
+from . import environment as env
+from . import instruments
+from . import mpcontext
+from . import products
+from . import testloader
+from . import wptcommandline
+from . import wptlogging
+from . import wpttest
+from mozlog import capture, handlers
+from .font import FontInstaller
+from .testrunner import ManagerGroup
+from .browsers.base import NullBrowser
+
+here = os.path.dirname(__file__)
+
+logger = None
+
+"""Runner for web-platform-tests
+
+The runner has several design goals:
+
+* Tests should run with no modification from upstream.
+
+* Tests should be regarded as "untrusted" so that errors, timeouts and even
+  crashes in the tests can be handled without failing the entire test run.
+
+* For performance tests can be run in multiple browsers in parallel.
+
+The upstream repository has the facility for creating a test manifest in JSON
+format. This manifest is used directly to determine which tests exist. Local
+metadata files are used to store the expected test results.
+"""
+
+def setup_logging(*args, **kwargs):
+    global logger
+    logger = wptlogging.setup(*args, **kwargs)
+    return logger
+
+
+def get_loader(test_paths, product, debug=None, run_info_extras=None, chunker_kwargs=None,
+               test_groups=None, **kwargs):
+    if run_info_extras is None:
+        run_info_extras = {}
+
+    run_info = wpttest.get_run_info(kwargs["run_info"], product,
+                                    browser_version=kwargs.get("browser_version"),
+                                    browser_channel=kwargs.get("browser_channel"),
+                                    verify=kwargs.get("verify"),
+                                    debug=debug,
+                                    extras=run_info_extras,
+                                    enable_webrender=kwargs.get("enable_webrender"))
+
+    test_manifests = testloader.ManifestLoader(test_paths, force_manifest_update=kwargs["manifest_update"],
+                                               manifest_download=kwargs["manifest_download"]).load()
+
+    manifest_filters = []
+
+    include = kwargs["include"]
+    if test_groups:
+        include = testloader.update_include_for_groups(test_groups, include)
+
+    if include or kwargs["exclude"] or kwargs["include_manifest"] or kwargs["default_exclude"]:
+        manifest_filters.append(testloader.TestFilter(include=include,
+                                                      exclude=kwargs["exclude"],
+                                                      manifest_path=kwargs["include_manifest"],
+                                                      test_manifests=test_manifests,
+                                                      explicit=kwargs["default_exclude"]))
+
+    ssl_enabled = sslutils.get_cls(kwargs["ssl_type"]).ssl_enabled
+    h2_enabled = wptserve.utils.http2_compatible()
+    test_loader = testloader.TestLoader(test_manifests,
+                                        kwargs["test_types"],
+                                        run_info,
+                                        manifest_filters=manifest_filters,
+                                        chunk_type=kwargs["chunk_type"],
+                                        total_chunks=kwargs["total_chunks"],
+                                        chunk_number=kwargs["this_chunk"],
+                                        include_https=ssl_enabled,
+                                        include_h2=h2_enabled,
+                                        include_quic=kwargs["enable_quic"],
+                                        skip_timeout=kwargs["skip_timeout"],
+                                        skip_implementation_status=kwargs["skip_implementation_status"],
+                                        chunker_kwargs=chunker_kwargs)
+    return run_info, test_loader
+
+
+def list_test_groups(test_paths, product, **kwargs):
+    env.do_delayed_imports(logger, test_paths)
+
+    run_info_extras = products.load_product(kwargs["config"], product)[-1](**kwargs)
+
+    run_info, test_loader = get_loader(test_paths, product,
+                                       run_info_extras=run_info_extras, **kwargs)
+
+    for item in sorted(test_loader.groups(kwargs["test_types"])):
+        print(item)
+
+
+def list_disabled(test_paths, product, **kwargs):
+    env.do_delayed_imports(logger, test_paths)
+
+    rv = []
+
+    run_info_extras = products.load_product(kwargs["config"], product)[-1](**kwargs)
+
+    run_info, test_loader = get_loader(test_paths, product,
+                                       run_info_extras=run_info_extras, **kwargs)
+
+    for test_type, tests in iteritems(test_loader.disabled_tests):
+        for test in tests:
+            rv.append({"test": test.id, "reason": test.disabled()})
+    print(json.dumps(rv, indent=2))
+
+
+def list_tests(test_paths, product, **kwargs):
+    env.do_delayed_imports(logger, test_paths)
+
+    run_info_extras = products.load_product(kwargs["config"], product)[-1](**kwargs)
+
+    run_info, test_loader = get_loader(test_paths, product,
+                                       run_info_extras=run_info_extras, **kwargs)
+
+    for test in test_loader.test_ids:
+        print(test)
+
+
+def get_pause_after_test(test_loader, **kwargs):
+    if kwargs["pause_after_test"] is None:
+        if kwargs["repeat_until_unexpected"]:
+            return False
+        if kwargs["headless"]:
+            return False
+        tests = test_loader.tests
+        is_single_testharness = (sum(len(item) for item in itervalues(tests)) == 1 and
+                                 len(tests.get("testharness", [])) == 1)
+        if kwargs["repeat"] == 1 and kwargs["rerun"] == 1 and is_single_testharness:
+            return True
+        return False
+    return kwargs["pause_after_test"]
+
+
+def run_tests(config, test_paths, product, **kwargs):
+    """Set up the test environment, load the list of tests to be executed, and
+    invoke the remainder of the code to execute tests"""
+    mp = mpcontext.get_context()
+    if kwargs["instrument_to_file"] is None:
+        recorder = instruments.NullInstrument()
+    else:
+        recorder = instruments.Instrument(kwargs["instrument_to_file"])
+    with recorder as recording, capture.CaptureIO(logger,
+                                                  not kwargs["no_capture_stdio"],
+                                                  mp_context=mp):
+        recording.set(["startup"])
+        env.do_delayed_imports(logger, test_paths)
+
+        product = products.load_product(config, product, load_cls=True)
+
+        env_extras = product.get_env_extras(**kwargs)
+
+        product.check_args(**kwargs)
+
+        if kwargs["install_fonts"]:
+            env_extras.append(FontInstaller(
+                logger,
+                font_dir=kwargs["font_dir"],
+                ahem=os.path.join(test_paths["/"]["tests_path"], "fonts/Ahem.ttf")
+            ))
+
+        recording.set(["startup", "load_tests"])
+
+        test_groups = (testloader.TestGroupsFile(logger, kwargs["test_groups_file"])
+                       if kwargs["test_groups_file"] else None)
+
+        (test_source_cls,
+         test_source_kwargs,
+         chunker_kwargs) = testloader.get_test_src(logger=logger,
+                                                   test_groups=test_groups,
+                                                   **kwargs)
+        run_info, test_loader = get_loader(test_paths,
+                                           product.name,
+                                           run_info_extras=product.run_info_extras(**kwargs),
+                                           chunker_kwargs=chunker_kwargs,
+                                           test_groups=test_groups,
+                                           **kwargs)
+
+        logger.info("Using %i client processes" % kwargs["processes"])
+
+        skipped_tests = 0
+        test_total = 0
+        unexpected_total = 0
+
+        if len(test_loader.test_ids) == 0 and kwargs["test_list"]:
+            logger.critical("Unable to find any tests at the path(s):")
+            for path in kwargs["test_list"]:
+                logger.critical("  %s" % path)
+            logger.critical("Please check spelling and make sure there are tests in the specified path(s).")
+            return False
+        kwargs["pause_after_test"] = get_pause_after_test(test_loader, **kwargs)
+
+        ssl_config = {"type": kwargs["ssl_type"],
+                      "openssl": {"openssl_binary": kwargs["openssl_binary"]},
+                      "pregenerated": {"host_key_path": kwargs["host_key_path"],
+                                       "host_cert_path": kwargs["host_cert_path"],
+                                       "ca_cert_path": kwargs["ca_cert_path"]}}
+
+        testharness_timeout_multipler = product.get_timeout_multiplier("testharness",
+                                                                       run_info,
+                                                                       **kwargs)
+
+        mojojs_path = kwargs["mojojs_path"] if kwargs["enable_mojojs"] else None
+
+        recording.set(["startup", "start_environment"])
+        with env.TestEnvironment(test_paths,
+                                 testharness_timeout_multipler,
+                                 kwargs["pause_after_test"],
+                                 kwargs["debug_info"],
+                                 product.env_options,
+                                 ssl_config,
+                                 env_extras,
+                                 kwargs["enable_quic"],
+                                 mojojs_path) as test_environment:
+            recording.set(["startup", "ensure_environment"])
+            try:
+                test_environment.ensure_started()
+            except env.TestEnvironmentError as e:
+                logger.critical("Error starting test environment: %s" % e.message)
+                raise
+
+            recording.set(["startup"])
+
+            repeat = kwargs["repeat"]
+            repeat_count = 0
+            repeat_until_unexpected = kwargs["repeat_until_unexpected"]
+
+            while repeat_count < repeat or repeat_until_unexpected:
+                repeat_count += 1
+                if repeat_until_unexpected:
+                    logger.info("Repetition %i" % (repeat_count))
+                elif repeat > 1:
+                    logger.info("Repetition %i / %i" % (repeat_count, repeat))
+
+                test_count = 0
+                unexpected_count = 0
+
+                tests = []
+                for test_type in test_loader.test_types:
+                    tests.extend(test_loader.tests[test_type])
+
+                try:
+                    test_groups = test_source_cls.tests_by_group(tests, **test_source_kwargs)
+                except Exception:
+                    logger.critical("Loading tests failed")
+                    return False
+
+                logger.suite_start(test_groups,
+                                   name='web-platform-test',
+                                   run_info=run_info,
+                                   extra={"run_by_dir": kwargs["run_by_dir"]})
+                for test_type in kwargs["test_types"]:
+                    logger.info("Running %s tests" % test_type)
+
+                    # WebDriver tests may create and destroy multiple browser
+                    # processes as part of their expected behavior. These
+                    # processes are managed by a WebDriver server binary. This
+                    # obviates the need for wptrunner to provide a browser, so
+                    # the NullBrowser is used in place of the "target" browser
+                    if test_type == "wdspec":
+                        browser_cls = NullBrowser
+                    else:
+                        browser_cls = product.browser_cls
+
+                    browser_kwargs = product.get_browser_kwargs(logger,
+                                                                test_type,
+                                                                run_info,
+                                                                config=test_environment.config,
+                                                                **kwargs)
+
+                    executor_cls = product.executor_classes.get(test_type)
+                    executor_kwargs = product.get_executor_kwargs(logger,
+                                                                  test_type,
+                                                                  test_environment.config,
+                                                                  test_environment.cache_manager,
+                                                                  run_info,
+                                                                  **kwargs)
+
+                    if executor_cls is None:
+                        logger.error("Unsupported test type %s for product %s" %
+                                     (test_type, product.name))
+                        continue
+
+                    for test in test_loader.disabled_tests[test_type]:
+                        logger.test_start(test.id)
+                        logger.test_end(test.id, status="SKIP")
+                        skipped_tests += 1
+
+                    if test_type == "testharness":
+                        run_tests = {"testharness": []}
+                        for test in test_loader.tests["testharness"]:
+                            if ((test.testdriver and not executor_cls.supports_testdriver) or
+                                (test.jsshell and not executor_cls.supports_jsshell)):
+                                logger.test_start(test.id)
+                                logger.test_end(test.id, status="SKIP")
+                                skipped_tests += 1
+                            else:
+                                run_tests["testharness"].append(test)
+                    else:
+                        run_tests = test_loader.tests
+
+                    recording.pause()
+                    with ManagerGroup("web-platform-tests",
+                                      kwargs["processes"],
+                                      test_source_cls,
+                                      test_source_kwargs,
+                                      browser_cls,
+                                      browser_kwargs,
+                                      executor_cls,
+                                      executor_kwargs,
+                                      kwargs["rerun"],
+                                      kwargs["pause_after_test"],
+                                      kwargs["pause_on_unexpected"],
+                                      kwargs["restart_on_unexpected"],
+                                      kwargs["debug_info"],
+                                      not kwargs["no_capture_stdio"],
+                                      recording=recording) as manager_group:
+                        try:
+                            manager_group.run(test_type, run_tests)
+                        except KeyboardInterrupt:
+                            logger.critical("Main thread got signal")
+                            manager_group.stop()
+                            raise
+                        test_count += manager_group.test_count()
+                        unexpected_count += manager_group.unexpected_count()
+                recording.set(["after-end"])
+                test_total += test_count
+                unexpected_total += unexpected_count
+                logger.info("Got %i unexpected results" % unexpected_count)
+                logger.suite_end()
+                if repeat_until_unexpected and unexpected_total > 0:
+                    break
+                if repeat_count == 1 and len(test_loader.test_ids) == skipped_tests:
+                    break
+
+    if test_total == 0:
+        if skipped_tests > 0:
+            logger.warning("All requested tests were skipped")
+        else:
+            if kwargs["default_exclude"]:
+                logger.info("No tests ran")
+                return True
+            else:
+                logger.critical("No tests ran")
+                return False
+
+    if unexpected_total and not kwargs["fail_on_unexpected"]:
+        logger.info("Tolerating %s unexpected results" % unexpected_total)
+        return True
+
+    return unexpected_total == 0
+
+
+def check_stability(**kwargs):
+    from . import stability
+    if kwargs["stability"]:
+        logger.warning("--stability is deprecated; please use --verify instead!")
+        kwargs['verify_max_time'] = None
+        kwargs['verify_chaos_mode'] = False
+        kwargs['verify_repeat_loop'] = 0
+        kwargs['verify_repeat_restart'] = 10 if kwargs['repeat'] == 1 else kwargs['repeat']
+        kwargs['verify_output_results'] = True
+
+    return stability.check_stability(logger,
+                                     max_time=kwargs['verify_max_time'],
+                                     chaos_mode=kwargs['verify_chaos_mode'],
+                                     repeat_loop=kwargs['verify_repeat_loop'],
+                                     repeat_restart=kwargs['verify_repeat_restart'],
+                                     output_results=kwargs['verify_output_results'],
+                                     **kwargs)
+
+
+def start(**kwargs):
+    assert logger is not None
+
+    logged_critical = wptlogging.LoggedAboveLevelHandler("CRITICAL")
+    handler = handlers.LogLevelFilter(logged_critical, "CRITICAL")
+    logger.add_handler(handler)
+
+    rv = False
+    try:
+        if kwargs["list_test_groups"]:
+            list_test_groups(**kwargs)
+        elif kwargs["list_disabled"]:
+            list_disabled(**kwargs)
+        elif kwargs["list_tests"]:
+            list_tests(**kwargs)
+        elif kwargs["verify"] or kwargs["stability"]:
+            rv = check_stability(**kwargs) or logged_critical.has_log
+        else:
+            rv = not run_tests(**kwargs) or logged_critical.has_log
+    finally:
+        logger.remove_handler(handler)
+    return rv
+
+
+def main():
+    """Main entry point when calling from the command line"""
+    kwargs = wptcommandline.parse_args()
+
+    try:
+        if kwargs["prefs_root"] is None:
+            kwargs["prefs_root"] = os.path.abspath(os.path.join(here, "prefs"))
+
+        setup_logging(kwargs, {"raw": sys.stdout})
+
+        return start(**kwargs)
+    except Exception:
+        if kwargs["pdb"]:
+            import pdb
+            import traceback
+            print(traceback.format_exc())
+            pdb.post_mortem()
+        else:
+            raise
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wpttest.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wpttest.py
new file mode 100644
index 0000000..ed9184e
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/tools/wptrunner/wptrunner/wpttest.py
@@ -0,0 +1,671 @@
+import os
+import subprocess
+import sys
+from six.moves.urllib.parse import urljoin
+from collections import defaultdict
+from six import iteritems, string_types
+
+from .wptmanifest.parser import atoms
+
+atom_reset = atoms["Reset"]
+enabled_tests = {"testharness", "reftest", "wdspec", "crashtest", "print-reftest"}
+
+
+class Result(object):
+    def __init__(self,
+                 status,
+                 message,
+                 expected=None,
+                 extra=None,
+                 stack=None,
+                 known_intermittent=None):
+        if status not in self.statuses:
+            raise ValueError("Unrecognised status %s" % status)
+        self.status = status
+        self.message = message
+        self.expected = expected
+        self.known_intermittent = known_intermittent if known_intermittent is not None else []
+        self.extra = extra if extra is not None else {}
+        self.stack = stack
+
+    def __repr__(self):
+        return "<%s.%s %s>" % (self.__module__, self.__class__.__name__, self.status)
+
+
+class SubtestResult(object):
+    def __init__(self, name, status, message, stack=None, expected=None, known_intermittent=None):
+        self.name = name
+        if status not in self.statuses:
+            raise ValueError("Unrecognised status %s" % status)
+        self.status = status
+        self.message = message
+        self.stack = stack
+        self.expected = expected
+        self.known_intermittent = known_intermittent if known_intermittent is not None else []
+
+    def __repr__(self):
+        return "<%s.%s %s %s>" % (self.__module__, self.__class__.__name__, self.name, self.status)
+
+
+class TestharnessResult(Result):
+    default_expected = "OK"
+    statuses = {"OK", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH", "PRECONDITION_FAILED"}
+
+
+class TestharnessSubtestResult(SubtestResult):
+    default_expected = "PASS"
+    statuses = {"PASS", "FAIL", "TIMEOUT", "NOTRUN", "PRECONDITION_FAILED"}
+
+
+class ReftestResult(Result):
+    default_expected = "PASS"
+    statuses = {"PASS", "FAIL", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT",
+                "CRASH"}
+
+
+class WdspecResult(Result):
+    default_expected = "OK"
+    statuses = {"OK", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT", "CRASH"}
+
+
+class WdspecSubtestResult(SubtestResult):
+    default_expected = "PASS"
+    statuses = {"PASS", "FAIL", "ERROR"}
+
+
+class CrashtestResult(Result):
+    default_expected = "PASS"
+    statuses = {"PASS", "ERROR", "INTERNAL-ERROR", "TIMEOUT", "EXTERNAL-TIMEOUT",
+                "CRASH"}
+
+
+def get_run_info(metadata_root, product, **kwargs):
+    return RunInfo(metadata_root, product, **kwargs)
+
+
+class RunInfo(dict):
+    def __init__(self, metadata_root, product, debug,
+                 browser_version=None,
+                 browser_channel=None,
+                 verify=None,
+                 extras=None,
+                 enable_webrender=False):
+        import mozinfo
+        self._update_mozinfo(metadata_root)
+        self.update(mozinfo.info)
+
+        from .update.tree import GitTree
+        try:
+            # GitTree.__init__ throws if we are not in a git tree.
+            rev = GitTree(log_error=False).rev
+        except (OSError, subprocess.CalledProcessError):
+            rev = None
+        if rev:
+            self["revision"] = rev.decode("utf-8")
+
+        self["python_version"] = sys.version_info.major
+        self["product"] = product
+        if debug is not None:
+            self["debug"] = debug
+        elif "debug" not in self:
+            # Default to release
+            self["debug"] = False
+        if browser_version:
+            self["browser_version"] = browser_version
+        if browser_channel:
+            self["browser_channel"] = browser_channel
+
+        self["verify"] = verify
+        if "wasm" not in self:
+            self["wasm"] = False
+        if extras is not None:
+            self.update(extras)
+
+        self["headless"] = extras.get("headless", False)
+        self["webrender"] = enable_webrender
+
+    def _update_mozinfo(self, metadata_root):
+        """Add extra build information from a mozinfo.json file in a parent
+        directory"""
+        import mozinfo
+
+        path = metadata_root
+        dirs = set()
+        while path != os.path.expanduser('~'):
+            if path in dirs:
+                break
+            dirs.add(str(path))
+            path = os.path.dirname(path)
+
+        mozinfo.find_and_update_from_json(*dirs)
+
+
+def server_protocol(manifest_item):
+    if hasattr(manifest_item, "h2") and manifest_item.h2:
+        return "h2"
+    if hasattr(manifest_item, "https") and manifest_item.https:
+        return "https"
+    return "http"
+
+
+class Test(object):
+
+    result_cls = None
+    subtest_result_cls = None
+    test_type = None
+
+    default_timeout = 10  # seconds
+    long_timeout = 60  # seconds
+
+    def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata,
+                 timeout=None, path=None, protocol="http", subdomain=False,
+                 quic=False):
+        self.url_base = url_base
+        self.tests_root = tests_root
+        self.url = url
+        self._inherit_metadata = inherit_metadata
+        self._test_metadata = test_metadata
+        self.timeout = timeout if timeout is not None else self.default_timeout
+        self.path = path
+        self.subdomain = subdomain
+        self.environment = {"url_base": url_base,
+                            "protocol": protocol,
+                            "prefs": self.prefs,
+                            "quic": quic}
+
+    def __eq__(self, other):
+        if not isinstance(other, Test):
+            return False
+        return self.id == other.id
+
+    # Python 2 does not have this delegation, while Python 3 does.
+    def __ne__(self, other):
+        return not self.__eq__(other)
+
+    def update_metadata(self, metadata=None):
+        if metadata is None:
+            metadata = {}
+        return metadata
+
+    @classmethod
+    def from_manifest(cls, manifest_file, manifest_item, inherit_metadata, test_metadata):
+        timeout = cls.long_timeout if manifest_item.timeout == "long" else cls.default_timeout
+        return cls(manifest_file.url_base,
+                   manifest_file.tests_root,
+                   manifest_item.url,
+                   inherit_metadata,
+                   test_metadata,
+                   timeout=timeout,
+                   path=os.path.join(manifest_file.tests_root, manifest_item.path),
+                   protocol=server_protocol(manifest_item),
+                   subdomain=manifest_item.subdomain)
+
+    @property
+    def id(self):
+        return self.url
+
+    @property
+    def keys(self):
+        return tuple()
+
+    @property
+    def abs_path(self):
+        return os.path.join(self.tests_root, self.path)
+
+    def _get_metadata(self, subtest=None):
+        if self._test_metadata is not None and subtest is not None:
+            return self._test_metadata.get_subtest(subtest)
+        else:
+            return self._test_metadata
+
+    def itermeta(self, subtest=None):
+        if self._test_metadata is not None:
+            if subtest is not None:
+                subtest_meta = self._get_metadata(subtest)
+                if subtest_meta is not None:
+                    yield subtest_meta
+            yield self._get_metadata()
+        for metadata in reversed(self._inherit_metadata):
+            yield metadata
+
+    def disabled(self, subtest=None):
+        for meta in self.itermeta(subtest):
+            disabled = meta.disabled
+            if disabled is not None:
+                return disabled
+        return None
+
+    @property
+    def restart_after(self):
+        for meta in self.itermeta(None):
+            restart_after = meta.restart_after
+            if restart_after is not None:
+                return True
+        return False
+
+    @property
+    def leaks(self):
+        for meta in self.itermeta(None):
+            leaks = meta.leaks
+            if leaks is not None:
+                return leaks
+        return False
+
+    @property
+    def min_assertion_count(self):
+        for meta in self.itermeta(None):
+            count = meta.min_assertion_count
+            if count is not None:
+                return count
+        return 0
+
+    @property
+    def max_assertion_count(self):
+        for meta in self.itermeta(None):
+            count = meta.max_assertion_count
+            if count is not None:
+                return count
+        return 0
+
+    @property
+    def lsan_disabled(self):
+        for meta in self.itermeta():
+            if meta.lsan_disabled is not None:
+                return meta.lsan_disabled
+        return False
+
+    @property
+    def lsan_allowed(self):
+        lsan_allowed = set()
+        for meta in self.itermeta():
+            lsan_allowed |= meta.lsan_allowed
+            if atom_reset in lsan_allowed:
+                lsan_allowed.remove(atom_reset)
+                break
+        return lsan_allowed
+
+    @property
+    def lsan_max_stack_depth(self):
+        for meta in self.itermeta(None):
+            depth = meta.lsan_max_stack_depth
+            if depth is not None:
+                return depth
+        return None
+
+    @property
+    def mozleak_allowed(self):
+        mozleak_allowed = set()
+        for meta in self.itermeta():
+            mozleak_allowed |= meta.leak_allowed
+            if atom_reset in mozleak_allowed:
+                mozleak_allowed.remove(atom_reset)
+                break
+        return mozleak_allowed
+
+    @property
+    def mozleak_threshold(self):
+        rv = {}
+        for meta in self.itermeta(None):
+            threshold = meta.leak_threshold
+            for key, value in iteritems(threshold):
+                if key not in rv:
+                    rv[key] = value
+        return rv
+
+    @property
+    def tags(self):
+        tags = set()
+        for meta in self.itermeta():
+            meta_tags = meta.tags
+            tags |= meta_tags
+            if atom_reset in meta_tags:
+                tags.remove(atom_reset)
+                break
+
+        tags.add("dir:%s" % self.id.lstrip("/").split("/")[0])
+
+        return tags
+
+    @property
+    def prefs(self):
+        prefs = {}
+        for meta in reversed(list(self.itermeta())):
+            meta_prefs = meta.prefs
+            if atom_reset in meta_prefs:
+                del meta_prefs[atom_reset]
+                prefs = {}
+            prefs.update(meta_prefs)
+        return prefs
+
+    def expected(self, subtest=None):
+        if subtest is None:
+            default = self.result_cls.default_expected
+        else:
+            default = self.subtest_result_cls.default_expected
+
+        metadata = self._get_metadata(subtest)
+        if metadata is None:
+            return default
+
+        try:
+            expected = metadata.get("expected")
+            if isinstance(expected, string_types):
+                return expected
+            elif isinstance(expected, list):
+                return expected[0]
+            elif expected is None:
+                return default
+        except KeyError:
+            return default
+
+    def implementation_status(self):
+        implementation_status = None
+        for meta in self.itermeta():
+            implementation_status = meta.implementation_status
+            if implementation_status:
+                return implementation_status
+
+        # assuming no specific case, we are implementing it
+        return "implementing"
+
+    def known_intermittent(self, subtest=None):
+        metadata = self._get_metadata(subtest)
+        if metadata is None:
+            return []
+
+        try:
+            expected = metadata.get("expected")
+            if isinstance(expected, list):
+                return expected[1:]
+            return []
+        except KeyError:
+            return []
+
+    def expect_any_subtest_status(self):
+        metadata = self._get_metadata()
+        if metadata is None:
+            return False
+        try:
+            # This key is used by the Blink CI to ignore subtest statuses
+            metadata.get("blink_expect_any_subtest_status")
+            return True
+        except KeyError:
+            return False
+
+    def __repr__(self):
+        return "<%s.%s %s>" % (self.__module__, self.__class__.__name__, self.id)
+
+
+class TestharnessTest(Test):
+    result_cls = TestharnessResult
+    subtest_result_cls = TestharnessSubtestResult
+    test_type = "testharness"
+
+    def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata,
+                 timeout=None, path=None, protocol="http", testdriver=False,
+                 jsshell=False, scripts=None, subdomain=False, quic=False):
+        Test.__init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, timeout,
+                      path, protocol, subdomain, quic)
+
+        self.testdriver = testdriver
+        self.jsshell = jsshell
+        self.scripts = scripts or []
+
+    @classmethod
+    def from_manifest(cls, manifest_file, manifest_item, inherit_metadata, test_metadata):
+        timeout = cls.long_timeout if manifest_item.timeout == "long" else cls.default_timeout
+        testdriver = manifest_item.testdriver if hasattr(manifest_item, "testdriver") else False
+        jsshell = manifest_item.jsshell if hasattr(manifest_item, "jsshell") else False
+        quic = manifest_item.quic if hasattr(manifest_item, "quic") else False
+        script_metadata = manifest_item.script_metadata or []
+        scripts = [v for (k, v) in script_metadata
+                   if k == "script"]
+        return cls(manifest_file.url_base,
+                   manifest_file.tests_root,
+                   manifest_item.url,
+                   inherit_metadata,
+                   test_metadata,
+                   timeout=timeout,
+                   path=os.path.join(manifest_file.tests_root, manifest_item.path),
+                   protocol=server_protocol(manifest_item),
+                   testdriver=testdriver,
+                   jsshell=jsshell,
+                   scripts=scripts,
+                   subdomain=manifest_item.subdomain,
+                   quic=quic)
+
+    @property
+    def id(self):
+        return self.url
+
+
+class ManualTest(Test):
+    test_type = "manual"
+
+    @property
+    def id(self):
+        return self.url
+
+
+class ReftestTest(Test):
+    """A reftest
+
+    A reftest should be considered to pass if one of its references matches (see below) *and* the
+    reference passes if it has any references recursively.
+
+    Attributes:
+        references (List[Tuple[str, str]]): a list of alternate references, where one must match for the test to pass
+        viewport_size (Optional[Tuple[int, int]]): size of the viewport for this test, if not default
+        dpi (Optional[int]): dpi to use when rendering this test, if not default
+
+    """
+    result_cls = ReftestResult
+    test_type = "reftest"
+
+    def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, references,
+                 timeout=None, path=None, viewport_size=None, dpi=None, fuzzy=None,
+                 protocol="http", subdomain=False, quic=False):
+        Test.__init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, timeout,
+                      path, protocol, subdomain, quic)
+
+        for _, ref_type in references:
+            if ref_type not in ("==", "!="):
+                raise ValueError
+
+        self.references = references
+        self.viewport_size = self.get_viewport_size(viewport_size)
+        self.dpi = dpi
+        self._fuzzy = fuzzy or {}
+
+    @classmethod
+    def cls_kwargs(cls, manifest_test):
+        return {"viewport_size": manifest_test.viewport_size,
+                "dpi": manifest_test.dpi,
+                "protocol": server_protocol(manifest_test),
+                "fuzzy": manifest_test.fuzzy}
+
+    @classmethod
+    def from_manifest(cls,
+                      manifest_file,
+                      manifest_test,
+                      inherit_metadata,
+                      test_metadata):
+
+        timeout = cls.long_timeout if manifest_test.timeout == "long" else cls.default_timeout
+        quic = manifest_test.quic if hasattr(manifest_test, "quic") else False
+
+        url = manifest_test.url
+
+        node = cls(manifest_file.url_base,
+                   manifest_file.tests_root,
+                   manifest_test.url,
+                   inherit_metadata,
+                   test_metadata,
+                   [],
+                   timeout=timeout,
+                   path=manifest_test.path,
+                   subdomain=manifest_test.subdomain,
+                   quic=quic,
+                   **cls.cls_kwargs(manifest_test))
+
+        refs_by_type = defaultdict(list)
+
+        for ref_url, ref_type in manifest_test.references:
+            refs_by_type[ref_type].append(ref_url)
+
+        # Construct a list of all the mismatches, where we end up with mismatch_1 != url !=
+        # mismatch_2 != url != mismatch_3 etc.
+        #
+        # Per the logic documented above, this means that none of the mismatches provided match,
+        mismatch_walk = None
+        if refs_by_type["!="]:
+            mismatch_walk = ReftestTest(manifest_file.url_base,
+                                        manifest_file.tests_root,
+                                        refs_by_type["!="][0],
+                                        [],
+                                        None,
+                                        [])
+            cmp_ref = mismatch_walk
+            for ref_url in refs_by_type["!="][1:]:
+                cmp_self = ReftestTest(manifest_file.url_base,
+                                       manifest_file.tests_root,
+                                       url,
+                                       [],
+                                       None,
+                                       [])
+                cmp_ref.references.append((cmp_self, "!="))
+                cmp_ref = ReftestTest(manifest_file.url_base,
+                                      manifest_file.tests_root,
+                                      ref_url,
+                                      [],
+                                      None,
+                                      [])
+                cmp_self.references.append((cmp_ref, "!="))
+
+        if mismatch_walk is None:
+            mismatch_refs = []
+        else:
+            mismatch_refs = [(mismatch_walk, "!=")]
+
+        if refs_by_type["=="]:
+            # For each == ref, add a reference to this node whose tail is the mismatch list.
+            # Per the logic documented above, this means any one of the matches must pass plus all the mismatches.
+            for ref_url in refs_by_type["=="]:
+                ref = ReftestTest(manifest_file.url_base,
+                                  manifest_file.tests_root,
+                                  ref_url,
+                                  [],
+                                  None,
+                                  mismatch_refs)
+                node.references.append((ref, "=="))
+        else:
+            # Otherwise, we just add the mismatches directly as we are immediately into the
+            # mismatch chain with no alternates.
+            node.references.extend(mismatch_refs)
+
+        return node
+
+    def update_metadata(self, metadata):
+        if "url_count" not in metadata:
+            metadata["url_count"] = defaultdict(int)
+        for reference, _ in self.references:
+            # We assume a naive implementation in which a url with multiple
+            # possible screenshots will need to take both the lhs and rhs screenshots
+            # for each possible match
+            metadata["url_count"][(self.environment["protocol"], reference.url)] += 1
+            reference.update_metadata(metadata)
+        return metadata
+
+    def get_viewport_size(self, override):
+        return override
+
+    @property
+    def id(self):
+        return self.url
+
+    @property
+    def keys(self):
+        return ("reftype", "refurl")
+
+    @property
+    def fuzzy(self):
+        return self._fuzzy
+
+    @property
+    def fuzzy_override(self):
+        values = {}
+        for meta in reversed(list(self.itermeta(None))):
+            value = meta.fuzzy
+            if not value:
+                continue
+            if atom_reset in value:
+                value.remove(atom_reset)
+                values = {}
+            for key, data in value:
+                if isinstance(key, (tuple, list)):
+                    key = list(key)
+                    key[0] = urljoin(self.url, key[0])
+                    key[1] = urljoin(self.url, key[1])
+                    key = tuple(key)
+                elif key:
+                    # Key is just a relative url to a ref
+                    key = urljoin(self.url, key)
+                values[key] = data
+        return values
+
+    @property
+    def page_ranges(self):
+        return {}
+
+
+class PrintReftestTest(ReftestTest):
+    test_type = "print-reftest"
+
+    def __init__(self, url_base, tests_root, url, inherit_metadata, test_metadata, references,
+                 timeout=None, path=None, viewport_size=None, dpi=None, fuzzy=None,
+                 page_ranges=None, protocol="http", subdomain=False, quic=False):
+        super(PrintReftestTest, self).__init__(url_base, tests_root, url, inherit_metadata, test_metadata,
+                                               references, timeout, path, viewport_size, dpi,
+                                               fuzzy, protocol, subdomain=subdomain, quic=quic)
+        self._page_ranges = page_ranges
+
+    @classmethod
+    def cls_kwargs(cls, manifest_test):
+        rv = super(PrintReftestTest, cls).cls_kwargs(manifest_test)
+        rv["page_ranges"] = manifest_test.page_ranges
+        return rv
+
+    def get_viewport_size(self, override):
+        assert override is None
+        return (5*2.54, 3*2.54)
+
+    @property
+    def page_ranges(self):
+        return self._page_ranges
+
+
+class WdspecTest(Test):
+    result_cls = WdspecResult
+    subtest_result_cls = WdspecSubtestResult
+    test_type = "wdspec"
+
+    default_timeout = 25
+    long_timeout = 180  # 3 minutes
+
+
+class CrashTest(Test):
+    result_cls = CrashtestResult
+    test_type = "crashtest"
+
+
+manifest_test_cls = {"reftest": ReftestTest,
+                     "print-reftest": PrintReftestTest,
+                     "testharness": TestharnessTest,
+                     "manual": ManualTest,
+                     "wdspec": WdspecTest,
+                     "crashtest": CrashTest}
+
+
+def from_manifest(manifest_file, manifest_test, inherit_metadata, test_metadata):
+    test_cls = manifest_test_cls[manifest_test.item_type]
+    return test_cls.from_manifest(manifest_file, manifest_test, inherit_metadata, test_metadata)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/basic_auth_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/basic_auth_wsh.py
new file mode 100755
index 0000000..1bfa45b
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/basic_auth_wsh.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+
+"""A WebSocket handler that enforces basic HTTP authentication. Username is
+'foo' and password is 'bar'."""
+
+
+from mod_pywebsocket.handshake import AbortedByUserException
+
+
+def web_socket_do_extra_handshake(request):
+    authorization = request.headers_in.get('Authorization')
+    if authorization is None or authorization != 'Basic Zm9vOmJhcg==':
+        request.connection.write(b'HTTP/1.1 401 Unauthorized\x0d\x0a'
+                                 b'Content-Length: 0\x0d\x0a'
+                                 b'WWW-Authenticate: Basic realm="camelot"\x0d\x0a'
+                                 b'\x0d\x0a')
+        raise AbortedByUserException('Abort the connection')
+
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/delayed-passive-close_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/delayed-passive-close_wsh.py
new file mode 100755
index 0000000..7d55b88
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/delayed-passive-close_wsh.py
@@ -0,0 +1,27 @@
+#!/usr/bin/python
+from mod_pywebsocket import common
+import time
+
+def web_socket_do_extra_handshake(request):
+    pass
+
+
+def web_socket_transfer_data(request):
+    # Wait for the close frame to arrive.
+    request.ws_stream.receive_message()
+
+
+def web_socket_passive_closing_handshake(request):
+    # Echo close status code and reason
+    code, reason = request.ws_close_code, request.ws_close_reason
+
+    # No status received is a reserved pseudo code representing an empty code,
+    # so echo back an empty code in this case.
+    if code == common.STATUS_NO_STATUS_RECEIVED:
+        code = None
+
+    # The browser may error the connection if the closing handshake takes too
+    # long, but hopefully no browser will have a timeout this short.
+    time.sleep(1)
+
+    return code, reason
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-cookie_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-cookie_wsh.py
new file mode 100755
index 0000000..367d031
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-cookie_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+    request.ws_cookie = request.headers_in.get('Cookie')
+
+def web_socket_transfer_data(request):
+    if request.ws_cookie is not None:
+        msgutil.send_message(request, request.ws_cookie)
+    else:
+        msgutil.send_message(request, '(none)')
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_v13_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_v13_wsh.py
new file mode 100755
index 0000000..4083c49
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_v13_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+    pass
+
+def web_socket_transfer_data(request):
+    while True:
+        msgutil.send_message(request, request.unparsed_uri.split('?')[1] or '')
+        return
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_wsh.py
new file mode 100755
index 0000000..8fd7ac3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo-query_wsh.py
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+    pass  # Always accept.
+
+def web_socket_transfer_data(request):
+    msgutil.send_message(request, request.unparsed_uri.split('?', 1)[1] or '')
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_close_data_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_close_data_wsh.py
new file mode 100755
index 0000000..e820568
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_close_data_wsh.py
@@ -0,0 +1,22 @@
+#!/usr/bin/python
+import six
+from mod_pywebsocket import msgutil
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+    # This example handler accepts any request. See origin_check_wsh.py for how
+    # to reject access from untrusted scripts based on origin value.
+
+    pass  # Always accept.
+
+
+def web_socket_transfer_data(request):
+    while True:
+        line = request.ws_stream.receive_message()
+        if line is None:
+            return
+        if isinstance(line, six.text_type):
+            if line == _GOODBYE_MESSAGE:
+                return
+                request.ws_stream.send_message(line, binary=False)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_exit_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_exit_wsh.py
new file mode 100755
index 0000000..4496918
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_exit_wsh.py
@@ -0,0 +1,21 @@
+#!/usr/bin/python
+import six
+from mod_pywebsocket import msgutil
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+    # This example handler accepts any request. See origin_check_wsh.py for how
+    # to reject access from untrusted scripts based on origin value.
+
+    pass  # Always accept.
+
+
+def web_socket_transfer_data(request):
+    while True:
+        line = request.ws_stream.receive_message()
+        if line is None:
+            return
+        if isinstance(line, six.text_type):
+            if line == _GOODBYE_MESSAGE:
+                return
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_raw_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_raw_wsh.py
new file mode 100755
index 0000000..e1fc266
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_raw_wsh.py
@@ -0,0 +1,16 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+    pass  # Always accept.
+
+def web_socket_transfer_data(request):
+    while True:
+        line = msgutil.receive_message(request)
+        if line == b'exit':
+            return
+
+        if line is not None:
+            request.connection.write(line)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_wsh.py
new file mode 100755
index 0000000..df1fdfa
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/echo_wsh.py
@@ -0,0 +1,37 @@
+#!/usr/bin/python
+import six
+from mod_pywebsocket import msgutil
+from mod_pywebsocket import common
+
+_GOODBYE_MESSAGE = u'Goodbye'
+
+def web_socket_do_extra_handshake(request):
+    # This example handler accepts any request. See origin_check_wsh.py for how
+    # to reject access from untrusted scripts based on origin value.
+    if request.ws_requested_protocols:
+        if "echo" in request.ws_requested_protocols:
+            request.ws_protocol = "echo"
+
+
+def web_socket_transfer_data(request):
+    while True:
+        line = request.ws_stream.receive_message()
+        if line is None:
+            return
+        if isinstance(line, six.text_type):
+            request.ws_stream.send_message(line, binary=False)
+            if line == _GOODBYE_MESSAGE:
+                return
+        else:
+            request.ws_stream.send_message(line, binary=True)
+
+def web_socket_passive_closing_handshake(request):
+    # Echo close status code and reason
+    code, reason = request.ws_close_code, request.ws_close_reason
+
+    # No status received is a reserved pseudo code representing an empty code,
+    # so echo back an empty code in this case.
+    if code == common.STATUS_NO_STATUS_RECEIVED:
+        code = None
+
+    return code, reason
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/empty-message_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/empty-message_wsh.py
new file mode 100755
index 0000000..0eb107f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/empty-message_wsh.py
@@ -0,0 +1,13 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+    pass  # Always accept.
+
+def web_socket_transfer_data(request):
+    line = msgutil.receive_message(request)
+    if line == "":
+        msgutil.send_message(request, 'pass')
+    else:
+        msgutil.send_message(request, 'fail')
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_extensions_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_extensions_wsh.py
new file mode 100755
index 0000000..0d0f0a8
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_extensions_wsh.py
@@ -0,0 +1,9 @@
+#!/usr/bin/python
+
+
+def web_socket_do_extra_handshake(request):
+    request.ws_extension_processors = []
+
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_protocol_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_protocol_wsh.py
new file mode 100755
index 0000000..ffc2ae8
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_no_protocol_wsh.py
@@ -0,0 +1,8 @@
+#!/usr/bin/python
+
+def web_socket_do_extra_handshake(request):
+    # Trick pywebsocket into believing no subprotocol was requested.
+    request.ws_requested_protocols = None
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_protocol_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_protocol_wsh.py
new file mode 100755
index 0000000..2ca20c0
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_protocol_wsh.py
@@ -0,0 +1,7 @@
+#!/usr/bin/python
+
+def web_socket_do_extra_handshake(request):
+    request.ws_protocol = 'foobar'
+
+def web_socket_transfer_data(request):
+    pass
\ No newline at end of file
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_sleep_2_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_sleep_2_wsh.py
new file mode 100755
index 0000000..3367ed8f
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/handshake_sleep_2_wsh.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+import time
+
+def web_socket_do_extra_handshake(request):
+    time.sleep(2)
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/invalid_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/invalid_wsh.py
new file mode 100755
index 0000000..10950474
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/invalid_wsh.py
@@ -0,0 +1,10 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+    request.connection.write(b"FOO BAR BAZ\r\n\r\n")
+
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/origin_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/origin_wsh.py
new file mode 100755
index 0000000..ce5f3a7
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/origin_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+
+def web_socket_do_extra_handshake(request):
+    pass # Always accept.
+
+
+def web_socket_transfer_data(request):
+    msgutil.send_message(request, request.ws_origin)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_array_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_array_wsh.py
new file mode 100755
index 0000000..5d46c58
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_array_wsh.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+    line = request.headers_in.get('Sec-WebSocket-Protocol')
+    request.ws_protocol = line.split(',', 1)[0]
+
+#pass
+
+def web_socket_transfer_data(request):
+    while True:
+        msgutil.send_message(request, request.ws_protocol)
+        return
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_wsh.py
new file mode 100755
index 0000000..96a4525
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/protocol_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil, util
+
+def web_socket_do_extra_handshake(request):
+    request.ws_protocol = request.headers_in.get('Sec-WebSocket-Protocol')
+#pass
+
+def web_socket_transfer_data(request):
+    while True:
+        msgutil.send_message(request, request.ws_protocol)
+        return
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/receive-backpressure_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/receive-backpressure_wsh.py
new file mode 100755
index 0000000..9c2e470
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/receive-backpressure_wsh.py
@@ -0,0 +1,14 @@
+#!/usr/bin/python
+
+import time
+
+
+def web_socket_do_extra_handshake(request):
+    # Turn off permessage-deflate, otherwise it shrinks our 8MB buffer to 8KB.
+    request.ws_extension_processors = []
+
+
+def web_socket_transfer_data(request):
+    # Wait two seconds to cause backpressure.
+    time.sleep(2);
+    request.ws_stream.receive_message()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/referrer_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/referrer_wsh.py
new file mode 100755
index 0000000..3418ceb0
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/referrer_wsh.py
@@ -0,0 +1,12 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import msgutil
+
+def web_socket_do_extra_handshake(request):
+    pass
+
+def web_socket_transfer_data(request):
+    referrer = request.headers_in.get("Referer")
+    if referrer is None:
+        referrer = "MISSING AS PER FETCH"
+    msgutil.send_message(request, referrer)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/send-backpressure_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/send-backpressure_wsh.py
new file mode 100755
index 0000000..40905c3
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/send-backpressure_wsh.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+
+import six
+import time
+
+# The amount of internal buffering a WebSocket connection has is not
+# standardised, and varies depending upon the OS. Setting this number too small
+# will result in false negatives, as the entire message gets buffered. Setting
+# this number too large will result in false positives, when it takes more than
+# 2 seconds to transmit the message anyway. This number was arrived at by
+# trial-and-error.
+MESSAGE_SIZE = 16 * 1024 * 1024
+
+
+def web_socket_do_extra_handshake(request):
+    # Turn off permessage-deflate, otherwise it shrinks our big message to a
+    # tiny message.
+    request.ws_extension_processors = []
+
+
+def web_socket_transfer_data(request):
+    # Send empty message to fill the ReadableStream queue
+    request.ws_stream.send_message(b'', binary=True)
+
+    # TODO(ricea@chromium.org): Use time.perf_counter() when migration to python
+    # 3 is complete. time.time() can go backwards.
+    start_time = time.time()
+
+    # The large message that will be blocked by backpressure.
+    request.ws_stream.send_message(b' ' * MESSAGE_SIZE, binary=True)
+
+    # Report the time taken to send the large message.
+    request.ws_stream.send_message(six.text_type(time.time() - start_time), binary=False)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie-secure_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie-secure_wsh.py
new file mode 100755
index 0000000..4db321fc9
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie-secure_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+from six.moves import urllib
+
+
+def web_socket_do_extra_handshake(request):
+    url_parts = urllib.parse.urlsplit(request.uri)
+    request.extra_headers.append(('Set-Cookie', 'ws_test_'+(url_parts.query or '')+'=test; Secure; Path=/'))
+
+def web_socket_transfer_data(request):
+    # Expect close() from user agent.
+    request.ws_stream.receive_message()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_http_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_http_wsh.py
new file mode 100755
index 0000000..2fa0ded6
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_http_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+
+from six.moves import urllib
+
+def web_socket_do_extra_handshake(request):
+    url_parts = urllib.parse.urlsplit(request.uri)
+    request.extra_headers.append(('Set-Cookie', 'ws_test_'+(url_parts.query or '')+'=test; Path=/; HttpOnly\x0D\x0ASec-WebSocket-Origin: '+request.ws_origin))
+
+def web_socket_transfer_data(request):
+    # Expect close from user agent.
+    request.ws_stream.receive_message()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_wsh.py
new file mode 100755
index 0000000..3cec1c04
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookie_wsh.py
@@ -0,0 +1,11 @@
+#!/usr/bin/python
+from six.moves import urllib
+
+
+def web_socket_do_extra_handshake(request):
+    url_parts = urllib.parse.urlsplit(request.uri)
+    request.extra_headers.append(('Set-Cookie', 'ws_test_'+(url_parts.query or '')+'=test; Path=/'))
+
+def web_socket_transfer_data(request):
+    # Expect close from user agent.
+    request.ws_stream.receive_message()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookies-samesite_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookies-samesite_wsh.py
new file mode 100644
index 0000000..6f4a1b4
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/set-cookies-samesite_wsh.py
@@ -0,0 +1,25 @@
+from six.moves import urllib
+
+
+def web_socket_do_extra_handshake(request):
+    url_parts = urllib.parse.urlsplit(request.uri)
+    max_age = ""
+    if "clear" in url_parts.query:
+        max_age = "; Max-Age=0"
+    value = "1"
+    if "value" in url_parts.query:
+        value = urllib.parse.parse_qs(url_parts.query)["value"][0]
+    cookies = [
+        "samesite-unspecified={}; Path=/".format(value) + max_age,
+        "samesite-lax={}; Path=/; SameSite=Lax".format(value) + max_age,
+        "samesite-strict={}; Path=/; SameSite=Strict".format(value) + max_age,
+        # SameSite=None cookies must be Secure.
+        "samesite-none={}; Path=/; SameSite=None; Secure".format(value) + max_age
+    ]
+    for cookie in cookies:
+        request.extra_headers.append(("Set-Cookie", cookie))
+
+
+def web_socket_transfer_data(request):
+    # Expect close() from user agent.
+    request.ws_stream.receive_message()
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/simple_handshake_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/simple_handshake_wsh.py
new file mode 100755
index 0000000..ad466877
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/simple_handshake_wsh.py
@@ -0,0 +1,35 @@
+#!/usr/bin/python
+
+from mod_pywebsocket import common, stream
+from mod_pywebsocket.handshake import AbortedByUserException, hybi
+
+
+def web_socket_do_extra_handshake(request):
+    # Send simple response header. This test implements the handshake manually,
+    # so that we can send the header in the same packet as the close frame.
+    msg = (b'HTTP/1.1 101 Switching Protocols:\x0D\x0A'
+           b'Connection: Upgrade\x0D\x0A'
+           b'Upgrade: WebSocket\x0D\x0A'
+           b'Set-Cookie: ws_test=test\x0D\x0A'
+           b'Sec-WebSocket-Origin: %s\x0D\x0A'
+           b'Sec-WebSocket-Accept: %s\x0D\x0A\x0D\x0A') % (request.ws_origin.encode(
+               'UTF-8'), hybi.compute_accept_from_unicode(request.headers_in.get(common.SEC_WEBSOCKET_KEY_HEADER)))
+    # Create a clean close frame.
+    close_body = stream.create_closing_handshake_body(1001, 'PASS')
+    close_frame = stream.create_close_frame(close_body)
+    # Concatenate the header and the close frame and write them to the socket.
+    request.connection.write(msg + close_frame)
+    # Wait for the responding close frame from the user agent. It's not possible
+    # to use the stream methods at this point because the stream hasn't been
+    # established from pywebsocket's point of view. Instead just read the
+    # correct number of bytes.
+    # Warning: reading the wrong number of bytes here will make the test
+    # flaky.
+    MASK_LENGTH = 4
+    request.connection.read(len(close_frame) + MASK_LENGTH)
+    # Close the socket without pywebsocket sending its own handshake response.
+    raise AbortedByUserException('Abort the connection')
+
+
+def web_socket_transfer_data(request):
+    pass
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/sleep_10_v13_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/sleep_10_v13_wsh.py
new file mode 100755
index 0000000..f0819101
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/sleep_10_v13_wsh.py
@@ -0,0 +1,24 @@
+#!/usr/bin/python
+
+import sys, urllib, time
+from mod_pywebsocket import common, msgutil, util
+
+def web_socket_do_extra_handshake(request):
+    request.connection.write(b'x')
+    time.sleep(2)
+    request.connection.write(b'x')
+    time.sleep(2)
+    request.connection.write(b'x')
+    time.sleep(2)
+    request.connection.write(b'x')
+    time.sleep(2)
+    request.connection.write(b'x')
+    time.sleep(2)
+    return
+
+def web_socket_transfer_data(request):
+    while True:
+        line = msgutil.receive_message(request)
+        if line == 'Goodbye':
+            return
+        request.ws_stream.send_message(line, binary=False)
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_blocking_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_blocking_wsh.py
new file mode 100755
index 0000000..10ecdfe
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_blocking_wsh.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python
+import json
+import threading
+import wptserve.stash
+from mod_pywebsocket import msgutil
+
+address, authkey = wptserve.stash.load_env_config()
+path = "/stash_responder_blocking"
+stash = wptserve.stash.Stash(path, address=address, authkey=authkey)
+cv = threading.Condition()
+
+def handle_set(key, value):
+    with cv:
+      stash.put(key, value)
+      cv.notify_all()
+
+def handle_get(key):
+    with cv:
+        while True:
+            value = stash.take(key)
+            if value is not None:
+                return value
+            cv.wait()
+
+def web_socket_do_extra_handshake(request):
+    pass
+
+def web_socket_transfer_data(request):
+    line = request.ws_stream.receive_message()
+
+    query = json.loads(line)
+    action = query["action"]
+    key = query["key"]
+
+    if action == "set":
+        value = query["value"]
+        handle_set(key, value)
+        response = {}
+    elif action == "get":
+        value = handle_get(key)
+        response = {"value": value}
+    else:
+        response = {}
+
+    msgutil.send_message(request, json.dumps(response))
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_wsh.py
new file mode 100755
index 0000000..fd6eabc
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/stash_responder_wsh.py
@@ -0,0 +1,46 @@
+#!/usr/bin/python
+from six.moves import urllib
+import json
+from mod_pywebsocket import common, msgutil, util
+from mod_pywebsocket.handshake import hybi
+from wptserve import stash
+
+address, authkey = stash.load_env_config()
+stash = stash.Stash("/stash_responder", address=address, authkey=authkey)
+
+def web_socket_do_extra_handshake(request):
+    return
+
+def web_socket_transfer_data(request):
+    while True:
+        line = request.ws_stream.receive_message()
+        if line == "echo":
+            query = request.unparsed_uri.split('?')[1]
+            GET = dict(urllib.parse.parse_qsl(query))
+
+            # TODO(kristijanburnik): This code should be reused from
+            # /mixed-content/generic/expect.py or implemented more generally
+            # for other tests.
+            path = GET.get("path", request.unparsed_uri.split('?')[0])
+            key = GET["key"]
+            action = GET["action"]
+
+            if action == "put":
+              value = GET["value"]
+              stash.take(key=key, path=path)
+              stash.put(key=key, value=value, path=path)
+              response_data = json.dumps({"status": "success", "result": key})
+            elif action == "purge":
+             value = stash.take(key=key, path=path)
+             response_data = json.dumps({"status": "success", "result": value})
+            elif action == "take":
+              value = stash.take(key=key, path=path)
+              if value is None:
+                  status = "allowed"
+              else:
+                  status = "blocked"
+              response_data = json.dumps({"status": status, "result": value})
+
+            msgutil.send_message(request, response_data)
+
+            return
diff --git a/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/wrong_accept_key_wsh.py b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/wrong_accept_key_wsh.py
new file mode 100755
index 0000000..77f703ab
--- /dev/null
+++ b/third_party/blink/tools/blinkpy/third_party/wpt/wpt/websockets/handlers/wrong_accept_key_wsh.py
@@ -0,0 +1,20 @@
+#!/usr/bin/python
+
+import sys, urllib, time
+from mod_pywebsocket import common, msgutil, util
+
+
+def web_socket_do_extra_handshake(request):
+    msg = (b'HTTP/1.1 101 Switching Protocols:\x0D\x0A'
+           b'Connection: Upgrade\x0D\x0A'
+           b'Upgrade: WebSocket\x0D\x0A'
+           b'Sec-WebSocket-Origin: %s\x0D\x0A'
+           b'Sec-WebSocket-Accept: thisisawrongacceptkey\x0D\x0A\x0D\x0A') % request.ws_origin.encode('UTF-8')
+    request.connection.write(msg)
+    return
+
+
+def web_socket_transfer_data(request):
+    while True:
+        request.ws_stream.send_message('test', binary=False)
+        return
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations
index c1704ae9..ef93def 100644
--- a/third_party/blink/web_tests/TestExpectations
+++ b/third_party/blink/web_tests/TestExpectations
@@ -71,6 +71,7 @@
 crbug.com/1132260 http/tests/devtools/console/console-uncaught-promise.js [ Pass Failure ]
 crbug.com/1132260 http/tests/devtools/tracing/timeline-network/timeline-network-resource-details.js [ Pass Failure ]
 crbug.com/1132260 inspector-protocol/page/frameAttachedStacktrace.js [ Pass Failure ]
+crbug.com/1164469 inspector-protocol/performance-timeline/largest-contentful-paint.js [ Pass Failure ]
 
 # With --enable-display-compositor-pixel-dump enabled by default, these three
 # tests fail. See crbug.com/887140 for more info.
@@ -2471,6 +2472,8 @@
 crbug.com/958381 [ Mac ] external/wpt/css/CSS2/tables/table-anonymous-objects-206.xht [ Failure ]
 
 # ====== New tests from wpt-importer added here ======
+crbug.com/626703 external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html [ Failure ]
+crbug.com/626703 virtual/threaded/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html [ Failure ]
 crbug.com/626703 [ Mac10.13 ] external/wpt/x-frame-options/multiple.html [ Timeout ]
 crbug.com/626703 [ Mac10.13 ] external/wpt/FileAPI/idlharness.worker.html [ Timeout ]
 crbug.com/626703 external/wpt/html/interaction/focus/document-level-focus-apis/document-has-system-focus.html [ Timeout ]
@@ -5656,13 +5659,6 @@
 # Mixed content autoupgrades cause test to fail because test relied on http subresources to test a different origin, needs to be changed to not rely on HTTP URLs.
 crbug.com/1042877 http/tests/security/img-crossorigin-redirect-credentials.https.html [ Failure ]
 
-# Temporarily disable tests to land DevTools frontend changes
-crbug.com/1152082 http/tests/devtools/bindings/blackboxed-sourcemap-detach.js [ Pass Failure Timeout ]
-crbug.com/1152082 http/tests/devtools/console/console-linkify-message-location.js [ Pass Failure Timeout ]
-crbug.com/1152082 http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code.js [ Pass Failure Timeout ]
-crbug.com/1152082 http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns.js [ Pass Failure Timeout ]
-crbug.com/1152082 http/tests/devtools/tracing/timeline-js/timeline-js-ignore-list.js [ Pass Failure Timeout ]
-
 # Sheriff 2020-10-09
 crbug.com/1136687 external/wpt/pointerevents/pointerlock/pointerevent_pointerlock_supercedes_capture.html [ Pass Failure ]
 crbug.com/1136726 [ Linux ] virtual/gpu-rasterization/images/imagemap-focus-ring-outline-color-not-inherited-from-map.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
index 8165cfb..91dd579 100644
--- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
+++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_8.json
@@ -98156,7 +98156,7 @@
      ],
      "snap-after-initial-layout": {
       "direction-rtl.html": [
-       "d10c013e1ee0d713057c26bd7acd961b4c0a5edc",
+       "85724c31feae72e26fd90b03d54f314311cd0137",
        [
         null,
         [
@@ -98168,8 +98168,21 @@
         {}
        ]
       ],
+      "scroll-snap-initial-layout-000.html": [
+       "ea47c9f36cc1f9bfda413dd6b6c9eb697bd54540",
+       [
+        null,
+        [
+         [
+          "/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000-ref.html",
+          "=="
+         ]
+        ],
+        {}
+       ]
+      ],
       "writing-mode-horizontal-tb.html": [
-       "aa65dde1810ebabfccfa76716063bd8e83c07bb0",
+       "9a680d10d9ff61fc7173118bbfac4fae5b08ff97",
        [
         null,
         [
@@ -98182,7 +98195,7 @@
        ]
       ],
       "writing-mode-vertical-lr.html": [
-       "898e64be6197679635290aebd22467c96a509750",
+       "f4de0411e053f0bb9505209e3ff6b4d9196961ab",
        [
         null,
         [
@@ -98195,7 +98208,7 @@
        ]
       ],
       "writing-mode-vertical-rl.html": [
-       "b3141f03f3c4b9a0a0108df8b55356e6fde3a759",
+       "1710bc16ddf6a95ff66e3305e1b591a130855a81",
        [
         null,
         [
@@ -200458,6 +200471,10 @@
       []
      ],
      "snap-after-initial-layout": {
+      "scroll-snap-initial-layout-000-ref.html": [
+       "f3eaa06ac9b7c48479d439041ce51575ad8cc072",
+       []
+      ],
       "snap-after-initial-layout-ref.html": [
        "c8009b626cb63ebcef4a211f8b61249faf36c72f",
        []
@@ -237462,7 +237479,7 @@
     ]
    },
    "lint.ignore": [
-    "65d307e410bc25f1e9b64d5f16ce71e8a09fbe3a",
+    "2e0fc8b39bc8df1a44d7b5469d81014c32fa844b",
     []
    ],
    "loading": {
@@ -239083,7 +239100,7 @@
      []
     ],
     "idlharness.window-expected.txt": [
-     "531f344a2160405685cee9e61ccdce57bad85cfb",
+     "e559211d7f7a1c66b190532b67dd112ef14513cb",
      []
     ],
     "passthrough": {
@@ -256837,7 +256854,7 @@
        []
       ],
       "handlers.py": [
-       "c748ca2e3b157fda3350e93b6c089bccf3f912b5",
+       "0fc11c190d111158ef3bf169cfd6dce02b2c6f4c",
        []
       ],
       "logger.py": [
@@ -258445,6 +258462,10 @@
      []
     ],
     "resources": {
+     "cross-origin.har": [
+      "7435393b13b1f640b0a1911e05456833febf7e8e",
+      []
+     ],
      "dynamic1": {
       "classic_script.js": [
        "5fcf045906c1ab151512a3e425b7c5c6f79cee59",
@@ -258490,7 +258511,7 @@
       ]
      },
      "generate-test-wbns.sh": [
-      "3c8a3ea68d60522452be94a7f8d0aaf9b11f5c55",
+      "8c8fd45d8172c7575fe17a30dfb308dd4fa4e2e0",
       []
      ],
      "location": {
@@ -258562,6 +258583,16 @@
        "21e57b9caca1183ecda6f5d4fb9ebd556abf769a",
        []
       ],
+      "cors": {
+       "__dir__.headers": [
+        "383abc543c68b31038d4b708b8465b2bae1ceac6",
+        []
+       ],
+       "cross-origin.wbn": [
+        "bed9bf2af7439c2637a61935c87324d0cd05f9ca",
+        []
+       ]
+      },
       "dynamic": {
        "__dir__.headers": [
         "cb762eff806849df46dc758ef7b98b63f27f54c9",
@@ -434504,6 +434535,13 @@
        {}
       ]
      ],
+     "subresource-loading-cross-origin.tentative.html": [
+      "3991aef2c40ccfa6c82eee09e76e9b42e16c8cf5",
+      [
+       null,
+       {}
+      ]
+     ],
      "subresource-loading-from-web-bundle.tentative.html": [
       "53a9c1b2cc707271c8d7b0e7fb7385fd59839744",
       [
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html
index d10c013e..85724c3 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/direction-rtl.html
@@ -19,10 +19,12 @@
 }
 
 #close-target {
-  width: 300px;
-  height: 300px;
-  top: 100px;
-  right: 200px;
+  width: 200px;
+  height: 200px;
+  border: solid green 50px;
+  top: 50px;
+  right: 150px;
+  margin: 50px;
   background-color: green;
   scroll-snap-align: start;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000-ref.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000-ref.html
new file mode 100644
index 0000000..f3eaa06
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000-ref.html
@@ -0,0 +1,81 @@
+<!DOCTYPE html>
+<title>
+  CSS Scroll Snap Reference
+</title>
+<style>
+
+.scroller {
+  width: 100px;
+  height: 100px;
+  border: solid blue;
+  margin: 10px;
+  display: inline-block;
+}
+
+.scroller > div {
+  width: 30px;
+  height: 30px;
+  background: orange;
+}
+
+.proxfar {
+  border-color: orange;
+}
+
+</style>
+
+<p>Test passes if there is an orange square precisely at the top left corner of each blue box (no gap),
+and each orange box is empty.
+
+
+<div class="mandatory">
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <!-- on-screen -->
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+</div>
+
+<div class="proximity">
+  <!-- off-screen -->
+  <div class="scroller proxfar">
+  </div>
+
+  <div class="scroller proxfar">
+  </div>
+
+  <div class="scroller proxfar">
+  </div>
+
+  <!-- on-screen -->
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+
+  <div class="scroller">
+    <div></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html
new file mode 100644
index 0000000..ea47c9f
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/scroll-snap-initial-layout-000.html
@@ -0,0 +1,113 @@
+<!DOCTYPE html>
+<title>
+  On-screen vs. Off-screen Snapped Initial Scroll Position (Mandatory and Proximity)
+</title>
+<link rel="help" href="https://drafts.csswg.org/css-scroll-snap-1/#scroll-snap-align">
+<link rel="help" href="https://drafts.csswg.org/css-scroll-snap/#re-snap">
+<link rel="author" title="Elika J. Etemad" href="http://fantasai.inkedblade.net/contact">
+<!-- Test assumes 2px proximity is enough to snap.
+     If your implementation has a cogent argument as to why this is too much,
+     please request a change to this test. ~fantasai -->
+<link rel="match" href="scroll-snap-initial-layout-000-ref.html">
+
+<style>
+
+.scroller {
+  scroll-snap-type: both mandatory;
+  overflow: hidden;
+  scroll-padding: 0;
+  width: 100px;
+  height: 100px;
+  border: solid blue;
+  margin: 10px;
+  display: inline-block;
+}
+
+.mandatory > .scroller {
+  scroll-snap-type: both mandatory;
+}
+
+.proximity > .scroller {
+  scroll-snap-type: both proximity;
+}
+
+.scroller > div {
+  /* padding wrapper */
+  width: 30px;
+}
+
+.scroller > div > div {
+  /* target box */
+  height: 30px;
+  background: orange;
+  scroll-snap-align: start;
+}
+
+.proxfar {
+  border-color: orange;
+}
+.proxfar > div > div {
+  background: red;
+}
+
+</style>
+
+<p>Test passes if there is an orange square precisely at the top left corner of each blue box (no gap),
+and each orange box is empty.
+
+
+<div class="mandatory">
+  <!-- off-screen -->
+  <div class="scroller">
+    <div style="padding: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding-block: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding-inline: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <!-- on-screen -->
+  <div class="scroller">
+    <div style="padding: 90px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding-block: 90px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding-inline: 90px;"><div class="small-target"></div></div>
+  </div>
+</div>
+
+<div class="proximity">
+  <!-- off-screen -->
+  <div class="scroller proxfar">
+    <div style="padding: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller proxfar">
+    <div style="padding-block: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller proxfar">
+    <div style="padding-inline: 110px;"><div class="small-target"></div></div>
+  </div>
+
+  <!-- on-screen -->
+  <div class="scroller">
+    <div style="padding: 2px 110px 110px 2px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding: 2px 110px 110px 2px;"><div class="small-target"></div></div>
+  </div>
+
+  <div class="scroller">
+    <div style="padding: 2px 110px 110px 2px;"><div class="small-target"></div></div>
+  </div>
+</div>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-horizontal-tb.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-horizontal-tb.html
index aa65dde1..9a680d1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-horizontal-tb.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-horizontal-tb.html
@@ -20,10 +20,12 @@
 }
 
 #close-target {
-  width: 300px;
-  height: 300px;
-  top: 100px;
-  left: 200px;
+  width: 200px;
+  height: 200px;
+  border: solid green 50px;
+  top: 50px;
+  left: 150px;
+  margin: 50px;
   background-color: green;
   scroll-snap-align: start end;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-lr.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-lr.html
index 898e64b..f4de0411 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-lr.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-lr.html
@@ -20,10 +20,12 @@
 }
 
 #close-target {
-  width: 300px;
-  height: 300px;
-  top: 100px;
-  left: 200px;
+  width: 200px;
+  height: 200px;
+  border: solid green 50px;
+  top: 50px;
+  left: 150px;
+  margin: 50px;
   background-color: green;
   scroll-snap-align: end start;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-rl.html b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-rl.html
index b3141f0..1710bc1 100644
--- a/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-rl.html
+++ b/third_party/blink/web_tests/external/wpt/css/css-scroll-snap/snap-after-initial-layout/writing-mode-vertical-rl.html
@@ -23,10 +23,12 @@
 }
 
 #close-target {
-  width: 300px;
-  height: 300px;
-  top: 100px;
-  left: 200px;
+  width: 200px;
+  height: 200px;
+  border: solid green 50px;
+  top: 50px;
+  left: 150px;
+  margin: 50px;
   background-color: green;
   scroll-snap-align: start;
 }
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html
new file mode 100644
index 0000000..3b8a31c
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior-ref.html
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>backdrop-filter: Edge behavior</title>
+<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
+
+
+
+
+<div>
+  <p>Expected: The black box inside the red box should not contain any red.</p>
+</div>
+
+<div id=backdrop></div>
+<div id=scroller></div>
+
+<style>
+  #scroller {
+    position: relative;
+    top:-202px;
+    width: 250px;
+    height: 250px;
+    border: 6px solid red;
+  }
+  #backdrop {
+    position: relative;
+    height: 200px;
+    width: 200px;
+    left: 6px;
+    top: 3px;
+    border: 1px solid black;
+  }
+</style>
diff --git a/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html
new file mode 100644
index 0000000..9c279c8
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/css/filter-effects/backdrop-filter-edge-behavior.html
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<meta charset="utf-8">
+<title>backdrop-filter: Edge behavior</title>
+<link rel="author" title="Mason Freed" href="mailto:masonfreed@chromium.org">
+<link rel="help" href="https://drafts.fxtf.org/filter-effects-2/#BackdropFilterProperty">
+<link rel="help" href="https://crbug.com/1165868">
+<link rel="match"  href="backdrop-filter-edge-behavior-ref.html">
+
+<div>
+  <p>Expected: The black box inside the red box should not contain any red.</p>
+</div>
+
+<div id=scroller>
+  <div class=filler></div>
+  <div id=backdrop></div>
+  <div class=filler></div>
+</div>
+
+<style>
+  #scroller {
+    width: 250px;
+    height: 250px;
+    overflow: scroll;
+    border: 6px solid red;
+  }
+  #scroller::-webkit-scrollbar {
+    width: 0px;
+  }
+  #backdrop {
+    height: 200px;
+    width: 200px;
+    backdrop-filter: blur(10px);
+    border: 1px solid black;
+  }
+  .filler {
+    position: relative;
+    left: 50px;
+    width: 100px;
+    height: 100px;
+  }
+</style>
+
+<script>
+  scroller.scrollTop = 103;
+</script>
\ No newline at end of file
diff --git a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
index c748ca2..0fc11c19 100644
--- a/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
+++ b/third_party/blink/web_tests/external/wpt/tools/wptserve/wptserve/handlers.py
@@ -98,7 +98,9 @@
                    {"link": link, "name": ".."})
         items = []
         prev_item = None
-        for item in sorted(os.listdir(path)):
+        # This ensures that .headers always sorts after the file it provides the headers for. E.g.,
+        # if we have x, x-y, and x.headers, the order will be x, x.headers, and then x-y.
+        for item in sorted(os.listdir(path), key=lambda x: (x[:-len(".headers")], x) if x.endswith(".headers") else (x, x)):
             if prev_item and prev_item + ".headers" == item:
                 items[-1][1] = item
                 prev_item = None
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh b/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh
index 8c8fd45..6683cb0 100755
--- a/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/generate-test-wbns.sh
@@ -74,5 +74,5 @@
 gen-bundle \
   -version b1 \
   -har cross-origin.har \
-  -primaryURL $wpt_test_https_origin/web-bundle/resources/wbn/cors/resource.json \
+  -primaryURL $wpt_test_https_origin/web-bundle/resources/wbn/cors/resource.cors.json \
   -o wbn/cors/cross-origin.wbn
diff --git a/third_party/blink/web_tests/external/wpt/web-bundle/resources/nested/resource.js b/third_party/blink/web_tests/external/wpt/web-bundle/resources/nested/resource.js
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/third_party/blink/web_tests/external/wpt/web-bundle/resources/nested/resource.js
diff --git a/third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach-expected.txt b/third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach-expected.txt
deleted file mode 100644
index fe25e41..0000000
--- a/third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach-expected.txt
+++ /dev/null
@@ -1,6 +0,0 @@
-Tests that blackboxed sourcemaps properly detach on reload crbug.com/888688
-Evaluating script with source map
-Message count: 1
-Page reloaded.
-After reload, Console message count: 0
-
diff --git a/third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach-expected.txt b/third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach-expected.txt
new file mode 100644
index 0000000..91fbbee
--- /dev/null
+++ b/third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach-expected.txt
@@ -0,0 +1,6 @@
+Tests that ignore-listed sourcemaps properly detach on reload crbug.com/888688
+Evaluating script with source map
+Message count: 1
+Page reloaded.
+After reload, Console message count: 0
+
diff --git a/third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach.js b/third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach.js
similarity index 85%
rename from third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach.js
rename to third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach.js
index 3df56f8b..5c43602a 100644
--- a/third_party/blink/web_tests/http/tests/devtools/bindings/blackboxed-sourcemap-detach.js
+++ b/third_party/blink/web_tests/http/tests/devtools/bindings/ignore-listed-sourcemap-detach.js
@@ -4,12 +4,12 @@
 
 (async function() {
   await TestRunner.loadModule('console_test_runner');
-  TestRunner.addResult(`Tests that blackboxed sourcemaps properly detach on reload crbug.com/888688`);
+  TestRunner.addResult(`Tests that ignore-listed sourcemaps properly detach on reload crbug.com/888688`);
   var content =
     `console.log(1);
 //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXZhbC1pbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbImV2YWwtaW4iXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImNvbnNvbGUubG9nKDEpOyJdfQ==`;
 
-  TestRunner.addSniffer(Bindings.BlackboxManager.prototype, '_patternChangeFinishedForTests', step1);
+  TestRunner.addSniffer(Bindings.IgnoreListManager.prototype, '_patternChangeFinishedForTests', step1);
   var frameworkRegexString = '.*';
   Common.settingForTest('skipStackFramesPattern').set('.*');
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/components/viewport-datagrid.js b/third_party/blink/web_tests/http/tests/devtools/components/viewport-datagrid.js
index c161ae3..b7daf25d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/components/viewport-datagrid.js
+++ b/third_party/blink/web_tests/http/tests/devtools/components/viewport-datagrid.js
@@ -165,7 +165,7 @@
   var children = root.children.slice();
   root.removeChildren();
   // Assure wheelTarget is anything but null, otherwise it happily bypasses crashing code.
-  dataGrid._wheelTarget = children.peekLast().element;
+  dataGrid._wheelTarget = children[children.length - 1].element;
   for (var i = 0; i < 40; ++i) {
     children[i].refresh();
     root.appendChild(children[i]);
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location-expected.txt b/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location-expected.txt
index da29245..b71b29d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location-expected.txt
@@ -1,4 +1,4 @@
-Test that console.log() would linkify its location in respect with blackboxing.
+Test that console.log() would linkify its location in respect with ignore-listing.
 
 foo.js:13 
 boo.js:20 
diff --git a/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location.js b/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location.js
index 1c650b9..6d4283a3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location.js
+++ b/third_party/blink/web_tests/http/tests/devtools/console/console-linkify-message-location.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 (async function() {
-  TestRunner.addResult(`Test that console.log() would linkify its location in respect with blackboxing.\n`);
+  TestRunner.addResult(`Test that console.log() would linkify its location in respect with ignore-listing.\n`);
 
   await TestRunner.loadModule('console_test_runner');
   await TestRunner.showPanel('console');
@@ -27,21 +27,21 @@
   async function step1() {
     await dumpConsoleMessageURLs();
 
-    TestRunner.addSniffer(Bindings.BlackboxManager.prototype, '_patternChangeFinishedForTests', step2);
+    TestRunner.addSniffer(Bindings.IgnoreListManager.prototype, '_patternChangeFinishedForTests', step2);
     var frameworkRegexString = 'foo\\.js';
     Common.settingForTest('skipStackFramesPattern').set(frameworkRegexString);
   }
 
   async function step2() {
     await dumpConsoleMessageURLs();
-    TestRunner.addSniffer(Bindings.BlackboxManager.prototype, '_patternChangeFinishedForTests', step3);
+    TestRunner.addSniffer(Bindings.IgnoreListManager.prototype, '_patternChangeFinishedForTests', step3);
     var frameworkRegexString = 'foo\\.js|boo\\.js';
     Common.settingForTest('skipStackFramesPattern').set(frameworkRegexString);
   }
 
   async function step3() {
     await dumpConsoleMessageURLs();
-    TestRunner.addSniffer(Bindings.BlackboxManager.prototype, '_patternChangeFinishedForTests', step4);
+    TestRunner.addSniffer(Bindings.IgnoreListManager.prototype, '_patternChangeFinishedForTests', step4);
     var frameworkRegexString = '';
     Common.settingForTest('skipStackFramesPattern').set(frameworkRegexString);
   }
diff --git a/third_party/blink/web_tests/http/tests/devtools/extensions/extensions-timeline-api.js b/third_party/blink/web_tests/http/tests/devtools/extensions/extensions-timeline-api.js
index 493ddfe..af93ae3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/extensions/extensions-timeline-api.js
+++ b/third_party/blink/web_tests/http/tests/devtools/extensions/extensions-timeline-api.js
@@ -8,7 +8,8 @@
   await TestRunner.showPanel('timeline');
 
   TestRunner.enableTimelineExtensionAndStart = function(callback) {
-    const provider = Extensions.extensionServer.traceProviders().peekLast();
+    const traceProviders = Extensions.extensionServer.traceProviders();
+    const provider = traceProviders[traceProviders.length - 1];
     const timelinePanel = UI.panels.timeline;
     const setting = Timeline.TimelinePanel._settingForTraceProvider(provider);
     setting.set(true);
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/parse-form-data.js b/third_party/blink/web_tests/http/tests/devtools/network/parse-form-data.js
index a0c87ec6..736483d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/network/parse-form-data.js
+++ b/third_party/blink/web_tests/http/tests/devtools/network/parse-form-data.js
@@ -23,7 +23,8 @@
     TestRunner.evaluateInPage('document.querySelector("form").submit();');
     await snifferPromise;
 
-    var request = NetworkTestRunner.networkRequests().peekLast();
+    const networkRequests = NetworkTestRunner.networkRequests();
+    var request = networkRequests[networkRequests.length - 1];
     if (request.url().endsWith('/')) {
       await TestRunner.addSnifferPromise(SDK.NetworkDispatcher.prototype, 'requestWillBeSent');
       request = NetworkTestRunner.networkRequests().pop();
diff --git a/third_party/blink/web_tests/http/tests/devtools/network/ping.js b/third_party/blink/web_tests/http/tests/devtools/network/ping.js
index d693ba8e7..3ba5c8b3 100644
--- a/third_party/blink/web_tests/http/tests/devtools/network/ping.js
+++ b/third_party/blink/web_tests/http/tests/devtools/network/ping.js
@@ -22,7 +22,8 @@
   TestRunner.evaluateInPage('navigateLink()');
   await snifferPromise;
 
-  var request = NetworkTestRunner.networkRequests().peekLast();
+  const networkRequests = NetworkTestRunner.networkRequests();
+  var request = networkRequests[networkRequests.length - 1];
   if (request.url().endsWith('/')) {
     await TestRunner.addSnifferPromise(SDK.NetworkDispatcher.prototype, 'requestWillBeSent');
     request = NetworkTestRunner.networkRequests().pop();
diff --git a/third_party/blink/web_tests/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js b/third_party/blink/web_tests/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js
index a8fc8eca..ae9061a24 100644
--- a/third_party/blink/web_tests/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js
+++ b/third_party/blink/web_tests/http/tests/devtools/oopif/oopif-performance-cpu-profiles.js
@@ -12,7 +12,11 @@
   await TestRunner.navigatePromise('resources/page.html');
   await PerformanceTestRunner.stopTimeline();
 
-  for (const track of PerformanceTestRunner.timelineModel().tracks().sort((a, b) => a.url.compareTo(b.url))) {
+  const sortedTracks = PerformanceTestRunner.timelineModel().tracks().sort((a, b) => {
+    return a.url > b.url ? 1 : b.url > a.url ? -1 : 0;
+  })
+
+  for (const track of sortedTracks) {
     if (track.type !== TimelineModel.TimelineModel.TrackType.MainThread)
       continue;
     TestRunner.addResult(`name: ${track.name}`);
diff --git a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-merge-editor-tabs.js b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-merge-editor-tabs.js
index 78a7a07..630c7fb5 100644
--- a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-merge-editor-tabs.js
+++ b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-merge-editor-tabs.js
@@ -79,7 +79,7 @@
   function dumpEditorTabs() {
     var editorContainer = UI.panels.sources._sourcesView._editorContainer;
     var openedUISourceCodes = [...editorContainer._tabIds.keys()];
-    openedUISourceCodes.sort((a, b) => a.url().compareTo(b.url()));
+    openedUISourceCodes.sort((a, b) => a.url() > b.url() ? 1 : b.url() > a.url() ? -1 : 0);
     TestRunner.addResult('Opened tabs: ');
     for (const code of openedUISourceCodes)
       TestRunner.addResult('    ' + code.url());
diff --git a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-switch-editor-tab.js b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-switch-editor-tab.js
index 9d016ce..80c5072 100644
--- a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-switch-editor-tab.js
+++ b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-switch-editor-tab.js
@@ -41,7 +41,7 @@
   function dumpEditorTabs() {
     var editorContainer = UI.panels.sources._sourcesView._editorContainer;
     var openedUISourceCodes = [...editorContainer._tabIds.keys()];
-    openedUISourceCodes.sort((a, b) => a.url().compareTo(b.url()));
+    openedUISourceCodes.sort((a, b) => a.url > b.url ? 1 : b.url > a.url ? -1 : 0);
     TestRunner.addResult('Opened tabs: ');
     for (const code of openedUISourceCodes)
       TestRunner.addResult('    ' + code.url());
diff --git a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-tabbed-editor-opens-filesystem-uisourcecode.js b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-tabbed-editor-opens-filesystem-uisourcecode.js
index 372e3f9..485c597 100644
--- a/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-tabbed-editor-opens-filesystem-uisourcecode.js
+++ b/third_party/blink/web_tests/http/tests/devtools/persistence/persistence-tabbed-editor-opens-filesystem-uisourcecode.js
@@ -30,7 +30,7 @@
   function dumpEditorTabs(title) {
     var editorContainer = UI.panels.sources._sourcesView._editorContainer;
     var openedUISourceCodes = [...editorContainer._tabIds.keys()];
-    openedUISourceCodes.sort((a, b) => a.url().compareTo(b.url()));
+    openedUISourceCodes.sort((a, b) => a.url > b.url ? 1 : b.url > a.url ? -1 : 0);
     TestRunner.addResult(title);
     for (const code of openedUISourceCodes)
       TestRunner.addResult('    ' + code.url());
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code-expected.txt
similarity index 63%
rename from third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code-expected.txt
rename to third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code-expected.txt
index 9ab983a..3862d7f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code-expected.txt
@@ -1,8 +1,8 @@
-Tests provisional blackboxing.
+Tests provisional ignore-listing.
 
 Set timer for test function.
 Call stack:
-    0) testFunction (frameworks-blackbox-by-source-code.js:12)
+    0) testFunction (frameworks-ignore-list-by-source-code.js:12)
     [setTimeout]
     0) scheduleTestFunction <omitted>
     <... skipped remaining frames ...>
@@ -10,7 +10,7 @@
 Executing StepInto...
 Executing StepInto...
 Call stack:
-    0) testFunction (frameworks-blackbox-by-source-code.js:14)
+    0) testFunction (frameworks-ignore-list-by-source-code.js:14)
     [setTimeout]
     0) scheduleTestFunction <omitted>
     <... skipped remaining frames ...>
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code.js
similarity index 81%
rename from third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code.js
rename to third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code.js
index 3375b34..06bdce84 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-by-source-code.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-by-source-code.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 (async function() {
-  TestRunner.addResult(`Tests provisional blackboxing.\n`);
+  TestRunner.addResult(`Tests provisional ignore-listing.\n`);
   await TestRunner.loadModule('sources_test_runner');
   await TestRunner.showPanel('sources');
   await TestRunner.evaluateInPagePromise(`
@@ -12,13 +12,13 @@
           debugger;
           eval("239;//# sourceURL=framework.js");
       }
-      //# sourceURL=frameworks-blackbox-by-source-code.js
+      //# sourceURL=frameworks-ignore-list-by-source-code.js
   `);
 
   SourcesTestRunner.startDebuggerTest(step1, true);
 
   function step1() {
-    TestRunner.addSniffer(Bindings.BlackboxManager.prototype, '_patternChangeFinishedForTests', step2);
+    TestRunner.addSniffer(Bindings.IgnoreListManager.prototype, '_patternChangeFinishedForTests', step2);
     var frameworkRegexString = '^framework\\.js$';
     Common.settingForTest('skipStackFramesPattern').set(frameworkRegexString);
   }
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns-expected.txt b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns-expected.txt
similarity index 88%
rename from third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns-expected.txt
rename to third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns-expected.txt
index b3774fa..599cc5e 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns-expected.txt
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns-expected.txt
@@ -1,4 +1,4 @@
-Tests framework blackbox patterns for various URLs.
+Tests framework ignore list patterns for various URLs.
 
 Testing "http://www.example.com/foo/jquery-1.7-min.js"
 Testing "https://www.example.com/jquery.js?version=1.7"
diff --git a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns.js b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns.js
similarity index 89%
rename from third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns.js
rename to third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns.js
index 153b229..8c9780d 100644
--- a/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-blackbox-patterns.js
+++ b/third_party/blink/web_tests/http/tests/devtools/sources/debugger-frameworks/frameworks-ignore-list-patterns.js
@@ -3,7 +3,7 @@
 // found in the LICENSE file.
 
 (async function() {
-  TestRunner.addResult(`Tests framework blackbox patterns for various URLs.\n`);
+  TestRunner.addResult(`Tests framework ignore list patterns for various URLs.\n`);
   await TestRunner.showPanel('sources');
 
   var testCases = [
@@ -34,7 +34,7 @@
   for (var i = 0; i < testCases.length; i += 2) {
     var url = testCases[i];
     TestRunner.addResult('Testing "' + url + '"');
-    var regexValue = Bindings.blackboxManager._urlToRegExpString(url);
+    var regexValue = Bindings.ignoreListManager._urlToRegExpString(url);
     TestRunner.assertEquals(testCases[i + 1], regexValue);
     if (!regexValue)
       continue;
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/frame-model-instrumentation.js b/third_party/blink/web_tests/http/tests/devtools/tracing/frame-model-instrumentation.js
index 03ebe3d..53d2c8a8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/frame-model-instrumentation.js
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/frame-model-instrumentation.js
@@ -13,7 +13,7 @@
   UI.panels.timeline._captureLayersAndPicturesSetting.set(true);
   await PerformanceTestRunner.invokeAsyncWithTimeline('doActions');
   const frames = PerformanceTestRunner.timelineFrameModel().frames();
-  const lastFrame = PerformanceTestRunner.timelineFrameModel().frames().peekLast();
+  const lastFrame = frames[frames.length - 1];
   if (lastFrame) {
     TestRunner.addResult('layerTree: ' + typeof lastFrame.layerTree);
     TestRunner.addResult('mainFrameId: ' + typeof lastFrame._mainFrameId);
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-ignore-list.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-ignore-list.js
index 85d04db9..c15d04f 100644
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-ignore-list.js
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-js/timeline-js-ignore-list.js
@@ -219,11 +219,11 @@
   dataProvider.setModel(PerformanceTestRunner.createPerformanceModelWithEvents(rawTraceEvents));
 
   TestRunner.addResult('\nIgnore listed url: lib_script.js');
-  Bindings.blackboxManager._blackboxURL('lib_script.js');
+  Bindings.ignoreListManager._ignoreListURL('lib_script.js');
   printTimelineData(dataProvider);
 
   TestRunner.addResult('\nUnignored url: lib_script.js');
-  Bindings.blackboxManager._unblackboxURL('lib_script.js');
+  Bindings.ignoreListManager._unIgnoreListURL('lib_script.js');
   printTimelineData(dataProvider);
   TestRunner.completeTest();
 })();
diff --git a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/layer-tree.js b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/layer-tree.js
index 5b56188a..a0558fb 100644
--- a/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/layer-tree.js
+++ b/third_party/blink/web_tests/http/tests/devtools/tracing/timeline-paint/layer-tree.js
@@ -35,7 +35,7 @@
 
   await PerformanceTestRunner.invokeAsyncWithTimeline('doActions');
   const frames = PerformanceTestRunner.timelineFrameModel().frames();
-  const lastFrame = PerformanceTestRunner.timelineFrameModel().frames().peekLast();
+  const lastFrame = frames[frames.length - 1];
   const layerTreeModel = await lastFrame.layerTree.layerTreePromise();
   LayersTestRunner.dumpLayerTree(undefined, layerTreeModel.contentRoot());
 
diff --git a/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js
index cd9ed9ab..ead44e8 100644
--- a/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js
+++ b/third_party/blink/web_tests/http/tests/devtools/wasm-isolated-code-cache/wasm-cache-test.js
@@ -57,6 +57,9 @@
 
   await PerformanceTestRunner.invokeWithTracing('runTests', processEvents);
 
+  function stringCompare(a, b) {
+    return a > b ? 1 : b > a ? -1 : 0;
+  }
   function processEvents() {
     // Since some WebAssembly compile events may be reported on different
     // threads, sort events by URL and type, to get a deterministic test.
@@ -64,8 +67,9 @@
       let url_a = a.args['url'] || '';
       let url_b = b.args['url'] || '';
       if (url_a != url_b)
-        return url_a.compareTo(url_b);
-      return a.name.compareTo(b.name);
+        return stringCompare(url_a, url_b)
+
+      return stringCompare(a.name, b.name)
     }
 
     const event_types = new Set([
diff --git a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/HeapSnapshotLoader.js b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/HeapSnapshotLoader.js
index 619d231..411de1a 100644
--- a/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/HeapSnapshotLoader.js
+++ b/third_party/blink/web_tests/inspector-protocol/heap-profiler/resources/HeapSnapshotLoader.js
@@ -393,20 +393,6 @@
   };
 
   /**
-   * @param {string} other
-   * @return {number}
-   */
-  String.prototype.compareTo = function(other) {
-    if (this > other) {
-      return 1;
-    }
-    if (this < other) {
-      return -1;
-    }
-    return 0;
-  };
-
-  /**
    * @param {string|undefined} string
    * @return {number}
    */
diff --git a/tools/ipc_fuzzer/fuzzer/fuzzer.cc b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
index 7319b4e..261f5aa 100644
--- a/tools/ipc_fuzzer/fuzzer/fuzzer.cc
+++ b/tools/ipc_fuzzer/fuzzer/fuzzer.cc
@@ -1670,12 +1670,14 @@
       case 0: {
         // network::DataElement::Type::TYPE_BYTES
         if (RandEvent(2)) {
-          p->SetToBytes(nullptr, 0);
+          *p = network::DataElement(
+              network::DataElementBytes(std::vector<uint8_t>()));
         } else {
           char data[256];
           int data_len = RandInRange(sizeof(data));
           fuzzer->FuzzBytes(&data[0], data_len);
-          p->SetToBytes(&data[0], data_len);
+          *p = network::DataElement(network::DataElementBytes(
+              std::vector<uint8_t>(std::begin(data), std::end(data))));
         }
         return true;
       }
@@ -1693,7 +1695,8 @@
           return false;
         if (!FuzzParam(&modification_time, fuzzer))
           return false;
-        p->SetToFilePathRange(path, offset, length, modification_time);
+        *p = network::DataElement(
+            network::DataElementFile(path, offset, length, modification_time));
         return true;
       }
       default: {
diff --git a/tools/json_schema_compiler/cpp_bundle_generator.py b/tools/json_schema_compiler/cpp_bundle_generator.py
index 0f7b683eb..0c79fe9 100644
--- a/tools/json_schema_compiler/cpp_bundle_generator.py
+++ b/tools/json_schema_compiler/cpp_bundle_generator.py
@@ -146,12 +146,13 @@
     for platform in model_object.platforms:
       if platform == Platforms.CHROMEOS:
         # TODO(https://crbug.com/1052397): For readability, this should become
-        # defined(OS_CHROMEOS) && BUILDFLAG(IS_ASH).
-        ifdefs.append('(defined(OS_CHROMEOS) && !BUILDFLAG(IS_LACROS))')
+        # defined(OS_CHROMEOS) && BUILDFLAG(IS_CHROMEOS_ASH).
+        ifdefs.append('(defined(OS_CHROMEOS) && '
+                      '!BUILDFLAG(IS_CHROMEOS_LACROS))')
       elif platform == Platforms.LACROS:
         # TODO(https://crbug.com/1052397): For readability, this should become
-        # defined(OS_CHROMEOS) && BUILDFLAG(IS_LACROS).
-        ifdefs.append('BUILDFLAG(IS_LACROS)')
+        # defined(OS_CHROMEOS) && BUILDFLAG(IS_CHROMEOS_LACROS).
+        ifdefs.append('BUILDFLAG(IS_CHROMEOS_LACROS)')
       elif platform == Platforms.LINUX:
         ifdefs.append('(defined(OS_LINUX) && !defined(OS_CHROMEOS))')
       elif platform == Platforms.MAC:
diff --git a/tools/json_schema_compiler/cpp_bundle_generator_test.py b/tools/json_schema_compiler/cpp_bundle_generator_test.py
index 0994d06..172fecae6 100755
--- a/tools/json_schema_compiler/cpp_bundle_generator_test.py
+++ b/tools/json_schema_compiler/cpp_bundle_generator_test.py
@@ -36,13 +36,14 @@
         'test/function_platform_all.json')
     self.assertEquals(
         'defined(OS_WIN) || (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || '
-        '(defined(OS_CHROMEOS) && !BUILDFLAG(IS_LACROS))',
+        '(defined(OS_CHROMEOS) && !BUILDFLAG(IS_CHROMEOS_LACROS))',
         _getPlatformIfdefs(cpp_bundle_generator, model))
 
   def testIfDefsForChromeOS(self):
     cpp_bundle_generator, model = _createCppBundleGenerator(
         'test/function_platform_chromeos.json')
-    self.assertEquals('(defined(OS_CHROMEOS) && !BUILDFLAG(IS_LACROS))',
+    self.assertEquals('(defined(OS_CHROMEOS) && '
+                      '!BUILDFLAG(IS_CHROMEOS_LACROS))',
                       _getPlatformIfdefs(cpp_bundle_generator, model))
 
 
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index 6272f65..4025dced 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -16883,6 +16883,17 @@
   <int value="3" label="Font Editor opened"/>
 </enum>
 
+<enum name="DevToolsDeveloperResourceLoaded">
+  <int value="0" label="LoadThroughPageViaTarget"/>
+  <int value="1" label="LoadThroughPageViaFrame"/>
+  <int value="2" label="LoadThroughPageFailure"/>
+  <int value="3" label="LoadThroughPageFallback"/>
+  <int value="4" label="FallbackAfterFailure"/>
+  <int value="5" label="FallbackPerOverride"/>
+  <int value="6" label="FallbackPerProtocol"/>
+  <int value="7" label="FallbackFailure"/>
+</enum>
+
 <enum name="DevToolsDualScreenDeviceEmulated">
   <int value="0" label="Dual-screen or fold device selected"/>
   <int value="1" label="Dual-screen span mode selected"/>
@@ -46577,7 +46588,6 @@
   <int value="1927218315" label="ShelfNewUi:disabled"/>
   <int value="1927259098" label="TranslateLanguageByULP:enabled"/>
   <int value="1927374573" label="EnterpriseRealtimeExtensionRequest:enabled"/>
-  <int value="1928407249" label="NewPhotoPicker:enabled"/>
   <int value="1929603041" label="HideShelfControlsInTabletMode:disabled"/>
   <int value="1930185502"
       label="EnableBluetoothVerboseLogsForGooglers:enabled"/>
@@ -46617,7 +46627,6 @@
       label="AutofillUpstreamEditableExpirationDate:disabled"/>
   <int value="1958387645" label="ScanCardsInWebPayments:enabled"/>
   <int value="1959148757" label="OffMainThreadFetch:enabled"/>
-  <int value="1960169775" label="NewPhotoPicker:disabled"/>
   <int value="1961068026"
       label="EnableEphemeralGuestProfilesOnDesktop:enabled"/>
   <int value="1961425320" label="force-qtkit"/>
@@ -56302,6 +56311,21 @@
   <int value="20" label="Tap Suppress"/>
 </enum>
 
+<enum name="OverlayQuadMaterial">
+  <int value="0" label="Invalid"/>
+  <int value="1" label="DebugBorder"/>
+  <int value="2" label="PictureContent"/>
+  <int value="3" label="CompositorRenderPass"/>
+  <int value="4" label="AggregatedRenderPass"/>
+  <int value="5" label="SolidColor"/>
+  <int value="6" label="StreamVideoContent"/>
+  <int value="7" label="SurfaceContent"/>
+  <int value="8" label="TextureContent"/>
+  <int value="9" label="TiledContent"/>
+  <int value="10" label="YuvVideoContent"/>
+  <int value="11" label="VideoHole"/>
+</enum>
+
 <enum name="OverlayStrategies">
   <int value="0" label="Unknown"/>
   <int value="1" label="No overlay"/>
@@ -56310,6 +56334,7 @@
   <int value="4" label="Underlay"/>
   <int value="5" label="Underlay Cast"/>
   <int value="6" label="All overlays failed"/>
+  <int value="7" label="Overlays failed min"/>
 </enum>
 
 <enum name="OverlaySupportFlag">
@@ -68700,6 +68725,13 @@
   <int value="10" label="Undo">The sync was aborted with an undo button.</int>
 </enum>
 
+<enum name="SigninInterceptGuestAvailability">
+  <int value="0" label="Guest option available"/>
+  <int value="1" label="Guest already open"/>
+  <int value="2" label="Guest mode blocked by policy"/>
+  <int value="3" label="Ephemeral Guest profile disabled"/>
+</enum>
+
 <enum name="SigninInterceptHeuristicOutcome">
   <int value="0" label="Intercept: profile switch"/>
   <int value="1" label="Intercept: multi-user"/>
@@ -68724,6 +68756,7 @@
   <int value="1" label="Declined"/>
   <int value="2" label="Ignored"/>
   <int value="3" label="Not displayed"/>
+  <int value="4" label="Accepted with Guest"/>
 </enum>
 
 <enum name="SigninInterceptSessionStartupResult">
@@ -69806,6 +69839,7 @@
   <int value="34" label="UMA_HOMEPAGE_PROMO_CHANGED_UNDO"/>
   <int value="35" label="UMA_CONDITIONAL_TAB_STRIP_DISMISS_UNDO"/>
   <int value="37" label="UMA_READING_LIST_BOOKMARK_ADDED"/>
+  <int value="38" label="UMA_PRIVACY_SANDBOX_PAGE_OPEN"/>
 </enum>
 
 <enum name="SnapshotItemId">
diff --git a/tools/metrics/histograms/histograms_xml/content/histograms.xml b/tools/metrics/histograms/histograms_xml/content/histograms.xml
index 69d8ef7..254f9c6 100644
--- a/tools/metrics/histograms/histograms_xml/content/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/content/histograms.xml
@@ -908,7 +908,7 @@
 </histogram>
 
 <histogram name="ContentSuggestions.Feed.Network.Duration.{NetworkEvent}"
-    units="ms" expires_after="M90">
+    units="ms" expires_after="2022-01-13">
   <owner>sczs@chromium.org</owner>
   <owner>harringtond@chromium.org</owner>
   <owner>feed@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/cookie/histograms.xml b/tools/metrics/histograms/histograms_xml/cookie/histograms.xml
index a516e89..297ae2ad 100644
--- a/tools/metrics/histograms/histograms_xml/cookie/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/cookie/histograms.xml
@@ -540,6 +540,9 @@
 
 <histogram name="Cookie.SameSiteUnspecifiedEffective"
     enum="CookieEffectiveSameSite" expires_after="M90">
+  <obsolete>
+    Removed Jan 2021 for cleanup: crbug.com/1165039
+  </obsolete>
   <owner>chlily@chromium.org</owner>
   <owner>morlovich@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/dev/histograms.xml b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
index d6a5fb7..1416ba9 100644
--- a/tools/metrics/histograms/histograms_xml/dev/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/dev/histograms.xml
@@ -126,6 +126,40 @@
   </summary>
 </histogram>
 
+<histogram name="DevTools.DeveloperResourceLoaded"
+    enum="DevToolsDeveloperResourceLoaded" expires_after="2021-12-31">
+  <owner>yangguo@chromium.org</owner>
+  <owner>sigurds@chromium.org</owner>
+  <summary>
+    Records for each developer resource load that the DevTools front-end issues
+    (e.g. to load a source map) several enum values encoding which load method
+    was used, whether a fallback was used (and why), and whether the method
+    succeeded or not.
+
+    Some explanations to make sense of the enum values:
+
+    LoadsThroughPage = LoadThroughPageViaTarget + LoadThroughPageViaFrame
+    SuccessfulLoadsThroughPage = LoadsThroughPage - LoadThroughPageFailure
+
+    LoadThroughPageFallback is the number of loads that can in principle be
+    loaded through the page, but had to use the fallback because either loading
+    through the page failed (LoadThroughPageFailure), or there was insufficient
+    information to dispatch the load through the page; the number of such loads
+    can be computed as LoadThroughPageFallback - LoadThroughPageFailure.
+
+    The number of loads not eligible for loading through the page can be
+    computed as FallbackPerOverride + FallbackPerProtocol, where
+    FallbackPerOverride indicates loads where the DevTools user disabled loading
+    through the page via an override, and FallbackPerProtocol indicates loads
+    where DevTools could not load the resource via the page due to the
+    resource's protocol scheme.
+
+    The total number of loads that used the fallback can be computed as
+    LoadThroughPageFallback + FallbackPerOverride + FallbackPerProtocol. Adding
+    SuccessfulLoadsThroughPage to that number gives the total number of loads.
+  </summary>
+</histogram>
+
 <histogram name="DevTools.DualScreenDeviceEmulated"
     enum="DevToolsDualScreenDeviceEmulated" expires_after="M87">
   <owner>yangguo@chromium.org</owner>
@@ -205,7 +239,7 @@
   </summary>
 </histogram>
 
-<histogram name="DevTools.IssueCreated" enum="DevToolsIssuesPanelOpenedFrom"
+<histogram name="DevTools.IssueCreated" enum="DevToolsIssueCreated"
     expires_after="2021-10-31">
   <owner>yangguo@chromium.org</owner>
   <owner>bmeurer@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
index a8afe61..4ebd9092 100644
--- a/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
+++ b/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml
@@ -11185,6 +11185,7 @@
   <suffix name="shopping_tasks" label="Module ID for Shopping Tasks"/>
   <affected-histogram name="NewTabPage.Modules.Dismissed"/>
   <affected-histogram name="NewTabPage.Modules.Impression"/>
+  <affected-histogram name="NewTabPage.Modules.LoadDuration"/>
   <affected-histogram name="NewTabPage.Modules.Loaded"/>
   <affected-histogram name="NewTabPage.Modules.Restored"/>
   <affected-histogram name="NewTabPage.Modules.Usage"/>
@@ -17369,8 +17370,16 @@
   <suffix name="SIGNALLING_MESSAGE" label="Signalling Message"/>
   <suffix name="SMS_FETCH_REQUEST" label="SMS Fetch Request"/>
   <suffix name="UNKNOWN_MESSAGE" label="Unknown Message"/>
-  <affected-histogram name="Sharing.DeviceLastUpdatedAge"/>
-  <affected-histogram name="Sharing.MajorVersionComparison"/>
+  <affected-histogram name="Sharing.DeviceLastUpdatedAge">
+    <obsolete>
+      Removed in M89.
+    </obsolete>
+  </affected-histogram>
+  <affected-histogram name="Sharing.MajorVersionComparison">
+    <obsolete>
+      Removed in M89.
+    </obsolete>
+  </affected-histogram>
   <affected-histogram name="Sharing.MessageAckTime"/>
   <affected-histogram name="Sharing.MessageAckTime.Android"/>
   <affected-histogram name="Sharing.MessageAckTime.ChromeOS"/>
@@ -17429,8 +17438,16 @@
   <suffix name="NetworkError" label="Network error"/>
   <suffix name="PayloadTooLarge" label="Payload is too large"/>
   <suffix name="Successful" label="Successful"/>
-  <affected-histogram name="Sharing.DeviceLastUpdatedAgeWithResult"/>
-  <affected-histogram name="Sharing.SharedClipboardRetries"/>
+  <affected-histogram name="Sharing.DeviceLastUpdatedAgeWithResult">
+    <obsolete>
+      Removed in M89.
+    </obsolete>
+  </affected-histogram>
+  <affected-histogram name="Sharing.SharedClipboardRetries">
+    <obsolete>
+      Removed in M89.
+    </obsolete>
+  </affected-histogram>
 </histogram_suffixes>
 
 <histogram_suffixes name="SharingWebRtcTimingEvent" separator=".">
diff --git a/tools/metrics/histograms/histograms_xml/net/histograms.xml b/tools/metrics/histograms/histograms_xml/net/histograms.xml
index 34ccf9d..56073891 100644
--- a/tools/metrics/histograms/histograms_xml/net/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/net/histograms.xml
@@ -1920,7 +1920,7 @@
 </histogram>
 
 <histogram name="Net.NetworkErrorLogging.SignedExchangeRequestOutcome"
-    enum="NetNetworkErrorLoggingRequestOutcome" expires_after="2021-01-24">
+    enum="NetNetworkErrorLoggingRequestOutcome" expires_after="M94">
   <owner>horo@chromium.org</owner>
   <owner>ksakamoto@chromium.org</owner>
   <owner>kinuko@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
index 144a4f9..d8b3c0db 100644
--- a/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/new_tab_page/histograms.xml
@@ -788,6 +788,16 @@
   </summary>
 </histogram>
 
+<histogram name="NewTabPage.Modules.LoadDuration" units="ms"
+    expires_after="2022-01-01">
+  <owner>danielms@google.com</owner>
+  <owner>tiborg@chromium.org</owner>
+  <owner>chrome-desktop-ntp@google.com</owner>
+  <summary>
+    Histogram of the time in milliseconds it took for an NTP module to load.
+  </summary>
+</histogram>
+
 <histogram name="NewTabPage.Modules.Loaded" units="ms"
     expires_after="2021-07-04">
   <owner>tiborg@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/others/histograms.xml b/tools/metrics/histograms/histograms_xml/others/histograms.xml
index 2caed7d..bb308b1 100644
--- a/tools/metrics/histograms/histograms_xml/others/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/others/histograms.xml
@@ -11677,7 +11677,7 @@
 </histogram>
 
 <histogram name="PrefetchedSignedExchangeCache.HeadersSizeTotal" units="bytes"
-    expires_after="2021-01-24">
+    expires_after="M94">
   <owner>horo@chromium.org</owner>
   <owner>webpackage-dev@chromium.org</owner>
   <summary>
@@ -17046,6 +17046,16 @@
   </summary>
 </histogram>
 
+<histogram name="Viz.DisplayCompositor.OverlayQuadMaterial"
+    enum="OverlayQuadMaterial" expires_after="2021-07-01">
+  <owner>petermcneeley@chromium.org</owner>
+  <owner>dcastagna@chromium.org</owner>
+  <summary>
+    Quad material for current promoted overlay, per frame. Recorded every time a
+    frame is rendered by the display compositor.
+  </summary>
+</histogram>
+
 <histogram name="Viz.DisplayCompositor.OverlayStrategy"
     enum="OverlayStrategies" expires_after="2021-07-01">
   <owner>dcastagna@chromium.org</owner>
@@ -18274,8 +18284,12 @@
 </histogram>
 
 <histogram name="WebsiteSettings.Menu.PermissionChanged.SessionOnly"
-    enum="ContentType" expires_after="M90">
-  <owner>timloh@chromium.org</owner>
+    enum="ContentType" expires_after="M96">
+  <owner>andypaicu@chromium.org</owner>
+  <owner>engedy@chromium.org</owner>
+  <owner>hkamila@chromium.org</owner>
+  <owner>ravjit@chromium.org</owner>
+  <owner>elklm@chromium.org</owner>
   <summary>
     Count of how often a specific content type (permission) is changed to the
     session only value using the content settings menu. This option only exists
diff --git a/tools/metrics/histograms/histograms_xml/permissions/histograms.xml b/tools/metrics/histograms/histograms_xml/permissions/histograms.xml
index f3e7d78..a1cd0d6 100644
--- a/tools/metrics/histograms/histograms_xml/permissions/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/permissions/histograms.xml
@@ -86,8 +86,12 @@
 </histogram>
 
 <histogram name="Permissions.BatteryLevel.Accepted.LocationSettingsDialog"
-    units="%" expires_after="M90">
-  <owner>timloh@chromium.org</owner>
+    units="%" expires_after="M96">
+  <owner>andypaicu@chromium.org</owner>
+  <owner>engedy@chromium.org</owner>
+  <owner>hkamila@chromium.org</owner>
+  <owner>ravjit@chromium.org</owner>
+  <owner>elklm@chromium.org</owner>
   <summary>
     Battery percentage when a location settings dialog was accepted.
   </summary>
@@ -131,10 +135,12 @@
 </histogram>
 
 <histogram name="Permissions.CrowdDeny.DidHoldbackQuietUi" enum="Boolean"
-    expires_after="2021-01-31">
+    expires_after="M96">
   <owner>andypaicu@chromium.org</owner>
   <owner>engedy@chromium.org</owner>
   <owner>hkamila@chromium.org</owner>
+  <owner>ravjit@chromium.org</owner>
+  <owner>elklm@chromium.org</owner>
   <summary>
     Whenever a notification permission prompt is to be displayed, crowd deny
     might trigger based on site reputation which will result in a quiet
diff --git a/tools/metrics/histograms/histograms_xml/search/histograms.xml b/tools/metrics/histograms/histograms_xml/search/histograms.xml
index 5172242f..c5e4bc81 100644
--- a/tools/metrics/histograms/histograms_xml/search/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/search/histograms.xml
@@ -1216,7 +1216,7 @@
 </histogram>
 
 <histogram name="Search.iOS.SelectDefaultSearchEngine"
-    enum="OmniboxSearchEngineType" expires_after="2021-02-04">
+    enum="OmniboxSearchEngineType" expires_after="2022-02-04">
   <owner>sczs@chromium.org</owner>
   <owner>gambard@chromium.org</owner>
   <summary>
diff --git a/tools/metrics/histograms/histograms_xml/sharing/histograms.xml b/tools/metrics/histograms/histograms_xml/sharing/histograms.xml
index f2eb45f2..416040d 100644
--- a/tools/metrics/histograms/histograms_xml/sharing/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/sharing/histograms.xml
@@ -115,6 +115,9 @@
 
 <histogram name="Sharing.DeviceInfoAvailable" enum="BooleanAvailable"
     expires_after="M87">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
   <owner>knollr@chromium.org</owner>
   <owner>mvanouwerkerk@chromium.org</owner>
   <summary>
@@ -125,6 +128,9 @@
 
 <histogram name="Sharing.DeviceLastUpdatedAge" units="hours"
     expires_after="M87">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
 <!-- Name completed by histogram_suffixes name="SharingMessage" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
@@ -138,6 +144,9 @@
 
 <histogram name="Sharing.DeviceLastUpdatedAgeWithResult" units="hours"
     expires_after="M87">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
 <!-- Name completed by histogram_suffixes name="SharingSendMessageResult" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
@@ -171,6 +180,9 @@
 
 <histogram name="Sharing.MajorVersionComparison"
     enum="SharingMajorVersionComparison" expires_after="M87">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
 <!-- Name completed by histogram_suffixes name="SharingMessage" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
@@ -407,6 +419,9 @@
 
 <histogram name="Sharing.SharedClipboardRetries" units="retries"
     expires_after="M87">
+  <obsolete>
+    Removed in M89.
+  </obsolete>
 <!-- Name completed by histogram_suffixes name="SharingSendMessageResult" -->
 
   <owner>mvanouwerkerk@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/signin/histograms.xml b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
index 4e05162..07250917 100644
--- a/tools/metrics/histograms/histograms_xml/signin/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/signin/histograms.xml
@@ -407,6 +407,16 @@
   </summary>
 </histogram>
 
+<histogram name="Signin.Intercept.Guest.Availability"
+    enum="SigninInterceptGuestAvailability" expires_after="2021-08-12">
+  <owner>rhalavati@chromium.org</owner>
+  <owner>droger@chromium.org</owner>
+  <summary>
+    Records whether Guest option was available prior to showing signin intercept
+    and if not, why.
+  </summary>
+</histogram>
+
 <histogram name="Signin.Intercept.HeuristicOutcome"
     enum="SigninInterceptHeuristicOutcome" expires_after="2021-08-12">
   <owner>droger@chromium.org</owner>
diff --git a/tools/metrics/histograms/histograms_xml/web_audio/histograms.xml b/tools/metrics/histograms/histograms_xml/web_audio/histograms.xml
index 80f4e7c..a1f0fbd 100644
--- a/tools/metrics/histograms/histograms_xml/web_audio/histograms.xml
+++ b/tools/metrics/histograms/histograms_xml/web_audio/histograms.xml
@@ -223,6 +223,9 @@
 
 <histogram name="WebAudio.OfflineAudioContext.ChannelCount" units="units"
     expires_after="2021-07-06">
+  <obsolete>
+    Removed 2021-01-12. See crbug.com/1165240.
+  </obsolete>
   <owner>rtoy@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <summary>
@@ -234,6 +237,9 @@
 
 <histogram name="WebAudio.OfflineAudioContext.Length" units="frames"
     expires_after="2021-05-23">
+  <obsolete>
+    Removed 2021-01-12. See crbug.com/1165240.
+  </obsolete>
   <owner>rtoy@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <summary>
@@ -245,6 +251,9 @@
 
 <histogram name="WebAudio.OfflineAudioContext.SampleRate384kHz" units="Hz"
     expires_after="2021-02-18">
+  <obsolete>
+    Removed 2021-01-12. See crbug.com/1165240.
+  </obsolete>
   <owner>rtoy@chromium.org</owner>
   <owner>hongchan@chromium.org</owner>
   <summary>
diff --git a/tools/perf/benchmarks/blink_perf_unittest.py b/tools/perf/benchmarks/blink_perf_unittest.py
index 91340d4..891ca35 100644
--- a/tools/perf/benchmarks/blink_perf_unittest.py
+++ b/tools/perf/benchmarks/blink_perf_unittest.py
@@ -130,6 +130,8 @@
     self.RunPageTest(self.blink_page_test, 'file://lifecycle-methods.html')
     self.assertFalse(self.HasChromeTraces())
 
+  @decorators.Disabled('linux',
+                       'chromeos')  # Disable due to flaky: crbug.com/1163628
   def testExtraChromeCategories(self):
     self.options.extra_chrome_categories = 'cc,blink'
     self.RunPageTest(self.blink_page_test, 'file://lifecycle-methods.html')
diff --git a/tools/perf/core/perfetto_binary_roller/binary_deps.json b/tools/perf/core/perfetto_binary_roller/binary_deps.json
index 02beb766..17fa149 100644
--- a/tools/perf/core/perfetto_binary_roller/binary_deps.json
+++ b/tools/perf/core/perfetto_binary_roller/binary_deps.json
@@ -1,16 +1,16 @@
 {
     "trace_processor_shell": {
         "win": {
-            "hash": "e1f08368dcce2a5fae6b8997393ce4172e26ffe0",
-            "remote_path": "perfetto_binaries/trace_processor_shell/win/2881d6b22d1eba089a772a15733151b67685cdaf/trace_processor_shell.exe"
+            "hash": "43de0f5bf6578be85985a48b8b8107237f5e79ce",
+            "remote_path": "perfetto_binaries/trace_processor_shell/win/44ba8e1708abec70b1c85015aae59026fb214c83/trace_processor_shell.exe"
         },
         "mac": {
             "hash": "b25230d11856547e55e67c4b28dfb2948a5e6473",
             "remote_path": "perfetto_binaries/trace_processor_shell/mac/44ba8e1708abec70b1c85015aae59026fb214c83/trace_processor_shell"
         },
         "linux": {
-            "hash": "dc8c4a04caf836aca794cd8e8f19207ca3116bc7",
-            "remote_path": "perfetto_binaries/trace_processor_shell/linux/51e1fea7385f810e7d08c2fb333112d00fbfcd0e/trace_processor_shell"
+            "hash": "7b943f691679aecb10dfc1e468229eda90fdcbc1",
+            "remote_path": "perfetto_binaries/trace_processor_shell/linux/44ba8e1708abec70b1c85015aae59026fb214c83/trace_processor_shell"
         }
     },
     "power_profile.sql": {
diff --git a/ui/base/clipboard/clipboard_test_template.h b/ui/base/clipboard/clipboard_test_template.h
index bbf88e3..78fac5f 100644
--- a/ui/base/clipboard/clipboard_test_template.h
+++ b/ui/base/clipboard/clipboard_test_template.h
@@ -112,9 +112,10 @@
   MOCK_METHOD2(IsClipboardReadAllowed,
                bool(const DataTransferEndpoint* const data_src,
                     const DataTransferEndpoint* const data_dst));
-  MOCK_METHOD2(IsDragDropAllowed,
+  MOCK_METHOD3(IsDragDropAllowed,
                bool(const DataTransferEndpoint* const data_src,
-                    const DataTransferEndpoint* const data_dst));
+                    const DataTransferEndpoint* const data_dst,
+                    const bool is_drop));
 };
 
 MockPolicyController::MockPolicyController() = default;
diff --git a/ui/base/data_transfer_policy/data_transfer_policy_controller.h b/ui/base/data_transfer_policy/data_transfer_policy_controller.h
index 4eb2e02..6d7f7f2b 100644
--- a/ui/base/data_transfer_policy/data_transfer_policy_controller.h
+++ b/ui/base/data_transfer_policy/data_transfer_policy_controller.h
@@ -35,9 +35,9 @@
 
   // nullptr can be passed instead of `data_src` or `data_dst`. If dropping the
   // data is not allowed, this function will show a notification to the user.
-  virtual bool IsDragDropAllowed(
-      const DataTransferEndpoint* const data_src,
-      const DataTransferEndpoint* const data_dst) = 0;
+  virtual bool IsDragDropAllowed(const DataTransferEndpoint* const data_src,
+                                 const DataTransferEndpoint* const data_dst,
+                                 const bool is_drop) = 0;
 
  protected:
   DataTransferPolicyController();
diff --git a/ui/file_manager/BUILD.gn b/ui/file_manager/BUILD.gn
index 7f6dbd4c..23125b4 100644
--- a/ui/file_manager/BUILD.gn
+++ b/ui/file_manager/BUILD.gn
@@ -64,7 +64,6 @@
     "file_manager/foreground/js:js_test_gen_html",
     "file_manager/foreground/js:js_test_gen_html_modules",
     "file_manager/foreground/js/metadata:js_test_gen_html_modules",
-    "file_manager/foreground/js/ui:js_test_gen_html",
     "file_manager/foreground/js/ui:js_test_gen_html_modules",
     "gallery/js:js_test_gen_html",
     "gallery/js/image_editor:js_test_gen_html",
diff --git a/ui/file_manager/file_manager/foreground/js/BUILD.gn b/ui/file_manager/file_manager/foreground/js/BUILD.gn
index 50e902ea..6680960 100644
--- a/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -47,17 +47,22 @@
     ":file_watcher.m",
     ":folder_shortcuts_data_model.m",
     ":holding_space_util.m",
+    ":last_modified_controller.m",
     ":launch_param.m",
     ":list_thumbnail_loader.m",
+    ":metadata_update_controller.m",
     ":mock_directory_model.m",
     ":mock_folder_shortcut_data_model.m",
     ":mock_navigation_list_model.m",
     ":mock_thumbnail_loader.m",
+    ":naming_controller.m",
     ":navigation_list_model.m",
     ":navigation_uma.m",
     ":path_component.m",
     ":providers_model.m",
+    ":quick_view_model.m",
     ":spinner_controller.m",
+    ":task_history.m",
     ":thumbnail_loader.m",
     ":web_store_utils.m",
   ]
@@ -1000,6 +1005,17 @@
   ]
 }
 
+js_library("last_modified_controller.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/last_modified_controller.m.js" ]
+  deps = [
+    ":directory_model.m",
+    "ui:file_table.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("launch_param") {
   deps = [
     ":dialog_type",
@@ -1104,6 +1120,19 @@
   ]
 }
 
+js_library("metadata_update_controller.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/metadata_update_controller.m.js" ]
+  deps = [
+    ":directory_model.m",
+    "metadata:metadata_model.m",
+    "ui:file_metadata_formatter.m",
+    "ui:list_container.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("metrics_start") {
   deps = [ "//ui/file_manager/file_manager/common/js:metrics" ]
 }
@@ -1125,6 +1154,21 @@
   ]
 }
 
+js_library("naming_controller.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/naming_controller.m.js" ]
+  deps = [
+    ":directory_contents.m",
+    ":directory_model.m",
+    ":file_selection.m",
+    "ui:list_container.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js/cr/ui:dialogs.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("navigation_list_model") {
   deps = [
     ":android_app_list_model",
@@ -1242,6 +1286,16 @@
   ]
 }
 
+js_library("quick_view_model.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/quick_view_model.m.js" ]
+  deps = [
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js/cr:event_target.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("quick_view_uma") {
   deps = [
     ":dialog_type",
@@ -1332,6 +1386,16 @@
   deps = [ "//ui/webui/resources/js/cr:event_target" ]
 }
 
+js_library("task_history.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/task_history.m.js" ]
+  deps = [
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js/cr:event_target.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 # TODO(tapted): Move this into //ui/file_manager/base.
 js_library("thumbnail_loader") {
   visibility += [ "//ui/file_manager/gallery/*" ]
@@ -1447,25 +1511,30 @@
     "file_list_model.js",
     "file_selection.js",
     "file_transfer_controller.js",
+    "file_type_filters_controller.js",
     "file_watcher.js",
     "folder_shortcuts_data_model.js",
     "holding_space_util.js",
+    "last_modified_controller.js",
     "launch_param.js",
     "list_thumbnail_loader.js",
+    "metadata_update_controller.js",
+    "metrics_start.js",
+    "mock_actions_model.js",
     "mock_directory_model.js",
     "mock_folder_shortcut_data_model.js",
     "mock_navigation_list_model.js",
     "mock_thumbnail_loader.js",
+    "naming_controller.js",
     "navigation_list_model.js",
+    "navigation_uma.js",
     "path_component.js",
     "providers_model.js",
+    "quick_view_model.js",
+    "spinner_controller.js",
+    "task_history.js",
     "thumbnail_loader.js",
     "web_store_utils.js",
-    "file_type_filters_controller.js",
-    "navigation_uma.js",
-    "metrics_start.js",
-    "mock_actions_model.js",
-    "spinner_controller.js",
   ]
 
   namespace_rewrites =
diff --git a/ui/file_manager/file_manager/foreground/js/holding_space_util.js b/ui/file_manager/file_manager/foreground/js/holding_space_util.js
index 19c53d7..435768c 100644
--- a/ui/file_manager/file_manager/foreground/js/holding_space_util.js
+++ b/ui/file_manager/file_manager/foreground/js/holding_space_util.js
@@ -41,7 +41,7 @@
 
   /**
    * Returns the volume types for which the holding space feature is allowed.
-   * @return {!Array<VolumeManagerCommon.VolumeType>}
+   * @return {!Array<?VolumeManagerCommon.VolumeType>}
    */
   static getAllowedVolumeTypes() {
     return [
diff --git a/ui/file_manager/file_manager/foreground/js/last_modified_controller.js b/ui/file_manager/file_manager/foreground/js/last_modified_controller.js
index c27d078..da5450e 100644
--- a/ui/file_manager/file_manager/foreground/js/last_modified_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/last_modified_controller.js
@@ -2,10 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {DirectoryModel} from './directory_model.m.js';
+// #import {FileTable} from './ui/file_table.m.js';
+// #import {util} from '../../common/js/util.m.js';
+
 /**
  * Controls last modified column in the file table.
  */
-class LastModifiedController {
+/* #export */ class LastModifiedController {
   /**
    * @param {!FileTable} fileTable File table UI.
    * @param {!DirectoryModel} directoryModel Directory model.
diff --git a/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js b/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js
index 2042e6de..567b0038 100644
--- a/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/metadata_update_controller.js
@@ -2,10 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {FileMetadataFormatter} from './ui/file_metadata_formatter.m.js';
+// #import {MetadataModel} from './metadata/metadata_model.m.js';
+// #import {DirectoryModel} from './directory_model.m.js';
+// #import {ListContainer} from './ui/list_container.m.js';
+// #import {util} from '../../common/js/util.m.js';
+
 /**
  * Controller for list contents update.
  */
-class MetadataUpdateController {
+/* #export */ class MetadataUpdateController {
   /**
    * @param {!ListContainer} listContainer
    * @param {!DirectoryModel} directoryModel
diff --git a/ui/file_manager/file_manager/foreground/js/naming_controller.js b/ui/file_manager/file_manager/foreground/js/naming_controller.js
index 79d6c68b..22a505e 100644
--- a/ui/file_manager/file_manager/foreground/js/naming_controller.js
+++ b/ui/file_manager/file_manager/foreground/js/naming_controller.js
@@ -2,10 +2,20 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {FileSelectionHandler} from './file_selection.m.js';
+// #import {FileFilter} from './directory_contents.m.js';
+// #import {DirectoryModel} from './directory_model.m.js';
+// #import {AlertDialog, ConfirmDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js';
+// #import {ListContainer} from './ui/list_container.m.js';
+// #import {util, strf} from '../../common/js/util.m.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// clang-format off
+
 /**
  * Controller to handle naming.
  */
-class NamingController {
+/* #export */ class NamingController {
   /**
    * @param {!ListContainer} listContainer
    * @param {!cr.ui.dialogs.AlertDialog} alertDialog
diff --git a/ui/file_manager/file_manager/foreground/js/quick_view_model.js b/ui/file_manager/file_manager/foreground/js/quick_view_model.js
index d7f472b..7d1e658 100644
--- a/ui/file_manager/file_manager/foreground/js/quick_view_model.js
+++ b/ui/file_manager/file_manager/foreground/js/quick_view_model.js
@@ -2,10 +2,15 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// #import {dispatchSimpleEvent} from 'chrome://resources/js/cr.m.js';
+// clang-format on
+
 /**
  * Quick view model that doesn't fit into properties of quick view element.
  */
-class QuickViewModel extends cr.EventTarget {
+/* #export */ class QuickViewModel extends cr.EventTarget {
   constructor() {
     super();
 
diff --git a/ui/file_manager/file_manager/foreground/js/task_history.js b/ui/file_manager/file_manager/foreground/js/task_history.js
index ae25995..03e1c2f 100644
--- a/ui/file_manager/file_manager/foreground/js/task_history.js
+++ b/ui/file_manager/file_manager/foreground/js/task_history.js
@@ -2,11 +2,16 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// #import {dispatchSimpleEvent} from 'chrome://resources/js/cr.m.js';
+// clang-format on
+
 /**
  * TaskHistory object keeps track of the histry of task executions.
  * This is responsible for keeping the history in persistent storage, too.
  */
-class TaskHistory extends cr.EventTarget {
+/* #export */ class TaskHistory extends cr.EventTarget {
   constructor() {
     super();
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
index bcbba01..19b81102 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
+++ b/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn
@@ -17,15 +17,18 @@
     ":closure_compile_jsmodules",
     ":closure_compile_module",
     ":js_test_gen_html_modules_type_check_auto",
-    ":js_test_gen_html_type_check_auto",
   ]
 }
 
 js_type_check("closure_compile_jsmodules") {
-  uses_js_modules = true
+  is_polymer3 = true
   deps = [
     ":a11y_announce.m",
     ":action_model_ui.m",
+    ":actions_submenu.m",
+    ":autocomplete_list.m",
+    ":banners.m",
+    ":breadcrumb.m",
     ":combobutton.m",
     ":commandbutton.m",
     ":default_task_dialog.m",
@@ -42,10 +45,16 @@
     ":files_alert_dialog.m",
     ":files_confirm_dialog.m",
     ":files_menu.m",
+    ":gear_menu.m",
+    ":import_crostini_image_dialog.m",
+    ":install_linux_package_dialog.m",
     ":list_container.m",
+    ":location_line.m",
     ":multi_menu.m",
     ":multi_menu_button.m",
     ":progress_center_panel.m",
+    ":providers_menu.m",
+    ":search_box.m",
     ":suggest_apps_dialog.m",
     "table:table.m",
     "table:table_column.m",
@@ -159,11 +168,28 @@
   ]
 }
 
-js_unittest("actions_submenu_unittest") {
+js_library("actions_submenu.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.m.js" ]
   deps = [
-    ":actions_submenu",
-    "//ui/file_manager/file_manager/foreground/js:mock_actions_model",
-    "//ui/webui/resources/js:webui_resource_test",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/js:actions_model.m",
+    "//ui/webui/resources/js:util.m",
+    "//ui/webui/resources/js/cr/ui:command.m",
+    "//ui/webui/resources/js/cr/ui:menu.m",
+    "//ui/webui/resources/js/cr/ui:menu_item.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
+js_unittest("actions_submenu_unittest.m") {
+  deps = [
+    ":actions_submenu.m",
+    "//chrome/test/data/webui:chai_assert",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/js:mock_actions_model.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js/cr/ui:menu.m",
   ]
 }
 
@@ -179,15 +205,44 @@
   externs_list = [ "//ui/file_manager/externs/chrome_echo_private.js" ]
 }
 
+js_library("banners.m") {
+  sources = [
+    "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/banners.m.js",
+  ]
+  deps = [
+    "//ui/file_manager/base/js:volume_manager_types.m",
+    "//ui/file_manager/externs:volume_info.m",
+    "//ui/file_manager/externs:volume_manager.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/js:constants.m",
+    "//ui/file_manager/file_manager/foreground/js:directory_model.m",
+    "//ui/file_manager/file_manager/foreground/js:holding_space_util.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js:util.m",
+    "//ui/webui/resources/js/cr:event_target.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("breadcrumb") {
   deps = [ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu" ]
 }
 
-js_unittest("breadcrumb_unittest") {
+js_library("breadcrumb.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.m.js" ]
+
+  deps = [ "//ui/webui/resources/cr_elements/cr_action_menu:cr_action_menu.m" ]
+
+  extra_deps = [ ":modulize" ]
+}
+
+js_unittest("breadcrumb_unittest.m") {
   deps = [
-    ":breadcrumb",
-    "//ui/webui/resources/js:assert",
-    "//ui/webui/resources/js:webui_resource_test",
+    ":breadcrumb.m",
+    "//chrome/test/data/webui:chai_assert",
+    "//ui/webui/resources/js:assert.m",
   ]
 }
 
@@ -703,6 +758,18 @@
   deps = [ "//ui/file_manager/file_manager/common/js:util" ]
 }
 
+js_library("gear_menu.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/gear_menu.m.js" ]
+  deps = [
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:load_time_data.m",
+    "//ui/webui/resources/js:util.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("install_linux_package_dialog") {
   deps = [
     ":file_manager_dialog_base",
@@ -710,11 +777,23 @@
   ]
 }
 
-js_unittest("install_linux_package_dialog_unittest") {
+js_library("install_linux_package_dialog.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.m.js" ]
   deps = [
-    ":install_linux_package_dialog",
-    "//ui/file_manager/base/js:test_error_reporting",
-    "//ui/webui/resources/js:webui_resource_test",
+    ":file_manager_dialog_base.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/webui/resources/js:assert.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
+js_unittest("install_linux_package_dialog_unittest.m") {
+  deps = [
+    ":install_linux_package_dialog.m",
+    "//chrome/test/data/webui:chai_assert",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:load_time_data.m",
   ]
 }
 
@@ -726,6 +805,16 @@
   ]
 }
 
+js_library("import_crostini_image_dialog.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.m.js" ]
+  deps = [
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/webui/resources/js/cr/ui:dialogs.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("list_container") {
   deps = [
     ":file_grid",
@@ -768,6 +857,22 @@
   ]
 }
 
+js_library("location_line.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/location_line.m.js" ]
+  deps = [
+    ":list_container.m",
+    "//ui/file_manager/externs:files_app_entry_interfaces.m",
+    "//ui/file_manager/externs:volume_manager.m",
+    "//ui/file_manager/file_manager/common/js:metrics.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/elements:files_tooltip.m",
+    "//ui/file_manager/file_manager/foreground/js:path_component.m",
+    "//ui/webui/resources/js/cr:event_target.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("multi_menu") {
   deps = [
     # TODO(files-ng): remove util dep when the files-ng flag is removed.
@@ -867,6 +972,20 @@
   externs_list = [ "//ui/file_manager/externs/menu_item_update_event.js" ]
 }
 
+js_library("providers_menu.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/providers_menu.m.js" ]
+  deps = [
+    ":files_menu.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/js:providers_model.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js/cr:ui.m",
+    "//ui/webui/resources/js/cr/ui:menu.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("search_box") {
   deps = [
     ":autocomplete_list",
@@ -882,6 +1001,25 @@
   externs_list = [ "//ui/file_manager/externs/search_item.js" ]
 }
 
+js_library("search_box.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/search_box.m.js" ]
+  deps = [
+    ":autocomplete_list.m",
+    "//ui/file_manager/file_manager/common/js:file_type.m",
+    "//ui/file_manager/file_manager/common/js:metrics.m",
+    "//ui/file_manager/file_manager/common/js:util.m",
+    "//ui/file_manager/file_manager/foreground/elements:files_toggle_ripple.m",
+    "//ui/webui/resources/js:assert.m",
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js:util.m",
+    "//ui/webui/resources/js/cr:event_target.m",
+    "//ui/webui/resources/js/cr/ui:list_item.m",
+  ]
+  externs_list = [ "//ui/file_manager/externs/search_item.js" ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("autocomplete_list") {
   deps = [
     "//ui/webui/resources/js/cr/ui:list",
@@ -890,6 +1028,20 @@
   ]
 }
 
+js_library("autocomplete_list.m") {
+  sources = [ "$root_gen_dir/ui/file_manager/file_manager/foreground/js/ui/autocomplete_list.m.js" ]
+  deps = [
+    "//ui/webui/resources/js:cr.m",
+    "//ui/webui/resources/js/cr/ui:array_data_model.m",
+    "//ui/webui/resources/js/cr/ui:list.m",
+    "//ui/webui/resources/js/cr/ui:list_item.m",
+    "//ui/webui/resources/js/cr/ui:list_single_selection_model.m",
+    "//ui/webui/resources/js/cr/ui:position_util.m",
+  ]
+
+  extra_deps = [ ":modulize" ]
+}
+
 js_library("suggest_apps_dialog") {
   deps = [
     ":file_manager_dialog_base",
@@ -927,15 +1079,18 @@
 
 js_test_gen_html("js_test_gen_html_modules") {
   deps = [
+    ":actions_submenu_unittest.m",
+    ":breadcrumb_unittest.m",
     ":directory_tree_unittest.m",
     ":file_list_selection_model_unittest.m",
     ":file_manager_dialog_base_unittest.m",
     ":file_table_list_unittest.m",
     ":file_table_unittest.m",
     ":file_tap_handler_unittest.m",
+    ":install_linux_package_dialog_unittest.m",
     ":multi_menu_unittest.m",
   ]
-  js_module = true
+  is_polymer3 = true
 
   closure_flags =
       strict_error_checking_closure_args + [
@@ -947,18 +1102,14 @@
       ]
 }
 
-js_test_gen_html("js_test_gen_html") {
-  deps = [
-    ":actions_submenu_unittest",
-    ":breadcrumb_unittest",
-    ":install_linux_package_dialog_unittest",
-  ]
-}
-
 js_modulizer("modulize") {
   input_files = [
     "a11y_announce.js",
     "action_model_ui.js",
+    "actions_submenu.js",
+    "autocomplete_list.js",
+    "banners.js",
+    "breadcrumb.js",
     "combobutton.js",
     "commandbutton.js",
     "default_task_dialog.js",
@@ -975,10 +1126,16 @@
     "files_alert_dialog.js",
     "files_confirm_dialog.js",
     "files_menu.js",
+    "gear_menu.js",
+    "import_crostini_image_dialog.js",
+    "install_linux_package_dialog.js",
     "list_container.js",
+    "location_line.js",
     "multi_menu.js",
     "multi_menu_button.js",
     "progress_center_panel.js",
+    "providers_menu.js",
+    "search_box.js",
     "suggest_apps_dialog.js",
   ]
 
@@ -988,5 +1145,6 @@
     "cr.ui.FilesMenuItem|FilesMenuItem",
     "cr.ui.MultiMenu|MultiMenu",
     "cr.ui.table.Table|Table",
+    "cr.ui.AutocompleteList|AutocompleteList",
   ]
 }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
index 8451e10..cddd9f7 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu.js
@@ -2,7 +2,14 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-class ActionsSubmenu {
+// #import {MenuItem} from 'chrome://resources/js/cr/ui/menu_item.m.js';
+// #import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+// #import {Command} from 'chrome://resources/js/cr/ui/command.m.js';
+// #import {util} from '../../../common/js/util.m.js';
+// #import {ActionsModel} from '../actions_model.m.js';
+// #import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
+
+/* #export */ class ActionsSubmenu {
   /** @param {!cr.ui.Menu} menu */
   constructor(menu) {
     /**
diff --git a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js
similarity index 61%
rename from ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
rename to ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js
index 395c7fa..67c6455 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/actions_submenu_unittest.m.js
@@ -1,44 +1,43 @@
 // Copyright 2015 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
-'use strict';
+
+import {assertInstanceof} from 'chrome://resources/js/assert.m.js';
+import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+import {assertEquals, assertFalse, assertTrue} from 'chrome://test/chai_assert.js';
+
+import {util} from '../../../common/js/util.m.js';
+import {MockActionModel, MockActionsModel} from '../mock_actions_model.m.js';
+
+import {ActionsSubmenu} from './actions_submenu.m.js';
 
 let menu = null;
 let submenu = null;
 let separator = null;
 
-document.write(`
-    <command id="share" label="Share"></command>
-    <command id="manage-in-drive" label="Manage in Drive"></command>
-    <command id="toggle-pinned" label="Toggle pinned"></command>
-    <command id="unpin-folder" label="Remove folder shortcut">
-    </command>
-
-    <cr-menu id="menu">
-    <hr id="actions-separator" hidden>
-    </cr-menu>`);
-
 function queryRequiredElement(selectors, opt_context) {
   const element = (opt_context || document).querySelector(selectors);
   return assertInstanceof(
       element, HTMLElement, 'Missing required element: ' + selectors);
 }
 
-function setUp() {
-  menu = util.queryDecoratedElement('#menu', cr.ui.Menu);
+export function setUp() {
+  document.body.innerHTML = `
+      <command id="share" label="Share"></command>
+      <command id="manage-in-drive" label="Manage in Drive"></command>
+      <command id="toggle-pinned" label="Toggle pinned"></command>
+      <command id="unpin-folder" label="Remove folder shortcut">
+      </command>
+
+      <cr-menu id="menu">
+      <hr id="actions-separator" hidden>
+      </cr-menu>`;
+  menu = util.queryDecoratedElement('#menu', Menu);
   separator = queryRequiredElement('#actions-separator', menu);
   submenu = new ActionsSubmenu(menu);
 }
 
-function tearDown() {
-  const items = document.querySelectorAll('#menu cr-menu-item');
-  for (let i = 0; i < items.length; i++) {
-    items[i].parentNode.removeChild(items[i]);
-  }
-  separator.hidden = true;
-}
-
-function testSeparator() {
+export function testSeparator() {
   assertTrue(separator.hidden);
 
   submenu.setActionsModel(
@@ -49,7 +48,7 @@
   assertTrue(separator.hidden);
 }
 
-function testNullModel() {
+export function testNullModel() {
   submenu.setActionsModel(
       new MockActionsModel({id: new MockActionModel('title', null)}));
   let item = menu.querySelector('cr-menu-item');
@@ -60,7 +59,7 @@
   assertFalse(!!item);
 }
 
-function testCustomActionRendering() {
+export function testCustomActionRendering() {
   submenu.setActionsModel(
       new MockActionsModel({id: new MockActionModel('title', null)}));
   const item = menu.querySelector('cr-menu-item');
@@ -69,7 +68,7 @@
   assertEquals(null, item.command);
 }
 
-function testCommandActionRendering() {
+export function testCommandActionRendering() {
   submenu.setActionsModel(new MockActionsModel(
       {SHARE: new MockActionModel('share with me!', null)}));
   const item = menu.querySelector('cr-menu-item');
diff --git a/ui/file_manager/file_manager/foreground/js/ui/autocomplete_list.js b/ui/file_manager/file_manager/foreground/js/ui/autocomplete_list.js
index fd7cf48..553de52 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/autocomplete_list.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/autocomplete_list.js
@@ -2,12 +2,22 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {positionPopupAroundElement, AnchorType} from 'chrome://resources/js/cr/ui/position_util.m.js';
+// #import {ArrayDataModel} from 'chrome://resources/js/cr/ui/array_data_model.m.js';
+// #import {ListItem} from 'chrome://resources/js/cr/ui/list_item.m.js';
+// #import {ListSingleSelectionModel} from 'chrome://resources/js/cr/ui/list_single_selection_model.m.js';
+// #import {List} from 'chrome://resources/js/cr/ui/list.m.js';
+// #import {dispatchSimpleEvent} from 'chrome://resources/js/cr.m.js';
+// clang-format on
+
+
 cr.define('cr.ui', function() {
   /**
    * Creates a new autocomplete list popup.
    * @extends {cr.ui.List}
    */
-  class AutocompleteList extends cr.ui.List {
+  /* #export */ class AutocompleteList extends cr.ui.List {
     constructor() {
       super();
       this.__proto__ = AutocompleteList.prototype;
@@ -219,5 +229,6 @@
   }
   AutocompleteList.prototype.__proto__ = cr.ui.List.prototype;
 
+  // #cr_define_end
   return {AutocompleteList: AutocompleteList};
 });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/banners.js b/ui/file_manager/file_manager/foreground/js/ui/banners.js
index bd2c6669..71e94e9 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/banners.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/banners.js
@@ -2,6 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {VolumeInfo} from '../../../../externs/volume_info.m.js';
+// #import {VolumeManager} from '../../../../externs/volume_manager.m.js';
+// #import {DirectoryModel} from '../directory_model.m.js';
+// #import {VolumeManagerCommon} from '../../../../base/js/volume_manager_types.m.js';
+// #import {constants} from '../constants.m.js';
+// #import {HoldingSpaceUtil} from '../holding_space_util.m.js';
+// #import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
+// #import {util, str, strf} from '../../../common/js/util.m.js';
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// #import {dispatchSimpleEvent} from 'chrome://resources/js/cr.m.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// clang-format on
+
+
 /**
  * Key in localStorage to keep number of times the Drive Welcome
  * banner has shown.
@@ -76,7 +91,7 @@
  *  - WelcomeBanner
  *  - AuthFailBanner
  */
-class Banners extends cr.EventTarget {
+/* #export */ class Banners extends cr.EventTarget {
   /**
    * @param {DirectoryModel} directoryModel The model.
    * @param {!VolumeManager} volumeManager The manager.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
index fd79e8d..fe9fe97 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb.js
@@ -180,7 +180,7 @@
 /**
  * Class BreadCrumb.
  */
-class BreadCrumb extends HTMLElement {
+/* #export */ class BreadCrumb extends HTMLElement {
   constructor() {
     /**
      * Create element content.
@@ -449,7 +449,8 @@
     }
 
     // Show drop-down below the elider button.
-    const menu = this.shadowRoot.querySelector('cr-action-menu');
+    const menu = /** @type {!CrActionMenuElement} */ (
+        this.shadowRoot.querySelector('cr-action-menu'));
     const top = elider.offsetTop + elider.offsetHeight + 8;
     !window.UNIT_TEST && menu.showAt(elider, {top: top});
 
diff --git a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js
similarity index 93%
rename from ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.js
rename to ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js
index dea05f0..ebfc1b6 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/breadcrumb_unittest.m.js
@@ -2,7 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-'use strict';
+import {assert} from 'chrome://resources/js/assert.m.js';
+import {assertEquals, assertFalse, assertNotEquals, assertTrue} from 'chrome://test/chai_assert.js';
+
+import {BreadCrumb} from './breadcrumb.m.js';
 
 /** @const {boolean} */
 window.UNIT_TEST = true;
@@ -11,7 +14,7 @@
  * Creates new <bread-drumb> element for each test. Asserts it has no initial
  * path using the element.path getter.
  */
-function setUp() {
+export function setUp() {
   document.body.innerHTML = '<bread-crumb></bread-crumb>';
   const path = assert(document.querySelector('bread-crumb')).path;
   assertEquals('', path);
@@ -19,13 +22,13 @@
 
 /**
  * Returns the <bread-crumb> element.
- * @return {!BreadCrumb|!Element}
+ * @return {!BreadCrumb}
  */
 function getBreadCrumb() {
   const element = assert(document.querySelector('bread-crumb'));
-  assertNotEqual('none', window.getComputedStyle(element).display);
+  assertNotEquals('none', window.getComputedStyle(element).display);
   assertFalse(element.hasAttribute('hidden'));
-  return element;
+  return /** @type {!BreadCrumb} */ (element);
 }
 
 /**
@@ -66,7 +69,7 @@
   const elider = 'button[elider]';
   const button = getBreadCrumb().shadowRoot.querySelectorAll(elider);
   assert(button) && assert(button.length === 1, 'invalid elider button');
-  return button[0];
+  return /** @type {!HTMLButtonElement} */ (button[0]);
 }
 
 /**
@@ -189,7 +192,7 @@
 /**
  * Tests rendering an empty path.
  */
-function testBreadcrumbEmptyPath() {
+export function testBreadcrumbEmptyPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -211,7 +214,7 @@
 /**
  * Tests rendering a one element path.
  */
-function testBreadcrumbOnePartPath() {
+export function testBreadcrumbOnePartPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -233,7 +236,7 @@
 /**
  * Tests rendering a two element path.
  */
-function testBreadcrumbTwoPartPath() {
+export function testBreadcrumbTwoPartPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -255,7 +258,7 @@
 /**
  * Tests rendering a three element path.
  */
-function testBreadcrumbThreePartPath() {
+export function testBreadcrumbThreePartPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -277,7 +280,7 @@
 /**
  * Tests rendering a four element path.
  */
-function testBreadcrumbFourPartPath() {
+export function testBreadcrumbFourPartPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -303,7 +306,7 @@
  * The drop-down menu button should contain the elided path parts and can have
  * display, but are invisible because the elider drop-down menu is closed.
  */
-function testBreadcrumbMoreThanFourElementPathsElide() {
+export function testBreadcrumbMoreThanFourElementPathsElide() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -337,7 +340,7 @@
  * The drop-down menu button should contain the elided path parts and can have
  * display, but are invisible because the elider drop-down menu is closed.
  */
-function testBreadcrumbRendersEscapedPathParts() {
+export function testBreadcrumbRendersEscapedPathParts() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -367,7 +370,7 @@
  * Tests rendering a path of more than four parts. The elider button should be
  * visible and clicking it should 'open' and 'close' its drop-down menu.
  */
-function testBreadcrumbElidedPathEliderButtonClicksOpenDropDownMenu() {
+export function testBreadcrumbElidedPathEliderButtonClicksOpenDropDownMenu() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -419,7 +422,7 @@
  * Tests that clicking on the main buttons emits a signal that indicates which
  * part of the breadcrumb path was clicked.
  */
-async function testBreadcrumbMainButtonClicksEmitNumberSignal(done) {
+export async function testBreadcrumbMainButtonClicksEmitNumberSignal(done) {
   const element = getBreadCrumb();
 
   // Set path.
@@ -475,7 +478,7 @@
  * Tests that clicking on the menu buttons emits a signal that indicates which
  * part of the breadcrumb path was clicked.
  */
-async function testBreadcrumbMenuButtonClicksEmitNumberSignal(done) {
+export async function testBreadcrumbMenuButtonClicksEmitNumberSignal(done) {
   const element = getBreadCrumb();
 
   // Set path.
@@ -533,7 +536,7 @@
  * Tests that setting the path emits a signal when the rendering of the new
  * path begins, and when it ends.
  */
-async function testBreadcrumbSetPathEmitsRenderSignals(done) {
+export async function testBreadcrumbSetPathEmitsRenderSignals(done) {
   const element = getBreadCrumb();
 
   // Set the BreadCrumb signals callback.
@@ -559,7 +562,7 @@
  * Tests that opening the elider button drop-down menu emits a render signal
  * to indicate that the elided menu items were rendered.
  */
-async function testBreadcrumbEliderButtonOpenEmitsRenderSignal(done) {
+export async function testBreadcrumbEliderButtonOpenEmitsRenderSignal(done) {
   const element = getBreadCrumb();
 
   // Set path.
@@ -591,7 +594,7 @@
 /**
  * Tests that setting the path closes the the drop-down menu.
  */
-function testBreadcrumbSetPathClosesEliderButtonDropDownMenu() {
+export function testBreadcrumbSetPathClosesEliderButtonDropDownMenu() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -640,7 +643,7 @@
 /**
  * Tests that setting the path updates the <bread-crumb path> attribute.
  */
-function testBreadcrumbSetPathChangesElementPath() {
+export function testBreadcrumbSetPathChangesElementPath() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -656,7 +659,7 @@
  * Tests that opening and closing the elider button drop-down menu adds and
  * removes <bread-crumb checked> attribute.
  */
-function testBreadcrumbEliderButtonOpenCloseChangesElementChecked() {
+export function testBreadcrumbEliderButtonOpenCloseChangesElementChecked() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -685,7 +688,7 @@
  * Tests that opening and closing the elider button drop-down menu adds and
  * removes global <html> element state.
  */
-function testBreadcrumbEliderButtonOpenCloseChangesGlobalState() {
+export function testBreadcrumbEliderButtonOpenCloseChangesGlobalState() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -719,7 +722,7 @@
  * Tests that wide text path components are rendered elided with ellipsis ...
  * an opportunity for adding a tooltip.
  */
-function testBreadcrumbPartPartsEllipsisElide() {
+export function testBreadcrumbPartPartsEllipsisElide() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -756,7 +759,7 @@
  * Tests that wide text path components in the drop-down menu are rendered
  * elided with ellipsis ... an opportunity for adding a tooltip.
  */
-function testBreadcrumbDropDownMenuPathPartsEllipsisElide() {
+export function testBreadcrumbDropDownMenuPathPartsEllipsisElide() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -796,7 +799,7 @@
  * Tests that breadcrumb getToolTipButtons() service returns all buttons that
  * have a [has-tooltip] attribute.
  */
-function testBreadcrumbButtonHasToolTipAttribute() {
+export function testBreadcrumbButtonHasToolTipAttribute() {
   const element = getBreadCrumb();
 
   // Set path.
@@ -848,6 +851,6 @@
   element.path = elider.getAttribute('aria-label');
   const ellipsis = element.getEllipsisButtons();
   assertEquals(getVisibleBreadCrumbMainButtons()[0], ellipsis[0]);
-  assertNotEqual(elider, ellipsis[0]);
+  assertNotEquals(elider, ellipsis[0]);
   assertEquals(1, ellipsis.length);
 }
diff --git a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
index 61a7ab5..6d78c18 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/gear_menu.js
@@ -2,7 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-class GearMenu {
+// #import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+// #import {str, util, strf} from '../../../common/js/util.m.js';
+// #import {assertInstanceof} from 'chrome://resources/js/assert.m.js';
+// #import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
+
+/* #export */ class GearMenu {
   /**
    * @param {!HTMLElement} element
    */
diff --git a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
index eaaeb387..f7cb772 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/import_crostini_image_dialog.js
@@ -2,6 +2,9 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {str, util} from '../../../common/js/util.m.js';
+// #import {ConfirmDialog} from 'chrome://resources/js/cr/ui/dialogs.m.js';
+
 /**
  * ImportCrostiniImageDialog is used as the handler for .tini files.
  */
@@ -9,7 +12,8 @@
   /**
    * Creates dialog in DOM.
    */
-  class ImportCrostiniImageDialog extends cr.ui.dialogs.ConfirmDialog {
+  /* #export */ class ImportCrostiniImageDialog extends
+      cr.ui.dialogs.ConfirmDialog {
     /**
      * @param {HTMLElement} parentNode Node to be parent for this dialog.
      */
@@ -35,5 +39,6 @@
     }
   }
 
+  // #cr_define_end
   return {ImportCrostiniImageDialog};
 });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js
index 72f4410f..12faccc 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog.js
@@ -2,6 +2,10 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {str} from '../../../common/js/util.m.js';
+// #import {FileManagerDialogBase} from './file_manager_dialog_base.m.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+
 /**
  * InstallLinuxPackageDialog is used as the handler for .deb files.
  */
@@ -9,7 +13,7 @@
   /**
    * Creates dialog in DOM tree.
    */
-  class InstallLinuxPackageDialog extends FileManagerDialogBase {
+  /* #export */ class InstallLinuxPackageDialog extends FileManagerDialogBase {
     /**
      * @param {HTMLElement} parentNode Node to be parent for this dialog.
      */
@@ -196,5 +200,6 @@
     }
   }
 
+  // #cr_define_end
   return {InstallLinuxPackageDialog: InstallLinuxPackageDialog};
 });
diff --git a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js
similarity index 70%
rename from ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
rename to ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js
index 6f1778c..36cd935 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/install_linux_package_dialog_unittest.m.js
@@ -2,7 +2,13 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-function testInstallButtonHiddenUntilInfoReady() {
+import {assertInstanceof} from 'chrome://resources/js/assert.m.js';
+import {loadTimeData} from 'chrome://resources/js/load_time_data.m.js';
+import {assertFalse, assertTrue} from 'chrome://test/chai_assert.js';
+
+import {InstallLinuxPackageDialog} from './install_linux_package_dialog.m.js';
+
+export function testInstallButtonHiddenUntilInfoReady() {
   // Polyfill chrome.app.window.current().
   /** @suppress {checkTypes,const} */
   chrome.app = {window: {current: () => null}};
@@ -20,7 +26,7 @@
       assertInstanceof(document.createElement('div'), HTMLElement);
 
   const info = {name: 'n', version: 'v', info: 'i', summary: 's'};
-  const dialog = new cr.filebrowser.InstallLinuxPackageDialog(container);
+  const dialog = new InstallLinuxPackageDialog(container);
 
   // Show dialog and very that install button is disabled.
   dialog.showInstallLinuxPackageDialog(/** @type {!Entry} */ ({}));
diff --git a/ui/file_manager/file_manager/foreground/js/ui/location_line.js b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
index 75f244dd..bd8bd05 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/location_line.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/location_line.js
@@ -2,10 +2,21 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {FakeEntry} from '../../../../externs/files_app_entry_interfaces.m.js';
+// #import {FilesTooltip} from '../../elements/files_tooltip.m.js';
+// #import {ListContainer} from './list_container.m.js';
+// #import {VolumeManager} from '../../../../externs/volume_manager.m.js';
+// #import {util} from '../../../common/js/util.m.js';
+// #import {PathComponent} from '../path_component.m.js';
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// #import {metrics} from '../../../common/js/metrics.m.js';
+// clang-format on
+
 /**
  * Location line.
  */
-class LocationLine extends cr.EventTarget {
+/* #export */ class LocationLine extends cr.EventTarget {
   /**
    * @param {!Element} breadcrumbs Container element for breadcrumbs.
    * @param {!VolumeManager} volumeManager Volume manager.
diff --git a/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js b/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
index 1b42e6d7..5ae400a 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/providers_menu.js
@@ -2,10 +2,17 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// #import {Menu} from 'chrome://resources/js/cr/ui/menu.m.js';
+// #import {ProvidersModel} from '../providers_model.m.js';
+// #import {util} from '../../../common/js/util.m.js';
+// #import {FilesMenuItem} from './files_menu.m.js';
+// #import {decorate} from 'chrome://resources/js/cr/ui.m.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+
 /**
  * Fills out the menu for mounting or installing new providers.
  */
-class ProvidersMenu {
+/* #export */ class ProvidersMenu {
   /**
    * @param {!ProvidersModel} model
    * @param {!cr.ui.Menu} menu
diff --git a/ui/file_manager/file_manager/foreground/js/ui/search_box.js b/ui/file_manager/file_manager/foreground/js/ui/search_box.js
index c194c0ca..dc2b881 100644
--- a/ui/file_manager/file_manager/foreground/js/ui/search_box.js
+++ b/ui/file_manager/file_manager/foreground/js/ui/search_box.js
@@ -2,10 +2,23 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+// clang-format off
+// #import {FileType} from '../../../common/js/file_type.m.js';
+// #import {strf, util} from '../../../common/js/util.m.js';
+// #import {ListItem} from 'chrome://resources/js/cr/ui/list_item.m.js';
+// #import {queryRequiredElement} from 'chrome://resources/js/util.m.js';
+// #import {NativeEventTarget as EventTarget} from 'chrome://resources/js/cr/event_target.m.js';
+// #import {metrics} from '../../common/js/metrics.m.js';
+// #import {dispatchSimpleEvent} from 'chrome://resources/js/cr.m.js';
+// #import {AutocompleteList} from './autocomplete_list.m.js';
+// #import {assert} from 'chrome://resources/js/assert.m.js';
+// #import '../../elements/files_toggle_ripple.m.js';
+// clang-format on
+
 /**
  * Search box.
  */
-class SearchBox extends cr.EventTarget {
+/* #export */ class SearchBox extends cr.EventTarget {
   /**
    * @param {!Element} element Root element of the search box.
    * @param {!Element} searchWrapper Wrapper element around the buttons and box.
@@ -79,8 +92,9 @@
         'click', this.onSearchButtonClick_.bind(this));
     this.clearButton_.addEventListener(
         'click', this.onClearButtonClick_.bind(this));
-    const dispatchItemSelect =
-        cr.dispatchSimpleEvent.bind(cr, this, SearchBox.EventType.ITEM_SELECT);
+    const dispatchItemSelect = () => {
+      cr.dispatchSimpleEvent(this, SearchBox.EventType.ITEM_SELECT);
+    };
     this.autocompleteList.handleEnterKeydown = dispatchItemSelect;
     this.autocompleteList.addEventListener('mousedown', dispatchItemSelect);
 
@@ -314,8 +328,7 @@
 /**
  * Autocomplete list for search box.
  */
-SearchBox.AutocompleteList =
-    class AutocompleteList extends cr.ui.AutocompleteList {
+SearchBox.AutocompleteList = class extends cr.ui.AutocompleteList {
   /**
    * @param {Document} document Document.
    */
diff --git a/ui/message_center/views/notification_control_buttons_view.cc b/ui/message_center/views/notification_control_buttons_view.cc
index 796a71c..2844ead 100644
--- a/ui/message_center/views/notification_control_buttons_view.cc
+++ b/ui/message_center/views/notification_control_buttons_view.cc
@@ -20,12 +20,10 @@
 #include "ui/strings/grit/ui_strings.h"
 #include "ui/views/background.h"
 #include "ui/views/layout/box_layout.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
 
 namespace message_center {
 
-const char NotificationControlButtonsView::kViewClassName[] =
-    "NotificationControlButtonsView";
-
 NotificationControlButtonsView::NotificationControlButtonsView(
     MessageView* message_view)
     : message_view_(message_view), icon_color_(gfx::kChromeIconGrey) {
@@ -146,10 +144,6 @@
   UpdateButtonIconColors();
 }
 
-const char* NotificationControlButtonsView::GetClassName() const {
-  return kViewClassName;
-}
-
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 void NotificationControlButtonsView::OnThemeChanged() {
   View::OnThemeChanged();
@@ -184,4 +178,7 @@
   return color_utils::BlendForMinContrast(icon_color_, background_color_).color;
 }
 
+BEGIN_METADATA(NotificationControlButtonsView, views::View)
+END_METADATA
+
 }  // namespace message_center
diff --git a/ui/message_center/views/notification_control_buttons_view.h b/ui/message_center/views/notification_control_buttons_view.h
index 97822be6..162f7204 100644
--- a/ui/message_center/views/notification_control_buttons_view.h
+++ b/ui/message_center/views/notification_control_buttons_view.h
@@ -20,10 +20,13 @@
 class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
     : public views::View {
  public:
-  // String to be returned by GetClassName() method.
-  static const char kViewClassName[];
+  METADATA_HEADER(NotificationControlButtonsView);
 
   explicit NotificationControlButtonsView(MessageView* message_view);
+  NotificationControlButtonsView(const NotificationControlButtonsView&) =
+      delete;
+  NotificationControlButtonsView& operator=(
+      const NotificationControlButtonsView&) = delete;
   ~NotificationControlButtonsView() override;
 
   // Change the visibility of the close button. True to show, false to hide.
@@ -51,8 +54,6 @@
   PaddedButton* settings_button() { return settings_button_; }
   PaddedButton* snooze_button() { return snooze_button_; }
 
-  // views::View
-  const char* GetClassName() const override;
 #if BUILDFLAG(IS_CHROMEOS_ASH)
   void OnThemeChanged() override;
 #endif
@@ -75,8 +76,6 @@
   SkColor icon_color_;
   // The background color for readability of the icons.
   SkColor background_color_ = SK_ColorTRANSPARENT;
-
-  DISALLOW_COPY_AND_ASSIGN(NotificationControlButtonsView);
 };
 
 }  // namespace message_center
diff --git a/ui/ozone/platform/wayland/fuzzer/wayland_buffer_fuzzer.cc b/ui/ozone/platform/wayland/fuzzer/wayland_buffer_fuzzer.cc
index 957bf28..42fcba8 100644
--- a/ui/ozone/platform/wayland/fuzzer/wayland_buffer_fuzzer.cc
+++ b/ui/ozone/platform/wayland/fuzzer/wayland_buffer_fuzzer.cc
@@ -12,11 +12,15 @@
 #include <memory>
 #include <vector>
 
+#include "base/at_exit.h"
+#include "base/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
 #include "base/message_loop/message_pump_type.h"
+#include "base/no_destructor.h"
 #include "base/task/single_thread_task_executor.h"
+#include "base/test/icu_test_util.h"
 #include "base/test/mock_callback.h"
 #include "base/test/task_environment.h"
 #include "base/test/test_timeouts.h"
@@ -35,8 +39,7 @@
 
 namespace {
 
-using MockTerminateGpuCallback =
-    base::MockCallback<base::OnceCallback<void(std::string)>>;
+using TerminateGpuCallback = base::OnceCallback<void(std::string)>;
 
 // Copied from ui/ozone/test/mock_platform_window_delegate.h to avoid
 // dependency from the whole library (it causes link problems).
@@ -73,18 +76,33 @@
     mojo::core::Init();
   }
 
+  void SetTerminateGpuCallback(ui::WaylandBufferManagerHost* host) {
+    DCHECK(host);
+    host->SetTerminateGpuCallback(base::BindOnce(
+        &Environment::OnTerminateCallbackFired, base::Unretained(this)));
+  }
+
+  void OnTerminateCallbackFired(std::string message) { terminated = true; }
+
   base::test::TaskEnvironment task_environment;
-  MockTerminateGpuCallback callback_;
+  bool terminated = false;
 };
 
 }  // namespace
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
   static Environment env;
+  DCHECK(!env.terminated);
+
+  // Required for ICU initialization.
+  static base::NoDestructor<base::AtExitManager> exit_manager;
   FuzzedDataProvider data_provider(data, size);
 
   base::CommandLine::Init(0, nullptr);
 
+  // Required for base::FormatNumber that WaylandBufferManagerHost uses.
+  base::test::InitializeICUForTesting();
+
   std::vector<uint32_t> known_fourccs{
       DRM_FORMAT_R8,          DRM_FORMAT_GR88,        DRM_FORMAT_ABGR8888,
       DRM_FORMAT_XBGR8888,    DRM_FORMAT_ARGB8888,    DRM_FORMAT_XRGB8888,
@@ -148,9 +166,8 @@
 
   const uint32_t kBufferId = 1;
 
-  EXPECT_CALL(*server.zwp_linux_dmabuf_v1(), CreateParams(_, _, _));
   auto* manager_host = connection->buffer_manager_host();
-  manager_host->SetTerminateGpuCallback(env.callback_.Get());
+  env.SetTerminateGpuCallback(manager_host);
   manager_host->CreateDmabufBasedBuffer(
       mojo::PlatformHandle(std::move(fd)), buffer_size, strides, offsets,
       modifiers, kFormat, kPlaneCount, kBufferId);
@@ -158,13 +175,20 @@
   // Wait until the buffers are created.
   env.task_environment.RunUntilIdle();
 
-  manager_host->DestroyBuffer(widget, kBufferId);
+  // If the |manager_host| fires the terminate gpu callback, we need to set the
+  // callback again.
+  if (env.terminated)
+    env.SetTerminateGpuCallback(manager_host);
 
+  manager_host->DestroyBuffer(widget, kBufferId);
   // Wait until the buffers are destroyed.
   env.task_environment.RunUntilIdle();
 
   // Pause the server so it is not running when mock expectations are validated.
   server.Pause();
 
+  // Reset the value as |env| is a static object.
+  env.terminated = false;
+
   return 0;
 }
diff --git a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
index 376a1100..db0c2586 100644
--- a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
+++ b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
@@ -75,11 +75,11 @@
       <template is="dom-repeat" items="[[avatars]]">
         <cr-button id="[[getAvatarId_(index)]]"
             aria-label="[[item.label]]"
-            class$="avatar [[getSelectedClass_(item.selected)]]"
+            class$="avatar [[getSelectedClass_(item, selectedAvatar)]]"
             style$="background-image: [[getIconImageSet_(item.url)]]"
             on-click="onAvatarTap_"
             role="radio"
-            aria-checked$="[[getCheckedAttribute_(item.selected)]]">
+            aria-checked$="[[getCheckedAttribute_(item, selectedAvatar)]]">
         </cr-button>
         <paper-tooltip for="[[getAvatarId_(index)]]"
             offset="-12" fit-to-visible-bounds>
diff --git a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
index a677b5e..51115d6 100644
--- a/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
+++ b/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
@@ -40,9 +40,6 @@
       notify: true,
     },
 
-    /** @private {?HTMLElement} */
-    selectedAvatarElement_: Object,
-
     ignoreModifiedKeyEvents: {
       type: Boolean,
       value: false,
@@ -59,19 +56,31 @@
   },
 
   /** @private */
-  getSelectedClass_(isSelected) {
+  getSelectedClass_(avatarItem) {
     // TODO(dpapad): Rename 'iron-selected' to 'selected' now that this CSS
     // class is not assigned by any iron-* behavior.
-    return isSelected ? 'iron-selected' : '';
+    return this.isAvatarSelected(avatarItem) ? 'iron-selected' : '';
   },
 
   /**
-   * @param {boolean} isSelected
+   * @param {AvatarIcon} avatarItem
    * @return {string}
    * @private
    */
-  getCheckedAttribute_(isSelected) {
-    return isSelected ? 'true' : 'false';
+  getCheckedAttribute_(avatarItem) {
+    return this.isAvatarSelected(avatarItem) ? 'true' : 'false';
+  },
+
+  /**
+   * @param {AvatarIcon} avatarItem
+   * @return {boolean}
+   * @private
+   */
+  isAvatarSelected(avatarItem) {
+    return !!avatarItem &&
+        (avatarItem.selected ||
+         (!!this.selectedAvatar &&
+          this.selectedAvatar.index === avatarItem.index));
   },
 
   /**
@@ -88,13 +97,6 @@
    * @private
    */
   onAvatarTap_(e) {
-    // Manual selection for profile creation
-    if (this.selectedAvatarElement_) {
-      this.selectedAvatarElement_.classList.remove('iron-selected');
-    }
-    this.selectedAvatarElement_ = /** @type {!HTMLElement} */ (e.target);
-    this.selectedAvatarElement_.classList.add('iron-selected');
-
     // |selectedAvatar| is set to pass back selection to the owner of this
     // component.
     this.selectedAvatar =
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
index fe24d68..f5838f3 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/WebLayerImpl.java
@@ -312,7 +312,7 @@
                     PhotoPickerListener listener, boolean allowMultiple, List<String> mimeTypes) {
                 PhotoPickerDialog dialog = new PhotoPickerDialog(windowAndroid,
                         windowAndroid.getContext().get().getContentResolver(), listener,
-                        allowMultiple, mimeTypes);
+                        allowMultiple, /* animatedThumbnailsSupported = */ false, mimeTypes);
                 dialog.show();
                 return dialog;
             }
diff --git a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
index 6b3a224..84e9b0dc 100644
--- a/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
+++ b/weblayer/browser/java/org/chromium/weblayer_private/settings/WebLayerSiteSettingsDelegate.java
@@ -142,4 +142,10 @@
     public Set<String> getAllDelegatedNotificationOrigins() {
         return Collections.EMPTY_SET;
     }
+
+    @Override
+    public void maybeDisplayPrivacySandboxSnackbar() {}
+
+    @Override
+    public void dismissPrivacySandboxSnackbar() {}
 }