diff --git a/DEPS b/DEPS index ecb439f..2f12014 100644 --- a/DEPS +++ b/DEPS
@@ -167,7 +167,7 @@ # 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': '2533afa3f8c628f635695047a7922845a68764be', + 'skia_revision': '1ffc2e453b00ec666b6083eb888b8e03b4c2bf72', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling V8 # and whatever else without interference from each other. @@ -183,7 +183,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling SwiftShader # and whatever else without interference from each other. - 'swiftshader_revision': 'a9dc7707d6106b329ed68a5175b3152db28cf6c8', + 'swiftshader_revision': '3044c24181e96187c8c683208693bd9d2f2d4420', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling PDFium # and whatever else without interference from each other. @@ -218,7 +218,7 @@ # Three lines of non-changing comments so that # the commit queue can handle CLs rolling freetype # and whatever else without interference from each other. - 'freetype_revision': '839a023619b593b742f62ffab8e7e4f9da8c1593', + 'freetype_revision': 'c912690d22ab16d772328396c27c47075924b012', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling HarfBuzz # and whatever else without interference from each other. @@ -230,7 +230,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': '5f4659d6f7a8b48728247d88b64abe806ccc6822', + 'catapult_revision': 'ca0d0564630e8e645b06536e91f8ee32ae562a0f', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling libFuzzer # and whatever else without interference from each other. @@ -302,7 +302,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': '55a00c7a1f9a188c5a512af510f8184bbdbad580', + 'dawn_revision': 'deb28ea45d0dd00e52026ae227d856582546ca9d', # Three lines of non-changing comments so that # the commit queue can handle CLs rolling feed # and whatever else without interference from each other. @@ -862,7 +862,7 @@ # Build tools for Chrome OS. Note: This depends on third_party/pyelftools. 'src/third_party/chromite': { - 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + 'c28e7f784c33041b8143fb20f3a5dd904a17387d', + 'url': Var('chromium_git') + '/chromiumos/chromite.git' + '@' + '94a459c0b4c70a4476ce63ebd8d841c9e2a6583e', 'condition': 'checkout_linux', }, @@ -1459,7 +1459,7 @@ Var('chromium_git') + '/external/khronosgroup/webgl.git' + '@' + '7c4e67ff117d6c640e6dd17989afe2fb7da7eecb', 'src/third_party/webrtc': - Var('webrtc_git') + '/src.git' + '@' + '894eb8b0c9ba8aa304eca33465dad3754afdc7e5', + Var('webrtc_git') + '/src.git' + '@' + '2f7d7794719ab33a1ab523e6bcc75d95bd846ff1', 'src/third_party/xdg-utils': { 'url': Var('chromium_git') + '/chromium/deps/xdg-utils.git' + '@' + 'd80274d5869b17b8c9067a1022e4416ee7ed5e0d', @@ -1521,7 +1521,7 @@ Var('chromium_git') + '/v8/v8.git' + '@' + Var('v8_revision'), 'src-internal': { - 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@8c6278001533212c9fdb4624d63947fb177ba304', + 'url': 'https://chrome-internal.googlesource.com/chrome/src-internal.git@a39aa78ade7b5c02c12895f3f96da494405dc13e', 'condition': 'checkout_src_internal', },
diff --git a/ash/assistant/assistant_controller.cc b/ash/assistant/assistant_controller.cc index 7a4eca15..f87ee17 100644 --- a/ash/assistant/assistant_controller.cc +++ b/ash/assistant/assistant_controller.cc
@@ -12,6 +12,7 @@ #include "ash/public/cpp/android_intent_helper.h" #include "ash/public/cpp/ash_pref_names.h" #include "ash/public/cpp/new_window_delegate.h" +#include "ash/public/mojom/assistant_volume_control.mojom.h" #include "ash/session/session_controller_impl.h" #include "ash/shell.h" #include "ash/shell_delegate.h" @@ -21,6 +22,10 @@ #include "chromeos/services/assistant/public/cpp/assistant_prefs.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "components/prefs/pref_registry_simple.h" +#include "mojo/public/cpp/bindings/pending_receiver.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote_set.h" #include "services/content/public/mojom/constants.mojom.h" #include "services/content/public/mojom/navigable_contents_factory.mojom.h" #include "services/service_manager/public/cpp/connector.h" @@ -34,16 +39,7 @@ } // namespace -AssistantController::AssistantController() - : assistant_volume_control_binding_(this), - assistant_alarm_timer_controller_(this), - assistant_interaction_controller_(this), - assistant_notification_controller_(this), - assistant_screen_context_controller_(this), - assistant_setup_controller_(this), - assistant_suggestions_controller_(this), - assistant_ui_controller_(this), - view_delegate_(this) { +AssistantController::AssistantController() { assistant_state_controller_.AddObserver(this); chromeos::CrasAudioHandler::Get()->AddAudioObserver(this); AddObserver(this); @@ -70,9 +66,9 @@ assistant_controller_bindings_.AddBinding(this, std::move(request)); } -void AssistantController::BindRequest( - mojom::AssistantVolumeControlRequest request) { - assistant_volume_control_binding_.Bind(std::move(request)); +void AssistantController::BindReceiver( + mojo::PendingReceiver<mojom::AssistantVolumeControl> receiver) { + assistant_volume_control_receiver_.Bind(std::move(receiver)); } void AssistantController::AddObserver(AssistantControllerObserver* observer) { @@ -200,8 +196,9 @@ chromeos::CrasAudioHandler::Get()->SetOutputMute(muted); } -void AssistantController::AddVolumeObserver(mojom::VolumeObserverPtr observer) { - volume_observer_.AddPtr(std::move(observer)); +void AssistantController::AddVolumeObserver( + mojo::PendingRemote<mojom::VolumeObserver> observer) { + volume_observers_.Add(std::move(observer)); int output_volume = chromeos::CrasAudioHandler::Get()->GetOutputVolumePercent(); @@ -211,16 +208,14 @@ } void AssistantController::OnOutputMuteChanged(bool mute_on) { - volume_observer_.ForAllPtrs([mute_on](mojom::VolumeObserver* observer) { + for (auto& observer : volume_observers_) observer->OnMuteStateChanged(mute_on); - }); } void AssistantController::OnOutputNodeVolumeChanged(uint64_t node, int volume) { // |node| refers to the active volume device, which we don't care here. - volume_observer_.ForAllPtrs([volume](mojom::VolumeObserver* observer) { + for (auto& observer : volume_observers_) observer->OnVolumeChanged(volume); - }); } void AssistantController::OnAccessibilityStatusChanged() { @@ -371,7 +366,7 @@ void AssistantController::BindVolumeControl( mojo::PendingReceiver<mojom::AssistantVolumeControl> receiver) { - Shell::Get()->assistant_controller()->BindRequest(std::move(receiver)); + Shell::Get()->assistant_controller()->BindReceiver(std::move(receiver)); } base::WeakPtr<AssistantController> AssistantController::GetWeakPtr() {
diff --git a/ash/assistant/assistant_controller.h b/ash/assistant/assistant_controller.h index 853113b8..e0cc241 100644 --- a/ash/assistant/assistant_controller.h +++ b/ash/assistant/assistant_controller.h
@@ -33,9 +33,10 @@ #include "chromeos/services/assistant/public/mojom/assistant.mojom-forward.h" #include "components/prefs/pref_service.h" #include "mojo/public/cpp/bindings/binding_set.h" -#include "mojo/public/cpp/bindings/interface_ptr_set.h" #include "mojo/public/cpp/bindings/pending_receiver.h" #include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote_set.h" #include "services/content/public/mojom/navigable_contents_factory.mojom-forward.h" class PrefRegistrySimple; @@ -67,7 +68,8 @@ void BindRequest( chromeos::assistant::mojom::AssistantControllerRequest request); - void BindRequest(mojom::AssistantVolumeControlRequest request); + void BindReceiver( + mojo::PendingReceiver<mojom::AssistantVolumeControl> receiver); // Adds/removes the specified |observer|. void AddObserver(AssistantControllerObserver* observer); @@ -96,7 +98,8 @@ // mojom::VolumeControl: void SetVolume(int volume, bool user_initiated) override; void SetMuted(bool muted) override; - void AddVolumeObserver(mojom::VolumeObserverPtr observer) override; + void AddVolumeObserver( + mojo::PendingRemote<mojom::VolumeObserver> observer) override; // chromeos::CrasAudioHandler::AudioObserver: void OnOutputMuteChanged(bool mute_on) override; @@ -184,23 +187,23 @@ mojo::BindingSet<chromeos::assistant::mojom::AssistantController> assistant_controller_bindings_; - mojo::Binding<mojom::AssistantVolumeControl> - assistant_volume_control_binding_; - mojo::InterfacePtrSet<mojom::VolumeObserver> volume_observer_; + mojo::Receiver<mojom::AssistantVolumeControl> + assistant_volume_control_receiver_{this}; + mojo::RemoteSet<mojom::VolumeObserver> volume_observers_; chromeos::assistant::mojom::AssistantPtr assistant_; // Assistant sub-controllers. - AssistantAlarmTimerController assistant_alarm_timer_controller_; - AssistantInteractionController assistant_interaction_controller_; - AssistantNotificationController assistant_notification_controller_; + AssistantAlarmTimerController assistant_alarm_timer_controller_{this}; + AssistantInteractionController assistant_interaction_controller_{this}; + AssistantNotificationController assistant_notification_controller_{this}; AssistantStateController assistant_state_controller_; - AssistantScreenContextController assistant_screen_context_controller_; - AssistantSetupController assistant_setup_controller_; - AssistantSuggestionsController assistant_suggestions_controller_; - AssistantUiController assistant_ui_controller_; + AssistantScreenContextController assistant_screen_context_controller_{this}; + AssistantSetupController assistant_setup_controller_{this}; + AssistantSuggestionsController assistant_suggestions_controller_{this}; + AssistantUiController assistant_ui_controller_{this}; - AssistantViewDelegateImpl view_delegate_; + AssistantViewDelegateImpl view_delegate_{this}; base::WeakPtrFactory<AssistantController> weak_factory_{this};
diff --git a/ash/public/mojom/assistant_volume_control.mojom b/ash/public/mojom/assistant_volume_control.mojom index e8bf405..a3660bec 100644 --- a/ash/public/mojom/assistant_volume_control.mojom +++ b/ash/public/mojom/assistant_volume_control.mojom
@@ -14,7 +14,7 @@ // Adds volume observer. The observer will be immediately notified of volume // and mute status when added. - AddVolumeObserver(VolumeObserver observer); + AddVolumeObserver(pending_remote<VolumeObserver> observer); }; // Observes volume state changes.
diff --git a/build/fuchsia/linux.sdk.sha1 b/build/fuchsia/linux.sdk.sha1 index ef3c1a2..0a90208c 100644 --- a/build/fuchsia/linux.sdk.sha1 +++ b/build/fuchsia/linux.sdk.sha1
@@ -1 +1 @@ -8900963580510499440 \ No newline at end of file +8900825675210164352 \ No newline at end of file
diff --git a/build/fuchsia/mac.sdk.sha1 b/build/fuchsia/mac.sdk.sha1 index 2997a23..58dae98 100644 --- a/build/fuchsia/mac.sdk.sha1 +++ b/build/fuchsia/mac.sdk.sha1
@@ -1 +1 @@ -8900963579521722560 \ No newline at end of file +8900825674754076848 \ No newline at end of file
diff --git a/chrome/VERSION b/chrome/VERSION index e8431bae..de3fe2e 100644 --- a/chrome/VERSION +++ b/chrome/VERSION
@@ -1,4 +1,4 @@ MAJOR=79 MINOR=0 -BUILD=3929 +BUILD=3930 PATCH=0
diff --git a/chrome/android/features/keyboard_accessory/BUILD.gn b/chrome/android/features/keyboard_accessory/BUILD.gn index 1c5b254e..bad4404 100644 --- a/chrome/android/features/keyboard_accessory/BUILD.gn +++ b/chrome/android/features/keyboard_accessory/BUILD.gn
@@ -32,10 +32,11 @@ java_files = [ "javatests/src/org/chromium/chrome/browser/keyboard_accessory/AutofillKeyboardAccessoryIntegrationTest.java", + "javatests/src/org/chromium/chrome/browser/keyboard_accessory/FakeKeyboard.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingUiCaptureTest.java", - "javatests/src/org/chromium/chrome/browser/keyboard_accessory/FakeKeyboard.java", + "javatests/src/org/chromium/chrome/browser/keyboard_accessory/PasswordGenerationIntegrationTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryViewTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/bar_component/KeyboardAccessoryModernViewTest.java", "javatests/src/org/chromium/chrome/browser/keyboard_accessory/sheet_component/AccessorySheetViewTest.java",
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java index 5715e77..4c6ab4e 100644 --- a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/ManualFillingTestHelper.java
@@ -38,7 +38,7 @@ import org.junit.Assert; import org.chromium.base.task.PostTask; -import org.chromium.chrome.browser.ChromeTabbedActivity; +import org.chromium.chrome.browser.ChromeActivity; import org.chromium.chrome.browser.ChromeWindow; import org.chromium.chrome.browser.autofill.AutofillTestHelper; import org.chromium.chrome.browser.autofill.PersonalDataManager.AutofillProfile; @@ -49,7 +49,7 @@ import org.chromium.chrome.browser.keyboard_accessory.sheet_tabs.AddressAccessorySheetCoordinator; import org.chromium.chrome.browser.keyboard_accessory.sheet_tabs.CreditCardAccessorySheetCoordinator; import org.chromium.chrome.browser.keyboard_accessory.sheet_tabs.PasswordAccessorySheetCoordinator; -import org.chromium.chrome.test.ChromeTabbedActivityTestRule; +import org.chromium.chrome.test.ChromeActivityTestRule; import org.chromium.content_public.browser.ImeAdapter; import org.chromium.content_public.browser.UiThreadTaskTraits; import org.chromium.content_public.browser.WebContents; @@ -73,7 +73,7 @@ private static final String USERNAME_NODE_ID = "username_field"; private static final String SUBMIT_NODE_ID = "input_submit_button"; - private final ChromeTabbedActivityTestRule mActivityTestRule; + private final ChromeActivityTestRule mActivityTestRule; private final AtomicReference<WebContents> mWebContentsRef = new AtomicReference<>(); private TestInputMethodManagerWrapper mInputMethodManagerWrapper; private PropertyProvider<AccessorySheetData> mSheetSuggestionsProvider = @@ -85,7 +85,7 @@ return (FakeKeyboard) mActivityTestRule.getKeyboardDelegate(); } - public ManualFillingTestHelper(ChromeTabbedActivityTestRule activityTestRule) { + public ManualFillingTestHelper(ChromeActivityTestRule activityTestRule) { mActivityTestRule = activityTestRule; } @@ -106,7 +106,7 @@ mActivityTestRule.startMainActivityWithURL(mEmbeddedTestServer.getURL(url)); setRtlForTesting(isRtl); TestThreadUtils.runOnUiThreadBlocking(() -> { - ChromeTabbedActivity activity = mActivityTestRule.getActivity(); + ChromeActivity activity = mActivityTestRule.getActivity(); mWebContentsRef.set(activity.getActivityTab().getWebContents()); getManualFillingCoordinator().getMediatorForTesting().setInsetObserverViewSupplier( () @@ -283,7 +283,6 @@ && popup.getListView().getHeight() != 0; } }); - return popup; } @@ -447,12 +446,28 @@ return onView(matcher); } + public ViewInteraction waitForViewOnRoot(View root, Matcher<View> matcher) { + waitForView((ViewGroup) root, allOf(matcher, isDisplayed())); + return onView(matcher); + } + + public ViewInteraction waitForViewOnActivityRoot(Matcher<View> matcher) { + return waitForViewOnRoot( + mActivityTestRule.getActivity().findViewById(android.R.id.content).getRootView(), + matcher); + } + public static void waitToBeHidden(Matcher<View> matcher) { onView(isRoot()).check((r, e) -> { waitForView((ViewGroup) r, matcher, VIEW_INVISIBLE | VIEW_NULL | VIEW_GONE); }); } + public String getAttribute(String node, String attribute) + throws InterruptedException, TimeoutException { + return DOMUtils.getNodeAttribute(attribute, mWebContentsRef.get(), node, String.class); + } + // -------------------------------------------- // Helpers that force override the native side. // TODO(fhorschig): Search alternatives.
diff --git a/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/PasswordGenerationIntegrationTest.java b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/PasswordGenerationIntegrationTest.java new file mode 100644 index 0000000..6d32ac2 --- /dev/null +++ b/chrome/android/features/keyboard_accessory/javatests/src/org/chromium/chrome/browser/keyboard_accessory/PasswordGenerationIntegrationTest.java
@@ -0,0 +1,214 @@ +// Copyright 2019 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.keyboard_accessory; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.ViewMatchers.isDescendantOfA; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; + +import static org.hamcrest.core.AllOf.allOf; + +import static org.chromium.chrome.R.id.password_generation_dialog; +import static org.chromium.chrome.browser.keyboard_accessory.ManualFillingTestHelper.selectTabAtPosition; + +import android.view.Window; +import android.widget.TextView; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; + +import org.chromium.base.test.util.CommandLineFlags; +import org.chromium.base.test.util.IntegrationTest; +import org.chromium.chrome.browser.ChromeSwitches; +import org.chromium.chrome.browser.infobar.InfoBarContainer; +import org.chromium.chrome.browser.modaldialog.AppModalPresenter; +import org.chromium.chrome.browser.sync.SyncTestRule; +import org.chromium.chrome.test.ChromeJUnit4ClassRunner; +import org.chromium.content_public.browser.test.util.CriteriaHelper; +import org.chromium.content_public.browser.test.util.DOMUtils; +import org.chromium.content_public.browser.test.util.TestThreadUtils; +import org.chromium.ui.widget.ButtonCompat; + +import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicReference; + +/** + * Integration tests for password generation. + */ +@RunWith(ChromeJUnit4ClassRunner.class) +@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE, "show-autofill-signatures"}) +public class PasswordGenerationIntegrationTest { + @Rule + public SyncTestRule mSyncTestRule = new SyncTestRule(); + + private static final String PASSWORD_NODE_ID = "password_field"; + private static final String PASSWORD_NODE_ID_MANUAL = "password_field_manual"; + private static final String SUBMIT_NODE_ID = "input_submit_button"; + private static final String SUBMIT_NODE_ID_MANUAL = "input_submit_button_manual"; + private static final String FORM_URL = + "/chrome/test/data/password/filled_simple_signup_form.html"; + private static final String PASSWORD_ATTRIBUTE_NAME = "password_creation_field"; + private static final String ELIGIBLE_FOR_GENERATION = "1"; + private static final String INFOBAR_MESSAGE = "Password saved"; + + private final ManualFillingTestHelper mHelper = new ManualFillingTestHelper(mSyncTestRule); + + @Before + public void setUp() throws InterruptedException { + mSyncTestRule.setUpTestAccountAndSignIn(); + mHelper.loadTestPage(FORM_URL, false); + } + + @After + public void tearDown() { + mHelper.clear(); + } + + @Test + @IntegrationTest + public void testAutomaticGenerationCancel() throws InterruptedException, TimeoutException { + waitForGenerationLabel(); + focusField(PASSWORD_NODE_ID); + mHelper.waitForKeyboardAccessoryToBeShown(true); + TestThreadUtils.runOnUiThreadBlocking(() -> { + ButtonCompat suggestStrongPassword = + (ButtonCompat) mHelper.getFirstAccessorySuggestion(); + Assert.assertNotNull(suggestStrongPassword); + suggestStrongPassword.performClick(); + }); + waitForGenerationDialog(); + onView(withId(R.id.negative_button)).perform(click()); + assertPasswordTextEmpty(PASSWORD_NODE_ID); + assertNoInfobarsAreShown(); + } + + @Test + @IntegrationTest + public void testManualGenerationCancel() throws InterruptedException, TimeoutException { + waitForGenerationLabel(); + focusField(PASSWORD_NODE_ID_MANUAL); + mHelper.waitForKeyboardAccessoryToBeShown(); + toggleAccessorySheet(); + pressManualGenerationSuggestion(); + waitForGenerationDialog(); + onView(withId(R.id.negative_button)).perform(click()); + assertPasswordTextEmpty(PASSWORD_NODE_ID_MANUAL); + assertNoInfobarsAreShown(); + } + + @Test + @IntegrationTest + public void testAutomaticGenerationUsePassword() throws InterruptedException, TimeoutException { + waitForGenerationLabel(); + focusField(PASSWORD_NODE_ID); + mHelper.waitForKeyboardAccessoryToBeShown(true); + TestThreadUtils.runOnUiThreadBlocking(() -> { + ButtonCompat suggestStrongPassword = + (ButtonCompat) mHelper.getFirstAccessorySuggestion(); + Assert.assertNotNull(suggestStrongPassword); + suggestStrongPassword.performClick(); + }); + waitForGenerationDialog(); + String generatedPassword = getTextFromTextView(R.id.generated_password); + onView(withId(R.id.positive_button)).perform(click()); + assertPasswordText(PASSWORD_NODE_ID, generatedPassword); + clickNode(SUBMIT_NODE_ID); + mHelper.waitForViewOnActivityRoot(withId(R.id.infobar_message)) + .check(matches(withText(INFOBAR_MESSAGE))); + } + + @Test + @IntegrationTest + public void testManualGenerationUsePassword() throws InterruptedException, TimeoutException { + waitForGenerationLabel(); + focusField(PASSWORD_NODE_ID_MANUAL); + mHelper.waitForKeyboardAccessoryToBeShown(); + toggleAccessorySheet(); + pressManualGenerationSuggestion(); + waitForGenerationDialog(); + String generatedPassword = getTextFromTextView(R.id.generated_password); + onView(withId(R.id.positive_button)).perform(click()); + assertPasswordText(PASSWORD_NODE_ID_MANUAL, generatedPassword); + clickNode(SUBMIT_NODE_ID_MANUAL); + mHelper.waitForViewOnActivityRoot(withId(R.id.infobar_message)) + .check(matches(withText(INFOBAR_MESSAGE))); + } + + public void pressManualGenerationSuggestion() { + onView(allOf(isDescendantOfA(withId(R.id.passwords_sheet)), + withText(R.string.password_generation_accessory_button))) + .perform(click()); + } + + public void toggleAccessorySheet() { + mHelper.waitForViewOnActivityRoot(withId(R.id.tabs)).perform(selectTabAtPosition(0)); + } + + public void focusField(String node) throws TimeoutException, InterruptedException { + DOMUtils.focusNode(mHelper.getWebContents(), node); + TestThreadUtils.runOnUiThreadBlocking( + () -> { mHelper.getWebContents().scrollFocusedEditableNodeIntoView(); }); + } + + public void clickNode(String node) throws InterruptedException, TimeoutException { + DOMUtils.clickNode(mHelper.getWebContents(), node); + } + + private void assertPasswordTextEmpty(String passwordNode) + throws InterruptedException, TimeoutException { + assertPasswordText(passwordNode, ""); + } + + private void assertPasswordText(String passwordNode, String text) + throws InterruptedException, TimeoutException { + Assert.assertEquals(mHelper.getFieldText(passwordNode), text); + } + + private void waitForGenerationLabel() { + CriteriaHelper.pollInstrumentationThread(() -> { + String attribute = mHelper.getAttribute(PASSWORD_NODE_ID, PASSWORD_ATTRIBUTE_NAME); + return attribute.equals(ELIGIBLE_FOR_GENERATION); + }); + } + + private void waitForGenerationDialog() { + waitForModalDialogPresenter(); + Window window = ((AppModalPresenter) mSyncTestRule.getActivity() + .getModalDialogManager() + .getCurrentPresenterForTest()) + .getWindow(); + mHelper.waitForViewOnRoot( + window.getDecorView().getRootView(), withId(password_generation_dialog)); + } + + private void waitForModalDialogPresenter() { + CriteriaHelper.pollUiThread(() + -> mSyncTestRule.getActivity() + .getModalDialogManager() + .getCurrentPresenterForTest() + != null); + } + + private void assertNoInfobarsAreShown() { + TestThreadUtils.runOnUiThreadBlocking(() -> { + Assert.assertFalse(InfoBarContainer.from(mSyncTestRule.getActivity().getActivityTab()) + .hasInfoBars()); + }); + } + + public static String getTextFromTextView(int id) { + AtomicReference<String> textRef = new AtomicReference<>(); + onView(withId(id)) + .check((view, error) -> textRef.set(((TextView) view).getText().toString())); + return textRef.get(); + } +}
diff --git a/chrome/android/java/res/layout/password_generation_dialog.xml b/chrome/android/java/res/layout/password_generation_dialog.xml index 3eed312e..e573297 100644 --- a/chrome/android/java/res/layout/password_generation_dialog.xml +++ b/chrome/android/java/res/layout/password_generation_dialog.xml
@@ -12,7 +12,8 @@ android:paddingStart="@dimen/password_generation_dialog_padding" android:paddingEnd="@dimen/password_generation_dialog_padding" android:paddingTop="@dimen/password_generation_dialog_padding" - android:paddingBottom="@dimen/password_generation_dialog_padding"> + android:paddingBottom="@dimen/password_generation_dialog_padding" + android:id="@+id/password_generation_dialog"> <org.chromium.ui.widget.TextViewWithLeading android:layout_width="match_parent"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java index 27094bb..30c6e46 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/modaldialog/AppModalPresenter.java
@@ -10,6 +10,7 @@ import android.view.LayoutInflater; import android.view.Window; +import org.chromium.base.VisibleForTesting; import org.chromium.chrome.R; import org.chromium.ui.modaldialog.DialogDismissalCause; import org.chromium.ui.modaldialog.ModalDialogManager; @@ -85,4 +86,9 @@ mDialog = null; } } + + @VisibleForTesting + public Window getWindow() { + return mDialog.getWindow(); + } }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapView.java b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapView.java index ce465f8..f0f9fbf 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapView.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/photo_picker/PickerBitmapView.java
@@ -175,8 +175,6 @@ @Override public void onSelectionStateChange(List<PickerBitmap> selectedItems) { - super.onSelectionStateChange(selectedItems); - // If the user cancels the dialog before this object has initialized, // the SelectionDelegate will try to notify us that all selections have // been cleared. However, we don't need to process that message and, in @@ -184,6 +182,8 @@ // being initialized. if (mBitmapDetails == null) return; + super.onSelectionStateChange(selectedItems); + updateSelectionState(); if (!isPictureTile()) return;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java index 36c3a48..852eb093 100644 --- a/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/Tab.java
@@ -622,8 +622,7 @@ * @return The profile associated with this tab. */ public Profile getProfile() { - if (mNativeTabAndroid == 0) return null; - return TabJni.get().getProfileAndroid(mNativeTabAndroid, Tab.this); + return Profile.fromWebContents(getWebContents()); } /** @@ -1898,7 +1897,6 @@ void releaseWebContents(long nativeTabAndroid, Tab caller); void onPhysicalBackingSizeChanged( long nativeTabAndroid, Tab caller, WebContents webContents, int width, int height); - Profile getProfileAndroid(long nativeTabAndroid, Tab caller); int loadUrl(long nativeTabAndroid, Tab caller, String url, String initiatorOrigin, String extraHeaders, ResourceRequestBody postData, int transition, String referrerUrl, int referrerPolicy, boolean isRendererInitiated,
diff --git a/chrome/android/public/profiles/java/src/org/chromium/chrome/browser/profiles/Profile.java b/chrome/android/public/profiles/java/src/org/chromium/chrome/browser/profiles/Profile.java index cf42fff..dbc510a 100644 --- a/chrome/android/public/profiles/java/src/org/chromium/chrome/browser/profiles/Profile.java +++ b/chrome/android/public/profiles/java/src/org/chromium/chrome/browser/profiles/Profile.java
@@ -10,6 +10,7 @@ import org.chromium.base.library_loader.LibraryProcessType; import org.chromium.chrome.browser.cookies.CookiesFetcher; import org.chromium.content_public.browser.BrowserStartupController; +import org.chromium.content_public.browser.WebContents; /** * Wrapper that allows passing a Profile reference around in the Java layer. @@ -36,6 +37,14 @@ } /** + * @param webContents {@link WebContents} object. + * @return {@link Profile} object associated with the given WebContents. + */ + public static Profile fromWebContents(WebContents webContents) { + return (Profile) ProfileJni.get().fromWebContents(webContents); + } + + /** * Destroys the Profile. Destruction is delayed until all associated * renderers have been killed, so the profile might not be destroyed upon returning from * this call. @@ -109,6 +118,7 @@ @NativeMethods interface Natives { Object getLastUsedProfile(); + Object fromWebContents(WebContents webContents); void destroyWhenAppropriate(long nativeProfileAndroid, Profile caller); Object getOriginalProfile(long nativeProfileAndroid, Profile caller); Object getOffTheRecordProfile(long nativeProfileAndroid, Profile caller);
diff --git a/chrome/android/webapk/shell_apk/current_version/current_version.gni b/chrome/android/webapk/shell_apk/current_version/current_version.gni index 3a8eaab3..ad30203 100644 --- a/chrome/android/webapk/shell_apk/current_version/current_version.gni +++ b/chrome/android/webapk/shell_apk/current_version/current_version.gni
@@ -12,4 +12,4 @@ # //chrome/android/webapk/shell_apk:webapk is changed. This includes # Java files, Android resource files and AndroidManifest.xml. Does not affect # Chrome.apk -current_shell_apk_version = 108 +current_shell_apk_version = 109
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserUtilsTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserUtilsTest.java index 66c3ea4..b2441c4 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserUtilsTest.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/HostBrowserUtilsTest.java
@@ -193,6 +193,16 @@ setHostBrowserInSharedPreferences(null); Assert.assertEquals(BROWSERS_SUPPORTING_WEBAPKS[0], HostBrowserUtils.computeHostBrowserPackageClearCachedDataOnChange(mContext)); + + // Shared pref browser: Null + // Default browser: Does not support WebAPKs + // > 1 installed browsers + setInstalledBrowsersAndClearedCachedData(DefaultBrowserWebApkSupport.NO, + new String[] { + BROWSERS_NOT_SUPPORTING_WEBAPKS[0], BROWSERS_NOT_SUPPORTING_WEBAPKS[1]}); + setHostBrowserInSharedPreferences(null); + Assert.assertEquals(DEFAULT_BROWSER_NOT_SUPPORTING_WEBAPKS, + HostBrowserUtils.computeHostBrowserPackageClearCachedDataOnChange(mContext)); } /**
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/MainActivityTest.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/MainActivityTest.java index 7bf3ecf..6a369a1 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/MainActivityTest.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/MainActivityTest.java
@@ -32,13 +32,15 @@ @RunWith(LocalRobolectricTestRunner.class) @Config(manifest = Config.NONE) public final class MainActivityTest { - private PackageManager mPackageManager; private static final String BROWSER_PACKAGE_NAME = "com.android.chrome"; + private PackageManager mPackageManager; + private TestBrowserInstaller mBrowserInstaller = new TestBrowserInstaller(); + @Before public void setUp() { mPackageManager = RuntimeEnvironment.application.getPackageManager(); - new TestBrowserInstaller().installModernBrowser(BROWSER_PACKAGE_NAME); + mBrowserInstaller.installModernBrowser(BROWSER_PACKAGE_NAME); } /** @@ -178,13 +180,40 @@ } /** + * Tests that if the only installed browser does not support WebAPKs that the browser is + * launched in tabbed mode. + */ + @Test + public void testShouldLaunchInTabNonChromeBrowser() throws Exception { + final String nonChromeBrowserPackageName = "com.crazy.browser"; + mBrowserInstaller.setInstalledBrowserWithVersion( + nonChromeBrowserPackageName, "10000.0.000.0"); + + final String startUrl = "https://www.google.com/"; + + Bundle bundle = new Bundle(); + bundle.putString(WebApkMetaDataKeys.START_URL, startUrl); + bundle.putString(WebApkMetaDataKeys.SCOPE, startUrl); + // Unbound WebAPK, no runtime host. + WebApkTestHelper.registerWebApkWithMetaData( + WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */); + + Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); + Robolectric.buildActivity(MainActivity.class, launchIntent).create(); + + Intent startedActivityIntent = ShadowApplication.getInstance().getNextStartedActivity(); + assertTabbedBrowserLaunched(startedActivityIntent, nonChromeBrowserPackageName, startUrl); + } + + /** * Tests that a WebAPK should be launched as a tab if Chrome's version number is lower than * {@link HostBrowserUtils#MINIMUM_REQUIRED_CHROME_VERSION}. */ @Test public void testShouldLaunchInTabWhenChromeVersionIsTooLow() throws Exception { + mBrowserInstaller.setInstalledBrowserWithVersion(BROWSER_PACKAGE_NAME, "56.0.000.0"); + final String startUrl = "https://www.google.com/"; - final String oldVersionName = "56.0.000.0"; Bundle bundle = new Bundle(); bundle.putString(WebApkMetaDataKeys.START_URL, startUrl); @@ -193,15 +222,11 @@ WebApkTestHelper.registerWebApkWithMetaData( WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */); - mPackageManager.getPackageInfo(BROWSER_PACKAGE_NAME, 0).versionName = oldVersionName; - Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); Robolectric.buildActivity(MainActivity.class, launchIntent).create(); Intent startedActivityIntent = ShadowApplication.getInstance().getNextStartedActivity(); - Assert.assertEquals(BROWSER_PACKAGE_NAME, startedActivityIntent.getPackage()); - Assert.assertEquals(Intent.ACTION_VIEW, startedActivityIntent.getAction()); - Assert.assertEquals(startUrl, startedActivityIntent.getDataString()); + assertTabbedBrowserLaunched(startedActivityIntent, BROWSER_PACKAGE_NAME, startUrl); } /** @@ -210,8 +235,9 @@ */ @Test public void testShouldNotLaunchInTabWithNewVersionOfChrome() throws Exception { + mBrowserInstaller.setInstalledBrowserWithVersion(BROWSER_PACKAGE_NAME, "57.0.000.0"); + final String startUrl = "https://www.google.com/"; - final String newVersionName = "57.0.000.0"; Bundle bundle = new Bundle(); bundle.putString(WebApkMetaDataKeys.START_URL, startUrl); @@ -220,8 +246,6 @@ WebApkTestHelper.registerWebApkWithMetaData( WebApkUtilsTest.WEBAPK_PACKAGE_NAME, bundle, null /* shareTargetMetaData */); - mPackageManager.getPackageInfo(BROWSER_PACKAGE_NAME, 0).versionName = newVersionName; - Intent launchIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(startUrl)); Robolectric.buildActivity(MainActivity.class, launchIntent).create(); @@ -267,6 +291,17 @@ } /** + * Asserts that the passed-in intent is an intent to launch the passed-in browser package in + * tabbed mode. + */ + private void assertTabbedBrowserLaunched( + Intent intent, String browserPackageName, String expectedStartUrl) { + Assert.assertEquals(browserPackageName, intent.getPackage()); + Assert.assertEquals(Intent.ACTION_VIEW, intent.getAction()); + Assert.assertEquals(expectedStartUrl, intent.getDataString()); + } + + /** * Asserts that the passed in intent is an intent to launch {@link BROWSER_PACKAGE_NAME} in * WebAPK mode. */
diff --git a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java index 5d37419..e9e9b5b 100644 --- a/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java +++ b/chrome/android/webapk/shell_apk/junit/src/org/chromium/webapk/shell_apk/TestBrowserInstaller.java
@@ -28,9 +28,7 @@ * Changes the installed browsers to the passed-in list. */ public void setInstalledModernBrowsers(String defaultBrowserPackage, String[] newPackages) { - while (!mInstalledBrowsers.isEmpty()) { - uninstallBrowser(mInstalledBrowsers.iterator().next()); - } + uninstallAllBrowsers(); installModernBrowser(defaultBrowserPackage); if (newPackages != null) { @@ -41,6 +39,14 @@ } /** + * Changes the installed browser to a browser with the passed-in package and version name. + */ + public void setInstalledBrowserWithVersion(String browser, String versionName) { + uninstallAllBrowsers(); + installBrowserWithVersion(browser, versionName); + } + + /** * Installs browser with the passed-in package name and large version name. */ public void installModernBrowser(String packageName) { @@ -48,7 +54,7 @@ } /** - * Installs browser with the passed-in package name and version code. + * Installs browser with the passed-in package name and version name. */ public void installBrowserWithVersion(String packageName, String versionName) { if (mInstalledBrowsers.contains(packageName)) return; @@ -62,6 +68,15 @@ } /** + * Uninstalls all browsers. + */ + public void uninstallAllBrowsers() { + while (!mInstalledBrowsers.isEmpty()) { + uninstallBrowser(mInstalledBrowsers.iterator().next()); + } + } + + /** * Uninstalls browser with the given package name. */ public void uninstallBrowser(String packageName) {
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java index bdafce16..44226d2 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/ChooseHostBrowserDialog.java
@@ -26,9 +26,8 @@ import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Map; /** * Shows the dialog to choose a host browser to launch WebAPK. Calls the listener callback when the @@ -52,14 +51,14 @@ private String mPackageName; private CharSequence mApplicationLabel; private Drawable mIcon; - private boolean mSupportsWebApks; + private boolean mEnable; - public BrowserItem(String packageName, CharSequence applicationLabel, Drawable icon, - boolean supportsWebApks) { + public BrowserItem( + String packageName, CharSequence applicationLabel, Drawable icon, boolean enable) { mPackageName = packageName; mApplicationLabel = applicationLabel; mIcon = icon; - mSupportsWebApks = supportsWebApks; + mEnable = enable; } /** Returns the package name of a browser. */ @@ -77,9 +76,9 @@ return mIcon; } - /** Returns whether the browser supports WebAPKs. */ - public boolean supportsWebApks() { - return mSupportsWebApks; + /** Returns whether to enable the browser list entry. */ + public boolean enable() { + return mEnable; } } @@ -87,11 +86,11 @@ * Shows the dialog for choosing a host browser. * @param context The current Context. * @param listener The listener for the dialog. - * @param infos The set of ResolvedInfos of the browsers that are shown on the dialog. + * @param infos Browser-package-name->ResolveInfo mapping for all of the installed browsers. * @param appName The name of the WebAPK for which the dialog is shown. */ - public static void show(Context context, final DialogListener listener, Set<ResolveInfo> infos, - String appName) { + public static void show(Context context, final DialogListener listener, + Map<String, ResolveInfo> infos, String appName) { final List<BrowserItem> browserItems = getBrowserInfosForHostBrowserSelection(context.getPackageManager(), infos); @@ -128,7 +127,7 @@ @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { BrowserItem browserItem = browserItems.get(position); - if (browserItem.supportsWebApks()) { + if (browserItem.enable()) { onDismissCanceler.canceled = true; listener.onHostBrowserSelected(browserItem.getPackageName()); dialog.cancel(); @@ -149,18 +148,23 @@ /** Returns a list of BrowserItem for all of the installed browsers. */ private static List<BrowserItem> getBrowserInfosForHostBrowserSelection( - PackageManager packageManager, Set<ResolveInfo> resolveInfos) { + PackageManager packageManager, Map<String, ResolveInfo> resolveInfos) { + boolean hasBrowserSupportingWebApk = false; + for (String installedBrowserPackage : resolveInfos.keySet()) { + if (HostBrowserUtils.doesBrowserSupportWebApks(installedBrowserPackage)) { + hasBrowserSupportingWebApk = true; + break; + } + } + List<BrowserItem> browsers = new ArrayList<>(); - List<String> browsersSupportingWebApk = HostBrowserUtils.getBrowsersSupportingWebApk(); - Set<String> packages = new HashSet<>(); - - for (ResolveInfo info : resolveInfos) { - if (packages.contains(info.activityInfo.packageName)) continue; - packages.add(info.activityInfo.packageName); - - browsers.add(new BrowserItem(info.activityInfo.packageName, - info.loadLabel(packageManager), info.loadIcon(packageManager), - browsersSupportingWebApk.contains(info.activityInfo.packageName))); + for (Map.Entry<String, ResolveInfo> entry : resolveInfos.entrySet()) { + String browserPackage = entry.getKey(); + ResolveInfo info = entry.getValue(); + boolean enable = !hasBrowserSupportingWebApk + || HostBrowserUtils.doesBrowserSupportWebApks(browserPackage); + browsers.add(new BrowserItem(browserPackage, info.loadLabel(packageManager), + info.loadIcon(packageManager), enable)); } if (browsers.size() <= 1) return browsers; @@ -168,10 +172,10 @@ Collections.sort(browsers, new Comparator<BrowserItem>() { @Override public int compare(BrowserItem a, BrowserItem b) { - if (a.mSupportsWebApks == b.mSupportsWebApks) { + if (a.mEnable == b.mEnable) { return a.getPackageName().compareTo(b.getPackageName()); } - return a.mSupportsWebApks ? -1 : 1; + return a.mEnable ? -1 : 1; } }); @@ -205,8 +209,8 @@ res.getDimensionPixelSize(R.dimen.list_column_padding), 0, 0, 0); BrowserItem item = mBrowsers.get(position); - name.setEnabled(item.supportsWebApks()); - if (item.supportsWebApks()) { + name.setEnabled(item.enable()); + if (item.enable()) { name.setText(item.getApplicationName()); name.setTextColor(WebApkUtils.getColor(res, R.color.black_alpha_87)); icon.setAlpha(SUPPORTED_ICON_OPACITY); @@ -224,13 +228,13 @@ icon.setAlpha(UNSUPPORTED_ICON_OPACITY); } icon.setImageDrawable(item.getApplicationIcon()); - icon.setEnabled(item.supportsWebApks()); + icon.setEnabled(item.enable()); return convertView; } @Override public boolean isEnabled(int position) { - return mBrowsers.get(position).supportsWebApks(); + return mBrowsers.get(position).enable(); } } }
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java index 51f3c8b5..35e79f0 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/HostBrowserUtils.java
@@ -15,9 +15,10 @@ import org.chromium.webapk.lib.common.WebApkMetaDataKeys; -import java.util.ArrayList; import java.util.Arrays; -import java.util.List; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; /** * Contains methods for getting information about host browser. @@ -39,8 +40,8 @@ /** * The package names of the browsers that support WebAPKs. The most preferred one comes first. */ - private static List<String> sBrowsersSupportingWebApk = - new ArrayList<String>(Arrays.asList("com.google.android.apps.chrome", + private static Set<String> sBrowsersSupportingWebApk = + new HashSet<String>(Arrays.asList("com.google.android.apps.chrome", "com.android.chrome", "com.chrome.beta", "com.chrome.dev", "com.chrome.canary", "org.chromium.chrome", "org.chromium.chrome.tests", ARC_INTENT_HELPER_BROWSER)); @@ -52,12 +53,9 @@ sHostPackage = null; } - /** - * Returns a list of browsers that support WebAPKs. TODO(hanxi): Replace this function once we - * figure out a better way to know which browser supports WebAPKs. - */ - public static List<String> getBrowsersSupportingWebApk() { - return sBrowsersSupportingWebApk; + /** Returns whether the passed-in browser package name supports WebAPKs. */ + public static boolean doesBrowserSupportWebApks(String browserPackageName) { + return sBrowsersSupportingWebApk.contains(browserPackageName); } /** @@ -118,6 +116,10 @@ /** Queries the given host browser's major version. */ public static int queryHostBrowserMajorChromiumVersion( Context context, String hostBrowserPackageName) { + if (!doesBrowserSupportWebApks(hostBrowserPackageName)) { + return -1; + } + PackageInfo info; try { info = context.getPackageManager().getPackageInfo(hostBrowserPackageName, 0); @@ -145,7 +147,7 @@ public static boolean shouldLaunchInTab(HostBrowserLauncherParams params) { String hostBrowserPackageName = params.getHostBrowserPackageName(); int hostBrowserMajorChromiumVersion = params.getHostBrowserMajorChromiumVersion(); - if (!sBrowsersSupportingWebApk.contains(hostBrowserPackageName)) { + if (!doesBrowserSupportWebApks(hostBrowserPackageName)) { return true; } @@ -193,26 +195,36 @@ // Gets the package name of the default browser on the Android device. // TODO(hanxi): Investigate the best way to know which browser supports WebAPKs. - String defaultBrowser = getDefaultBrowserPackageName(context.getPackageManager()); - if (!TextUtils.isEmpty(defaultBrowser) && sBrowsersSupportingWebApk.contains(defaultBrowser) + String defaultBrowser = getDefaultBrowserPackageName(packageManager); + if (!TextUtils.isEmpty(defaultBrowser) && doesBrowserSupportWebApks(defaultBrowser) && WebApkUtils.isInstalled(packageManager, defaultBrowser)) { return defaultBrowser; } + Map<String, ResolveInfo> installedBrowsers = + WebApkUtils.getInstalledBrowserResolveInfos(packageManager); + if (installedBrowsers.size() == 1) { + return installedBrowsers.keySet().iterator().next(); + } + // If there is only one browser supporting WebAPK, and we can't decide which browser to use // by looking up cache, metadata and default browser, open with that browser. - int availableBrowserCounter = 0; + int numSupportedBrowsersInstalled = 0; String lastSupportedBrowser = null; - for (String packageName : sBrowsersSupportingWebApk) { - if (availableBrowserCounter > 1) break; - if (WebApkUtils.isInstalled(packageManager, packageName)) { - availableBrowserCounter++; - lastSupportedBrowser = packageName; + for (String browserPackageName : installedBrowsers.keySet()) { + if (numSupportedBrowsersInstalled > 1) break; + if (doesBrowserSupportWebApks(browserPackageName)) { + numSupportedBrowsersInstalled++; + lastSupportedBrowser = browserPackageName; } } - if (availableBrowserCounter == 1) { + if (numSupportedBrowsersInstalled == 1) { return lastSupportedBrowser; } + + if (numSupportedBrowsersInstalled == 0 && installedBrowsers.containsKey(defaultBrowser)) { + return defaultBrowser; + } return null; } @@ -227,9 +239,7 @@ Intent browserIntent = WebApkUtils.getQueryInstalledBrowsersIntent(); ResolveInfo resolveInfo = packageManager.resolveActivity(browserIntent, PackageManager.MATCH_DEFAULT_ONLY); - if (resolveInfo == null || resolveInfo.activityInfo == null) return null; - - return resolveInfo.activityInfo.packageName; + return WebApkUtils.getPackageNameFromResolveInfo(resolveInfo); } /** Deletes the internal storage for the given context. */
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/LaunchHostBrowserSelector.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/LaunchHostBrowserSelector.java index 27aa87bd..1949e38 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/LaunchHostBrowserSelector.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/LaunchHostBrowserSelector.java
@@ -16,8 +16,7 @@ import org.chromium.webapk.lib.common.WebApkMetaDataKeys; -import java.util.List; -import java.util.Set; +import java.util.Map; /** Selects host browser to launch, showing a dialog to select browser if necessary. */ public class LaunchHostBrowserSelector { @@ -77,9 +76,9 @@ return; } - Set<ResolveInfo> infos = + Map<String, ResolveInfo> infos = WebApkUtils.getInstalledBrowserResolveInfos(mContext.getPackageManager()); - if (hasBrowserSupportingWebApks(infos)) { + if (!infos.isEmpty()) { showChooseHostBrowserDialog(infos, selectCallback); } else { showInstallHostBrowserDialog(metadata, selectCallback); @@ -96,19 +95,9 @@ } } - /** Returns whether there is any installed browser supporting WebAPKs. */ - private static boolean hasBrowserSupportingWebApks(Set<ResolveInfo> resolveInfos) { - List<String> browsersSupportingWebApk = HostBrowserUtils.getBrowsersSupportingWebApk(); - for (ResolveInfo info : resolveInfos) { - if (browsersSupportingWebApk.contains(info.activityInfo.packageName)) { - return true; - } - } - return false; - } - /** Shows a dialog to choose the host browser. */ - private void showChooseHostBrowserDialog(Set<ResolveInfo> infos, Callback selectCallback) { + private void showChooseHostBrowserDialog( + Map<String, ResolveInfo> infos, Callback selectCallback) { ChooseHostBrowserDialog.DialogListener listener = new ChooseHostBrowserDialog.DialogListener() { @Override
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java index d019222..3e24429 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkServiceFactory.java
@@ -39,6 +39,10 @@ @Override public IBinder onBind(Intent intent) { final String hostBrowserPackage = HostBrowserUtils.getCachedHostBrowserPackage(this); + if (!HostBrowserUtils.doesBrowserSupportWebApks(hostBrowserPackage)) { + Log.w(TAG, "Host browser does not support WebAPKs."); + return null; + } ClassLoader webApkClassLoader = HostBrowserClassLoader.getClassLoaderInstance( this, hostBrowserPackage, WEBAPK_SERVICE_IMPL_CLASS_NAME); if (webApkClassLoader == null) {
diff --git a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java index b872bfa..4f2244c 100644 --- a/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java +++ b/chrome/android/webapk/shell_apk/src/org/chromium/webapk/shell_apk/WebApkUtils.java
@@ -34,9 +34,9 @@ import org.chromium.webapk.lib.common.WebApkMetaDataKeys; import java.util.ArrayList; -import java.util.HashSet; +import java.util.HashMap; import java.util.List; -import java.util.Set; +import java.util.Map; /** * Contains utility methods for interacting with WebAPKs. @@ -105,22 +105,31 @@ return returnUrlBuilder.toString(); } - /** Returns a set of ResolveInfo for all of the installed browsers. */ - public static Set<ResolveInfo> getInstalledBrowserResolveInfos(PackageManager packageManager) { + /** Returns a browser-package-name->ResolveInfo mapping for all of the installed browsers. */ + public static Map<String, ResolveInfo> getInstalledBrowserResolveInfos( + PackageManager packageManager) { Intent browserIntent = getQueryInstalledBrowsersIntent(); // Note: {@link PackageManager#queryIntentActivities()} does not return ResolveInfos for // disabled browsers. - Set<ResolveInfo> result = new HashSet<>(); - List<ResolveInfo> resolveInfosAll = + List<ResolveInfo> resolveInfos = packageManager.queryIntentActivities(browserIntent, PackageManager.MATCH_ALL); - List<ResolveInfo> resolveInfosDefaultOnly = packageManager.queryIntentActivities( - browserIntent, PackageManager.MATCH_DEFAULT_ONLY); + resolveInfos.addAll(packageManager.queryIntentActivities( + browserIntent, PackageManager.MATCH_DEFAULT_ONLY)); - result.addAll(resolveInfosAll); - result.addAll(resolveInfosDefaultOnly); + Map<String, ResolveInfo> result = new HashMap<>(); + for (ResolveInfo resolveInfo : resolveInfos) { + result.put(getPackageNameFromResolveInfo(resolveInfo), resolveInfo); + } return result; } + /** Returns the package name for the passed-in ResolveInfo. */ + public static String getPackageNameFromResolveInfo(ResolveInfo resolveInfo) { + return (resolveInfo != null && resolveInfo.activityInfo != null) + ? resolveInfo.activityInfo.packageName + : null; + } + /** Builds a context for the passed in remote package name. */ public static Context fetchRemoteContext(Context context, String remotePackageName) { try {
diff --git a/chrome/app/settings_strings.grdp b/chrome/app/settings_strings.grdp index e476f15..ab8d959 100644 --- a/chrome/app/settings_strings.grdp +++ b/chrome/app/settings_strings.grdp
@@ -1758,6 +1758,9 @@ <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_KERBEROS_AUTHENTICATION" desc="Authentication method option to use a users Kerberos ticket to authenticate. Only availible for Active Directory users."> SSO </message> + <message name="IDS_SETTINGS_DOWNLOADS_ADD_SHARE_DISCOVERY_MESSAGE" desc="The message shown next to the loading spinner shown when searching for SMB shares."> + Looking for file shares + </message> </if> <!-- Kerberos tickets -->
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn index ea66680..20fcf610 100644 --- a/chrome/browser/BUILD.gn +++ b/chrome/browser/BUILD.gn
@@ -3004,7 +3004,6 @@ "background/background_contents_service_observer.h", "badging/badge_manager.cc", "badging/badge_manager.h", - "badging/badge_manager_delegate.cc", "badging/badge_manager_delegate.h", "badging/badge_manager_factory.cc", "badging/badge_manager_factory.h",
diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc index 8a346b3..8b6b7eb 100644 --- a/chrome/browser/about_flags.cc +++ b/chrome/browser/about_flags.cc
@@ -4031,7 +4031,7 @@ FEATURE_VALUE_TYPE(blink::features::kNativeFileSystemAPI)}, {"file-handling-api", flag_descriptions::kFileHandlingAPIName, - flag_descriptions::kFileHandlingAPIDescription, kOsCrOS, + flag_descriptions::kFileHandlingAPIDescription, kOsDesktop, FEATURE_VALUE_TYPE(blink::features::kFileHandlingAPI)}, #if !defined(OS_ANDROID)
diff --git a/chrome/browser/android/tab_android.cc b/chrome/browser/android/tab_android.cc index b00e343..e146a29 100644 --- a/chrome/browser/android/tab_android.cc +++ b/chrome/browser/android/tab_android.cc
@@ -323,19 +323,6 @@ web_contents->GetNativeView()->OnPhysicalBackingSizeChanged(size); } -base::android::ScopedJavaLocalRef<jobject> TabAndroid::GetProfileAndroid( - JNIEnv* env, - const JavaParamRef<jobject>& obj) { - Profile* profile = GetProfile(); - if (!profile) - return base::android::ScopedJavaLocalRef<jobject>(); - ProfileAndroid* profile_android = ProfileAndroid::FromProfile(profile); - if (!profile_android) - return base::android::ScopedJavaLocalRef<jobject>(); - - return profile_android->GetJavaObject(); -} - TabAndroid::TabLoadStatus TabAndroid::LoadUrl( JNIEnv* env, const JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/android/tab_android.h b/chrome/browser/android/tab_android.h index a12f8d0..e38f52e7 100644 --- a/chrome/browser/android/tab_android.h +++ b/chrome/browser/android/tab_android.h
@@ -133,9 +133,6 @@ const base::android::JavaParamRef<jobject>& jweb_contents, jint width, jint height); - base::android::ScopedJavaLocalRef<jobject> GetProfileAndroid( - JNIEnv* env, - const base::android::JavaParamRef<jobject>& obj); TabLoadStatus LoadUrl( JNIEnv* env, const base::android::JavaParamRef<jobject>& obj,
diff --git a/chrome/browser/apps/app_service/app_service_proxy.cc b/chrome/browser/apps/app_service/app_service_proxy.cc index c98caa7..c1509f6 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.cc +++ b/chrome/browser/apps/app_service/app_service_proxy.cc
@@ -12,6 +12,7 @@ #include "chrome/browser/apps/app_service/app_icon_source.h" #include "chrome/browser/apps/app_service/app_service_metrics.h" #include "chrome/browser/apps/app_service/app_service_proxy_factory.h" +#include "chrome/browser/chromeos/extensions/gfx_utils.h" #include "chrome/browser/profiles/profile.h" #include "chrome/services/app_service/app_service_impl.h" #include "chrome/services/app_service/public/cpp/intent_util.h" @@ -268,4 +269,16 @@ receivers_.Add(this, std::move(receiver)); } +#if defined(OS_CHROMEOS) +void AppServiceProxy::ApplyChromeBadge(Profile* profile, + const std::string& arc_package_name) { + const std::vector<std::string> extension_ids = + extensions::util::GetEquivalentInstalledExtensions(profile, + arc_package_name); + for (auto app_id : extension_ids) { + this->extension_apps_->ApplyChromeBadge(app_id); + } +} +#endif // OS_CHROMEOS + } // namespace apps
diff --git a/chrome/browser/apps/app_service/app_service_proxy.h b/chrome/browser/apps/app_service/app_service_proxy.h index 0d663c6..e3d8295 100644 --- a/chrome/browser/apps/app_service/app_service_proxy.h +++ b/chrome/browser/apps/app_service/app_service_proxy.h
@@ -76,6 +76,10 @@ std::vector<std::string> GetAppIdsForUrl(const GURL& url); std::vector<std::string> GetAppIdsForIntent(apps::mojom::IntentPtr intent); +#if defined(OS_CHROMEOS) + void ApplyChromeBadge(Profile* profile, const std::string& arc_package_name); +#endif + private: // An adapter, presenting an IconLoader interface based on the underlying // Mojo service (or on a fake implementation for testing).
diff --git a/chrome/browser/apps/app_service/arc_apps.cc b/chrome/browser/apps/app_service/arc_apps.cc index f579953..44711c3 100644 --- a/chrome/browser/apps/app_service/arc_apps.cc +++ b/chrome/browser/apps/app_service/arc_apps.cc
@@ -177,6 +177,7 @@ prefs->GetApp(app_id); if (app_info) { apps.push_back(Convert(prefs, app_id, *app_info)); + ApplyChromeBadge(app_info->package_name); } } } @@ -383,6 +384,7 @@ void ArcApps::OnPackageInstalled( const arc::mojom::ArcPackageInfo& package_info) { + ApplyChromeBadge(package_info.package_name); ConvertAndPublishPackageApps(package_info); } @@ -392,6 +394,11 @@ ConvertAndPublishPackageApps(package_info, update_icon); } +void ArcApps::OnPackageRemoved(const std::string& package_name, + bool uninstalled) { + ApplyChromeBadge(package_name); +} + void ArcApps::OnPackageListInitialRefreshed() { ArcAppListPrefs* prefs = ArcAppListPrefs::Get(profile_); if (!prefs) { @@ -583,4 +590,12 @@ } } +void ArcApps::ApplyChromeBadge(const std::string& arc_package_name) { + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile_); + if (proxy) { + proxy->ApplyChromeBadge(profile_, arc_package_name); + } +} + } // namespace apps
diff --git a/chrome/browser/apps/app_service/arc_apps.h b/chrome/browser/apps/app_service/arc_apps.h index da9c70b..18ecd9c 100644 --- a/chrome/browser/apps/app_service/arc_apps.h +++ b/chrome/browser/apps/app_service/arc_apps.h
@@ -86,6 +86,8 @@ const arc::mojom::ArcPackageInfo& package_info) override; void OnPackageModified( const arc::mojom::ArcPackageInfo& package_info) override; + void OnPackageRemoved(const std::string& package_name, + bool uninstalled) override; void OnPackageListInitialRefreshed() override; void LoadPlayStoreIcon(apps::mojom::IconCompression icon_compression, @@ -101,6 +103,7 @@ void ConvertAndPublishPackageApps( const arc::mojom::ArcPackageInfo& package_info, bool update_icon = true); + void ApplyChromeBadge(const std::string& arc_package_name); void UpdateAppIntentFilters( std::string package_name, arc::ArcIntentHelperBridge* intent_helper_bridge,
diff --git a/chrome/browser/apps/app_service/extension_apps.cc b/chrome/browser/apps/app_service/extension_apps.cc index 1e17987..6026937 100644 --- a/chrome/browser/apps/app_service/extension_apps.cc +++ b/chrome/browser/apps/app_service/extension_apps.cc
@@ -713,23 +713,7 @@ app->short_name = extension->short_name(); app->description = extension->description(); app->version = extension->GetVersionForDisplay(); - - IconEffects icon_effects = IconEffects::kNone; -#if defined(OS_CHROMEOS) - icon_effects = - static_cast<IconEffects>(icon_effects | IconEffects::kResizeAndPad); - if (extensions::util::ShouldApplyChromeBadge(profile_, extension->id())) { - icon_effects = static_cast<IconEffects>(icon_effects | IconEffects::kBadge); - } -#endif - if (!extensions::util::IsAppLaunchable(extension->id(), profile_)) { - icon_effects = static_cast<IconEffects>(icon_effects | IconEffects::kGray); - } - if (extension->from_bookmark()) { - icon_effects = - static_cast<IconEffects>(icon_effects | IconEffects::kRoundCorners); - } - app->icon_key = icon_key_factory_.MakeIconKey(icon_effects); + app->icon_key = icon_key_factory_.MakeIconKey(GetIconEffect(extension)); if (profile_) { auto* prefs = extensions::ExtensionPrefs::Get(profile_); @@ -798,4 +782,41 @@ return true; } +IconEffects ExtensionApps::GetIconEffect( + const extensions::Extension* extension) { + IconEffects icon_effects = IconEffects::kNone; +#if defined(OS_CHROMEOS) + icon_effects = + static_cast<IconEffects>(icon_effects | IconEffects::kResizeAndPad); + if (extensions::util::ShouldApplyChromeBadge(profile_, extension->id())) { + icon_effects = static_cast<IconEffects>(icon_effects | IconEffects::kBadge); + } +#endif + if (!extensions::util::IsAppLaunchable(extension->id(), profile_)) { + icon_effects = static_cast<IconEffects>(icon_effects | IconEffects::kGray); + } + if (extension->from_bookmark()) { + icon_effects = + static_cast<IconEffects>(icon_effects | IconEffects::kRoundCorners); + } + return icon_effects; +} + +void ExtensionApps::ApplyChromeBadge(const std::string& app_id) { + extensions::ExtensionRegistry* registry = + extensions::ExtensionRegistry::Get(profile_); + const extensions::Extension* extension = + registry->GetInstalledExtension(app_id); + if (!extension || !Accepts(extension)) { + return; + } + + apps::mojom::AppPtr app = apps::mojom::App::New(); + app->app_type = app_type_; + app->app_id = extension->id(); + app->icon_key = icon_key_factory_.MakeIconKey(GetIconEffect(extension)); + + Publish(std::move(app)); +} + } // namespace apps
diff --git a/chrome/browser/apps/app_service/extension_apps.h b/chrome/browser/apps/app_service/extension_apps.h index 0d8ca5e..8f4e28a 100644 --- a/chrome/browser/apps/app_service/extension_apps.h +++ b/chrome/browser/apps/app_service/extension_apps.h
@@ -10,6 +10,7 @@ #include "base/macros.h" #include "base/memory/weak_ptr.h" #include "base/scoped_observer.h" +#include "chrome/browser/apps/app_service/app_icon_factory.h" #include "chrome/browser/apps/app_service/icon_key_util.h" #include "chrome/services/app_service/public/mojom/app_service.mojom.h" #include "components/content_settings/core/browser/content_settings_observer.h" @@ -51,6 +52,8 @@ void Shutdown(); + void ApplyChromeBadge(const std::string& app_id); + private: void Initialize(const mojo::Remote<apps::mojom::AppService>& app_service); @@ -130,6 +133,8 @@ apps::mojom::Readiness readiness, std::vector<apps::mojom::AppPtr>* apps_out); + IconEffects GetIconEffect(const extensions::Extension* extension); + mojo::Receiver<apps::mojom::Publisher> receiver_{this}; mojo::RemoteSet<apps::mojom::Subscriber> subscribers_;
diff --git a/chrome/browser/badging/badge_manager.cc b/chrome/browser/badging/badge_manager.cc index 682cccc8..f2f40ed 100644 --- a/chrome/browser/badging/badge_manager.cc +++ b/chrome/browser/badging/badge_manager.cc
@@ -32,13 +32,9 @@ BadgeManager::BadgeManager(Profile* profile) { #if defined(OS_MACOSX) - SetDelegate(std::make_unique<BadgeManagerDelegateMac>( - profile, this, - &web_app::WebAppProviderBase::GetProviderBase(profile)->registrar())); + SetDelegate(std::make_unique<BadgeManagerDelegateMac>(profile, this)); #elif defined(OS_WIN) - SetDelegate(std::make_unique<BadgeManagerDelegateWin>( - profile, this, - &web_app::WebAppProviderBase::GetProviderBase(profile)->registrar())); + SetDelegate(std::make_unique<BadgeManagerDelegateWin>(profile, this)); #endif } @@ -64,39 +60,35 @@ std::move(context)); } -bool BadgeManager::HasMoreSpecificBadgeForUrl(const GURL& scope, - const GURL& url) { - return MostSpecificBadgeForScope(url).spec().size() > scope.spec().size(); -} - base::Optional<BadgeManager::BadgeValue> BadgeManager::GetBadgeValue( - const GURL& scope) { - const GURL& most_specific = MostSpecificBadgeForScope(scope); - if (most_specific == GURL::EmptyGURL()) + const web_app::AppId& app_id) { + const auto& it = badged_apps_.find(app_id); + if (it == badged_apps_.end()) return base::nullopt; - return base::make_optional(badged_scopes_[most_specific]); + return it->second; } -void BadgeManager::SetBadgeForTesting(const GURL& scope, BadgeValue value) { - UpdateBadge(scope, value); +void BadgeManager::SetBadgeForTesting(const web_app::AppId& app_id, + BadgeValue value) { + UpdateBadge(app_id, value); } -void BadgeManager::ClearBadgeForTesting(const GURL& scope) { - UpdateBadge(scope, base::nullopt); +void BadgeManager::ClearBadgeForTesting(const web_app::AppId& app_id) { + UpdateBadge(app_id, base::nullopt); } -void BadgeManager::UpdateBadge(const GURL& scope, +void BadgeManager::UpdateBadge(const web_app::AppId& app_id, base::Optional<BadgeValue> value) { if (!value) - badged_scopes_.erase(scope); + badged_apps_.erase(app_id); else - badged_scopes_[scope] = value.value(); + badged_apps_[app_id] = value.value(); if (!delegate_) return; - delegate_->OnBadgeUpdated(scope); + delegate_->OnAppBadgeUpdated(app_id); } void BadgeManager::SetBadge(blink::mojom::BadgeValuePtr mojo_value) { @@ -107,48 +99,28 @@ return; } - const base::Optional<GURL> app_scope = - GetAppScopeForContext(receivers_.current_context()); - if (!app_scope) + const base::Optional<web_app::AppId> app_id = + GetAppIdForBadging(receivers_.current_context()); + if (!app_id) return; // Convert the mojo badge representation into a BadgeManager::BadgeValue. BadgeValue value = mojo_value->is_flag() ? base::nullopt : base::make_optional(mojo_value->get_number()); - UpdateBadge(app_scope.value(), base::make_optional(value)); + UpdateBadge(app_id.value(), base::make_optional(value)); } void BadgeManager::ClearBadge() { - const base::Optional<GURL> app_scope = - GetAppScopeForContext(receivers_.current_context()); - if (!app_scope) + const base::Optional<web_app::AppId> app_id = + GetAppIdForBadging(receivers_.current_context()); + if (!app_id) return; - UpdateBadge(app_scope.value(), base::nullopt); + UpdateBadge(app_id.value(), base::nullopt); } -GURL BadgeManager::MostSpecificBadgeForScope(const GURL& scope) { - const std::string& scope_string = scope.spec(); - GURL best_match = GURL::EmptyGURL(); - uint64_t longest_match = 0; - - for (const auto& pair : badged_scopes_) { - const std::string& cur_scope_str = pair.first.spec(); - if (scope_string.find(cur_scope_str) != 0) - continue; - - if (longest_match >= cur_scope_str.size()) - continue; - - longest_match = cur_scope_str.size(); - best_match = pair.first; - } - - return best_match; -} - -base::Optional<GURL> BadgeManager::GetAppScopeForContext( +base::Optional<web_app::AppId> BadgeManager::GetAppIdForBadging( const BindingContext& context) { content::RenderFrameHost* frame = content::RenderFrameHost::FromID(context.process_id, context.frame_id); @@ -167,10 +139,7 @@ const base::Optional<web_app::AppId> app_id = registrar.FindAppWithUrlInScope(frame->GetLastCommittedURL()); - if (!app_id) - return base::nullopt; - - return registrar.GetAppScope(app_id.value()); + return app_id; } std::string GetBadgeString(base::Optional<uint64_t> badge_content) {
diff --git a/chrome/browser/badging/badge_manager.h b/chrome/browser/badging/badge_manager.h index 5f5833f3..361e0764 100644 --- a/chrome/browser/badging/badge_manager.h +++ b/chrome/browser/badging/badge_manager.h
@@ -11,6 +11,7 @@ #include "base/macros.h" #include "base/optional.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "components/keyed_service/core/keyed_service.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "third_party/blink/public/mojom/badging/badging.mojom.h" @@ -46,16 +47,12 @@ content::RenderFrameHost* frame, mojo::PendingReceiver<blink::mojom::BadgeService> receiver); - // Returns whether there is a more specific badge for |url| than |scope|. - // Note: This function does not check that there is a badge for |scope|. - bool HasMoreSpecificBadgeForUrl(const GURL& scope, const GURL& url); + // Gets the badge for |app_id|. This will be base::nullopt if the app is not + // badged. + base::Optional<BadgeValue> GetBadgeValue(const web_app::AppId& app_id); - // Gets the most specific badge applying to |scope|. This will be - // base::nullopt if the scope is not badged. - base::Optional<BadgeValue> GetBadgeValue(const GURL& scope); - - void SetBadgeForTesting(const GURL& scope, BadgeValue value); - void ClearBadgeForTesting(const GURL& scope); + void SetBadgeForTesting(const web_app::AppId& app_id, BadgeValue value); + void ClearBadgeForTesting(const web_app::AppId& app_id); private: // The BindingContext of a mojo request. Allows mojo calls to be tied back to @@ -68,9 +65,10 @@ int frame_id; }; - // Updates the badge for |scope| to be |value|, if it is not base::nullopt. + // Updates the badge for |app_id| to be |value|, if it is not base::nullopt. // If value is |base::nullopt| then this clears the badge. - void UpdateBadge(const GURL& scope, base::Optional<BadgeValue> value); + void UpdateBadge(const web_app::AppId& app_id, + base::Optional<BadgeValue> value); // blink::mojom::BadgeService: // Note: These are private to stop them being called outside of mojo as they @@ -78,13 +76,10 @@ void SetBadge(blink::mojom::BadgeValuePtr value) override; void ClearBadge() override; - // Finds the scope URL of the most specific badge for |scope|. Returns - // GURL::EmptyGURL() if no match is found. - GURL MostSpecificBadgeForScope(const GURL& scope); - - // Finds the most specific app scope containing |context|. base::nullopt if - // no app contains |context|. - base::Optional<GURL> GetAppScopeForContext(const BindingContext& context); + // Gets the app id to badge, based on the |context|. base::nullopt if + // |context| isn't inside an app. + base::Optional<web_app::AppId> GetAppIdForBadging( + const BindingContext& context); // All the mojo receivers for the BadgeManager. Keeps track of the // render_frame the binding is associated with, so as to not have to rely @@ -95,8 +90,8 @@ // Note: This is currently only set on Windows and MacOS. std::unique_ptr<BadgeManagerDelegate> delegate_; - // Maps scope to badge contents. - std::map<GURL, BadgeValue> badged_scopes_; + // Maps app_id to badge contents. + std::map<web_app::AppId, BadgeValue> badged_apps_; DISALLOW_COPY_AND_ASSIGN(BadgeManager); };
diff --git a/chrome/browser/badging/badge_manager_delegate.cc b/chrome/browser/badging/badge_manager_delegate.cc deleted file mode 100644 index 5dec757..0000000 --- a/chrome/browser/badging/badge_manager_delegate.cc +++ /dev/null
@@ -1,40 +0,0 @@ -// Copyright 2019 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 "chrome/browser/badging/badge_manager_delegate.h" - -#include <vector> - -#include "chrome/browser/web_applications/components/app_registrar.h" - -namespace badging { - -void BadgeManagerDelegate::OnBadgeUpdated(const GURL& scope) { - const std::vector<web_app::AppId>& app_ids = - registrar()->FindAppsInScope(scope); - - for (const auto& app_id : app_ids) { - const auto& app_scope = registrar()->GetAppScope(app_id); - if (!app_scope) - continue; - - // If it wasn't the most specific badge for the app that changed, there's no - // need to update it. - if (badge_manager()->HasMoreSpecificBadgeForUrl(scope, app_scope.value())) - continue; - - OnAppBadgeUpdated(app_id); - } -} - -base::Optional<BadgeManager::BadgeValue> BadgeManagerDelegate::GetAppBadgeValue( - const web_app::AppId& app_id) { - const auto& scope = registrar()->GetAppScope(app_id); - if (!scope) - return base::nullopt; - - return badge_manager()->GetBadgeValue(scope.value()); -} - -} // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate.h b/chrome/browser/badging/badge_manager_delegate.h index fd63a76b..ba3e9635 100644 --- a/chrome/browser/badging/badge_manager_delegate.h +++ b/chrome/browser/badging/badge_manager_delegate.h
@@ -12,47 +12,29 @@ class Profile; -namespace web_app { -class AppRegistrar; -} - namespace badging { // A BadgeManagerDelegate is responsible for updating the UI in response to a // badge change. class BadgeManagerDelegate { public: - explicit BadgeManagerDelegate(Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar) - : profile_(profile), - badge_manager_(badge_manager), - registrar_(registrar) {} + explicit BadgeManagerDelegate(Profile* profile, BadgeManager* badge_manager) + : profile_(profile), badge_manager_(badge_manager) {} virtual ~BadgeManagerDelegate() = default; - // Called when the badge for |scope| has changed. - virtual void OnBadgeUpdated(const GURL& scope); - - protected: // Called when the badge for |app_id| has changed. virtual void OnAppBadgeUpdated(const web_app::AppId& app_id) = 0; - // Gets the badge for |app_id|. base::nullopt if the |app_id| is not badged. - base::Optional<BadgeManager::BadgeValue> GetAppBadgeValue( - const web_app::AppId& app_id); - + protected: Profile* profile() { return profile_; } BadgeManager* badge_manager() { return badge_manager_; } - web_app::AppRegistrar* registrar() { return registrar_; } private: // The profile the badge manager delegate is associated with. Profile* profile_; // The badge manager that owns this delegate. BadgeManager* badge_manager_; - // The registrar of apps this delegate is concerned with. - web_app::AppRegistrar* registrar_; DISALLOW_COPY_AND_ASSIGN(BadgeManagerDelegate); };
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.cc b/chrome/browser/badging/badge_manager_delegate_mac.cc index 54253fe..01f001ac 100644 --- a/chrome/browser/badging/badge_manager_delegate_mac.cc +++ b/chrome/browser/badging/badge_manager_delegate_mac.cc
@@ -9,20 +9,17 @@ #include "chrome/browser/badging/badge_manager.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/browser_list.h" -#include "chrome/browser/web_applications/components/app_registrar.h" #include "chrome/common/mac/app_shim.mojom.h" namespace badging { -BadgeManagerDelegateMac::BadgeManagerDelegateMac( - Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar) - : BadgeManagerDelegate(profile, badge_manager, registrar) {} +BadgeManagerDelegateMac::BadgeManagerDelegateMac(Profile* profile, + BadgeManager* badge_manager) + : BadgeManagerDelegate(profile, badge_manager) {} void BadgeManagerDelegateMac::OnAppBadgeUpdated(const web_app::AppId& app_id) { const base::Optional<BadgeManager::BadgeValue>& badge = - GetAppBadgeValue(app_id); + badge_manager()->GetBadgeValue(app_id); SetAppBadgeLabel(app_id, badge ? badging::GetBadgeString(badge.value()) : ""); }
diff --git a/chrome/browser/badging/badge_manager_delegate_mac.h b/chrome/browser/badging/badge_manager_delegate_mac.h index b31eb96..b9d342ca 100644 --- a/chrome/browser/badging/badge_manager_delegate_mac.h +++ b/chrome/browser/badging/badge_manager_delegate_mac.h
@@ -12,10 +12,6 @@ class Profile; -namespace web_app { -class AppRegistrar; -} - namespace badging { class BadgeManager; @@ -24,8 +20,7 @@ class BadgeManagerDelegateMac : public BadgeManagerDelegate { public: explicit BadgeManagerDelegateMac(Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar); + BadgeManager* badge_manager); void OnAppBadgeUpdated(const web_app::AppId& app_id) override;
diff --git a/chrome/browser/badging/badge_manager_delegate_unittest.cc b/chrome/browser/badging/badge_manager_delegate_unittest.cc deleted file mode 100644 index ccd7bed0..0000000 --- a/chrome/browser/badging/badge_manager_delegate_unittest.cc +++ /dev/null
@@ -1,92 +0,0 @@ -// Copyright 2019 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 <memory> -#include <utility> - -#include "base/optional.h" -#include "chrome/browser/badging/badge_manager.h" -#include "chrome/browser/badging/badge_manager_factory.h" -#include "chrome/browser/badging/test_badge_manager_delegate.h" -#include "chrome/browser/web_applications/components/web_app_helpers.h" -#include "chrome/browser/web_applications/test/test_app_registrar.h" -#include "chrome/test/base/testing_profile.h" -#include "content/public/test/browser_task_environment.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace badging { - -class BadgeManagerDelegateUnittest : public ::testing::Test { - public: - BadgeManagerDelegateUnittest() = default; - ~BadgeManagerDelegateUnittest() override = default; - - void SetUp() override { - profile_.reset(new TestingProfile()); - registrar_.reset(new web_app::TestAppRegistrar()); - - badge_manager_ = - BadgeManagerFactory::GetInstance()->GetForProfile(profile_.get()); - - // Delegate lifetime is managed by BadgeManager. - auto owned_delegate = std::make_unique<TestBadgeManagerDelegate>( - profile_.get(), badge_manager_, registrar()); - delegate_ = owned_delegate.get(); - badge_manager_->SetDelegate(std::move(owned_delegate)); - } - - void TearDown() override { profile_.reset(); } - - TestBadgeManagerDelegate* delegate() { return delegate_; } - - web_app::TestAppRegistrar* registrar() const { return registrar_.get(); } - BadgeManager* badge_manager() const { return badge_manager_; } - - private: - std::unique_ptr<web_app::TestAppRegistrar> registrar_; - TestBadgeManagerDelegate* delegate_; - BadgeManager* badge_manager_; - std::unique_ptr<TestingProfile> profile_; - content::BrowserTaskEnvironment task_environment_; - - DISALLOW_COPY_AND_ASSIGN(BadgeManagerDelegateUnittest); -}; - -TEST_F(BadgeManagerDelegateUnittest, InScopeAppsAreBadged) { - const web_app::AppId& kApp1 = "app1"; - const web_app::AppId& kApp2 = "app2"; - - registrar()->AddExternalApp(kApp1, {GURL("https://example.com/app1")}); - registrar()->AddExternalApp(kApp2, {GURL("https://example.com/app2")}); - - badge_manager()->SetBadgeForTesting(GURL("https://example.com/"), - base::nullopt); - - EXPECT_EQ(2UL, delegate()->set_app_badges().size()); - - EXPECT_EQ(kApp1, delegate()->set_app_badges()[0].first); - EXPECT_EQ(base::nullopt, delegate()->set_app_badges()[0].second); - - EXPECT_EQ(kApp2, delegate()->set_app_badges()[1].first); - EXPECT_EQ(base::nullopt, delegate()->set_app_badges()[1].second); -} - -TEST_F(BadgeManagerDelegateUnittest, InScopeAppsAreCleared) { - const web_app::AppId& kApp1 = "app1"; - const web_app::AppId& kApp2 = "app2"; - - registrar()->AddExternalApp(kApp1, {GURL("https://example.com/app1")}); - registrar()->AddExternalApp(kApp2, {GURL("https://example.com/app2")}); - - badge_manager()->SetBadgeForTesting(GURL("https://example.com/"), - base::nullopt); - badge_manager()->ClearBadgeForTesting(GURL("https://example.com/")); - - EXPECT_EQ(2UL, delegate()->cleared_app_badges().size()); - - EXPECT_EQ(kApp1, delegate()->cleared_app_badges()[0]); - EXPECT_EQ(kApp2, delegate()->cleared_app_badges()[1]); -} - -} // namespace badging
diff --git a/chrome/browser/badging/badge_manager_delegate_win.cc b/chrome/browser/badging/badge_manager_delegate_win.cc index 01ed79c..32c156f 100644 --- a/chrome/browser/badging/badge_manager_delegate_win.cc +++ b/chrome/browser/badging/badge_manager_delegate_win.cc
@@ -12,7 +12,6 @@ #include "chrome/browser/ui/browser_list.h" #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/web_applications/app_browser_controller.h" -#include "chrome/browser/web_applications/components/app_registrar.h" #include "ui/base/l10n/l10n_util.h" #include "ui/strings/grit/ui_strings.h" @@ -62,14 +61,13 @@ } // namespace -BadgeManagerDelegateWin::BadgeManagerDelegateWin( - Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar) - : BadgeManagerDelegate(profile, badge_manager, registrar) {} +BadgeManagerDelegateWin::BadgeManagerDelegateWin(Profile* profile, + BadgeManager* badge_manager) + : BadgeManagerDelegate(profile, badge_manager) {} void BadgeManagerDelegateWin::OnAppBadgeUpdated(const web_app::AppId& app_id) { - const auto& content_and_alt = GetBadgeContentAndAlt(GetAppBadgeValue(app_id)); + const auto& content_and_alt = + GetBadgeContentAndAlt(badge_manager()->GetBadgeValue(app_id)); for (Browser* browser : *BrowserList::GetInstance()) { if (!IsAppBrowser(browser, app_id))
diff --git a/chrome/browser/badging/badge_manager_delegate_win.h b/chrome/browser/badging/badge_manager_delegate_win.h index dd62482b..76bb448 100644 --- a/chrome/browser/badging/badge_manager_delegate_win.h +++ b/chrome/browser/badging/badge_manager_delegate_win.h
@@ -13,10 +13,6 @@ class Profile; -namespace web_app { -class AppRegistrar; -} - namespace badging { class BadgeManager; @@ -25,8 +21,7 @@ class BadgeManagerDelegateWin : public BadgeManagerDelegate { public: explicit BadgeManagerDelegateWin(Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar); + BadgeManager* badge_manager); void OnAppBadgeUpdated(const web_app::AppId& app_id) override;
diff --git a/chrome/browser/badging/badge_manager_unittest.cc b/chrome/browser/badging/badge_manager_unittest.cc index abdd68a..079b73e 100644 --- a/chrome/browser/badging/badge_manager_unittest.cc +++ b/chrome/browser/badging/badge_manager_unittest.cc
@@ -31,7 +31,7 @@ typedef std::pair<GURL, base::Optional<int>> SetBadgeAction; constexpr uint64_t kBadgeContents = 1; -const GURL kAppScope("https://example.com/app"); +const web_app::AppId kAppId = "1"; } // namespace @@ -44,14 +44,13 @@ void SetUp() override { profile_.reset(new TestingProfile()); - registrar_.reset(new web_app::TestAppRegistrar()); badge_manager_ = BadgeManagerFactory::GetInstance()->GetForProfile(profile_.get()); // Delegate lifetime is managed by BadgeManager auto owned_delegate = std::make_unique<TestBadgeManagerDelegate>( - profile_.get(), badge_manager_, registrar_.get()); + profile_.get(), badge_manager_); delegate_ = owned_delegate.get(); badge_manager_->SetDelegate(std::move(owned_delegate)); } @@ -63,7 +62,6 @@ BadgeManager* badge_manager() const { return badge_manager_; } private: - std::unique_ptr<web_app::TestAppRegistrar> registrar_; TestBadgeManagerDelegate* delegate_; BadgeManager* badge_manager_; content::BrowserTaskEnvironment task_environment_; @@ -73,63 +71,63 @@ }; TEST_F(BadgeManagerUnittest, SetFlagBadgeForApp) { - badge_manager()->SetBadgeForTesting(kAppScope, base::nullopt); + badge_manager()->SetBadgeForTesting(kAppId, base::nullopt); - EXPECT_EQ(1UL, delegate()->set_scope_badges().size()); - EXPECT_EQ(kAppScope, delegate()->set_scope_badges().front().first); - EXPECT_EQ(base::nullopt, delegate()->set_scope_badges().front().second); + EXPECT_EQ(1UL, delegate()->set_badges().size()); + EXPECT_EQ(kAppId, delegate()->set_badges().front().first); + EXPECT_EQ(base::nullopt, delegate()->set_badges().front().second); } TEST_F(BadgeManagerUnittest, SetBadgeForApp) { - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - EXPECT_EQ(1UL, delegate()->set_scope_badges().size()); - EXPECT_EQ(kAppScope, delegate()->set_scope_badges().front().first); - EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges().front().second); + EXPECT_EQ(1UL, delegate()->set_badges().size()); + EXPECT_EQ(kAppId, delegate()->set_badges().front().first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges().front().second); } TEST_F(BadgeManagerUnittest, SetBadgeForMultipleApps) { - const GURL kOtherScope("http://other.app/other"); + const web_app::AppId kOtherAppId = "2"; constexpr uint64_t kOtherContents = 2; - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - badge_manager()->SetBadgeForTesting(kOtherScope, + badge_manager()->SetBadgeForTesting(kOtherAppId, base::make_optional(kOtherContents)); - EXPECT_EQ(2UL, delegate()->set_scope_badges().size()); + EXPECT_EQ(2UL, delegate()->set_badges().size()); - EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[0].first); - EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[0].second); + EXPECT_EQ(kAppId, delegate()->set_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); - EXPECT_EQ(kOtherScope, delegate()->set_scope_badges()[1].first); - EXPECT_EQ(kOtherContents, delegate()->set_scope_badges()[1].second); + EXPECT_EQ(kOtherAppId, delegate()->set_badges()[1].first); + EXPECT_EQ(kOtherContents, delegate()->set_badges()[1].second); } TEST_F(BadgeManagerUnittest, SetBadgeForAppAfterClear) { - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - badge_manager()->ClearBadgeForTesting(kAppScope); - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->ClearBadgeForTesting(kAppId); + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - EXPECT_EQ(2UL, delegate()->set_scope_badges().size()); + EXPECT_EQ(2UL, delegate()->set_badges().size()); - EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[0].first); - EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[0].second); + EXPECT_EQ(kAppId, delegate()->set_badges()[0].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[0].second); - EXPECT_EQ(kAppScope, delegate()->set_scope_badges()[1].first); - EXPECT_EQ(kBadgeContents, delegate()->set_scope_badges()[1].second); + EXPECT_EQ(kAppId, delegate()->set_badges()[1].first); + EXPECT_EQ(kBadgeContents, delegate()->set_badges()[1].second); } TEST_F(BadgeManagerUnittest, ClearBadgeForBadgedApp) { - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - badge_manager()->ClearBadgeForTesting(kAppScope); + badge_manager()->ClearBadgeForTesting(kAppId); - EXPECT_EQ(1UL, delegate()->cleared_scope_badges().size()); - EXPECT_EQ(kAppScope, delegate()->cleared_scope_badges().front()); + EXPECT_EQ(1UL, delegate()->cleared_badges().size()); + EXPECT_EQ(kAppId, delegate()->cleared_badges().front()); } TEST_F(BadgeManagerUnittest, BadgingMultipleProfiles) { @@ -137,28 +135,27 @@ auto* other_badge_manager = BadgeManagerFactory::GetInstance()->GetForProfile(other_profile.get()); - web_app::TestAppRegistrar other_registrar; auto owned_other_delegate = std::make_unique<TestBadgeManagerDelegate>( - other_profile.get(), other_badge_manager, &other_registrar); + other_profile.get(), other_badge_manager); auto* other_delegate = owned_other_delegate.get(); other_badge_manager->SetDelegate(std::move(owned_other_delegate)); - other_badge_manager->SetBadgeForTesting(kAppScope, base::nullopt); - other_badge_manager->SetBadgeForTesting(kAppScope, + other_badge_manager->SetBadgeForTesting(kAppId, base::nullopt); + other_badge_manager->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - other_badge_manager->SetBadgeForTesting(kAppScope, base::nullopt); - other_badge_manager->ClearBadgeForTesting(kAppScope); + other_badge_manager->SetBadgeForTesting(kAppId, base::nullopt); + other_badge_manager->ClearBadgeForTesting(kAppId); - badge_manager()->ClearBadgeForTesting(kAppScope); + badge_manager()->ClearBadgeForTesting(kAppId); - EXPECT_EQ(3UL, other_delegate->set_scope_badges().size()); - EXPECT_EQ(0UL, delegate()->set_scope_badges().size()); + EXPECT_EQ(3UL, other_delegate->set_badges().size()); + EXPECT_EQ(0UL, delegate()->set_badges().size()); - EXPECT_EQ(1UL, other_delegate->cleared_scope_badges().size()); - EXPECT_EQ(1UL, delegate()->cleared_scope_badges().size()); + EXPECT_EQ(1UL, other_delegate->cleared_badges().size()); + EXPECT_EQ(1UL, delegate()->cleared_badges().size()); - EXPECT_EQ(kAppScope, other_delegate->set_scope_badges().back().first); - EXPECT_EQ(base::nullopt, other_delegate->set_scope_badges().back().second); + EXPECT_EQ(kAppId, other_delegate->set_badges().back().first); + EXPECT_EQ(base::nullopt, other_delegate->set_badges().back().second); } // Tests methods which call into the badge manager delegate do not crash when @@ -166,46 +163,10 @@ TEST_F(BadgeManagerUnittest, BadgingWithNoDelegateDoesNotCrash) { badge_manager()->SetDelegate(nullptr); - badge_manager()->SetBadgeForTesting(kAppScope, base::nullopt); - badge_manager()->SetBadgeForTesting(kAppScope, + badge_manager()->SetBadgeForTesting(kAppId, base::nullopt); + badge_manager()->SetBadgeForTesting(kAppId, base::make_optional(kBadgeContents)); - badge_manager()->SetBadgeForTesting(GURL(), base::nullopt); - badge_manager()->SetBadgeForTesting(GURL(), - base::make_optional(kBadgeContents)); - badge_manager()->ClearBadgeForTesting(GURL()); -} - -TEST_F(BadgeManagerUnittest, MostSpecificBadgeApplies) { - const GURL origin("https://example.com/"); - const GURL app("https://example.com/app"); - const GURL app_page("https://example.com/app/page/1"); - - const base::Optional<BadgeManager::BadgeValue> origin_badge = - base::make_optional(base::Optional<uint64_t>(1U)); - const base::Optional<BadgeManager::BadgeValue> app_badge = - base::make_optional(base::Optional<uint64_t>(1U)); - const base::Optional<BadgeManager::BadgeValue> app_page_badge = - base::make_optional(base::Optional<uint64_t>(1U)); - - badge_manager()->SetBadgeForTesting(origin, origin_badge.value()); - EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), origin_badge); - - badge_manager()->SetBadgeForTesting(app, app_badge.value()); - EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app), app_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_badge); - - badge_manager()->SetBadgeForTesting(app_page, app_page_badge.value()); - EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app), app_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_page_badge); - - badge_manager()->ClearBadgeForTesting(app); - EXPECT_EQ(badge_manager()->GetBadgeValue(origin), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app), origin_badge); - EXPECT_EQ(badge_manager()->GetBadgeValue(app_page), app_page_badge); + badge_manager()->ClearBadgeForTesting(kAppId); } } // namespace badging
diff --git a/chrome/browser/badging/test_badge_manager_delegate.cc b/chrome/browser/badging/test_badge_manager_delegate.cc index 1c79864..ae3b626 100644 --- a/chrome/browser/badging/test_badge_manager_delegate.cc +++ b/chrome/browser/badging/test_badge_manager_delegate.cc
@@ -11,11 +11,9 @@ namespace badging { -TestBadgeManagerDelegate::TestBadgeManagerDelegate( - Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar) - : BadgeManagerDelegate(profile, badge_manager, registrar) {} +TestBadgeManagerDelegate::TestBadgeManagerDelegate(Profile* profile, + BadgeManager* badge_manager) + : BadgeManagerDelegate(profile, badge_manager) {} TestBadgeManagerDelegate::~TestBadgeManagerDelegate() = default; @@ -24,32 +22,20 @@ on_badge_changed_ = on_badge_changed; } -void TestBadgeManagerDelegate::OnBadgeUpdated(const GURL& scope) { - BadgeManagerDelegate::OnBadgeUpdated(scope); - - const auto& value = badge_manager()->GetBadgeValue(scope); +void TestBadgeManagerDelegate::OnAppBadgeUpdated(const web_app::AppId& app_id) { + const auto& value = badge_manager()->GetBadgeValue(app_id); if (!value) - cleared_scope_badges_.push_back(scope); + cleared_badges_.push_back(app_id); else - set_scope_badges_.push_back(std::make_pair(scope, value.value())); + set_badges_.push_back(std::make_pair(app_id, value.value())); if (on_badge_changed_) on_badge_changed_.Run(); } -void TestBadgeManagerDelegate::OnAppBadgeUpdated(const web_app::AppId& app_id) { - const auto& value = GetAppBadgeValue(app_id); - if (!value) - cleared_app_badges_.push_back(app_id); - else - set_app_badges_.push_back(std::make_pair(app_id, value.value())); -} - void TestBadgeManagerDelegate::ResetBadges() { - cleared_app_badges_.clear(); - set_app_badges_.clear(); - cleared_scope_badges_.clear(); - set_scope_badges_.clear(); + cleared_badges_.clear(); + set_badges_.clear(); } } // namespace badging
diff --git a/chrome/browser/badging/test_badge_manager_delegate.h b/chrome/browser/badging/test_badge_manager_delegate.h index fa689c62..41b9c18 100644 --- a/chrome/browser/badging/test_badge_manager_delegate.h +++ b/chrome/browser/badging/test_badge_manager_delegate.h
@@ -15,10 +15,6 @@ class Profile; -namespace web_app { -class AppRegistrar; -} - namespace badging { class BadgeManager; @@ -29,9 +25,7 @@ // Testing delegate that records badge changes for apps. class TestBadgeManagerDelegate : public BadgeManagerDelegate { public: - TestBadgeManagerDelegate(Profile* profile, - BadgeManager* badge_manager, - web_app::AppRegistrar* registrar); + TestBadgeManagerDelegate(Profile* profile, BadgeManager* badge_manager); ~TestBadgeManagerDelegate() override; // Sets a callback to fire when a badge is set or cleared. @@ -40,27 +34,19 @@ // Resets the lists of cleared and set badges. void ResetBadges(); - std::vector<web_app::AppId> cleared_app_badges() { - return cleared_app_badges_; - } - std::vector<AppBadge> set_app_badges() { return set_app_badges_; } - std::vector<GURL> cleared_scope_badges() { return cleared_scope_badges_; } - std::vector<ScopeBadge> set_scope_badges() { return set_scope_badges_; } + std::vector<web_app::AppId> cleared_badges() { return cleared_badges_; } + std::vector<AppBadge> set_badges() { return set_badges_; } // BadgeManagerDelegate: - void OnBadgeUpdated(const GURL& scope) override; - - protected: - // BadgeManagerDelegate: void OnAppBadgeUpdated(const web_app::AppId& app_badge) override; + protected: + private: base::RepeatingCallback<void()> on_badge_changed_; - std::vector<web_app::AppId> cleared_app_badges_; - std::vector<AppBadge> set_app_badges_; - std::vector<GURL> cleared_scope_badges_; - std::vector<ScopeBadge> set_scope_badges_; + std::vector<web_app::AppId> cleared_badges_; + std::vector<AppBadge> set_badges_; }; } // namespace badging
diff --git a/chrome/browser/chrome_notification_types.h b/chrome/browser/chrome_notification_types.h index fa06a890..e768221f 100644 --- a/chrome/browser/chrome_notification_types.h +++ b/chrome/browser/chrome_notification_types.h
@@ -198,10 +198,6 @@ #endif #if defined(TOOLKIT_VIEWS) - // Sent when a bookmark's context menu is shown. Used to notify - // tests that the context menu has been created and shown. - NOTIFICATION_BOOKMARK_CONTEXT_MENU_SHOWN, - // Notification that the nested loop using during tab dragging has returned. // Used for testing. NOTIFICATION_TAB_DRAG_LOOP_DONE,
diff --git a/chrome/browser/chromeos/concierge_helper_service.cc b/chrome/browser/chromeos/concierge_helper_service.cc index 93b3243..63eb9783 100644 --- a/chrome/browser/chromeos/concierge_helper_service.cc +++ b/chrome/browser/chromeos/concierge_helper_service.cc
@@ -9,7 +9,7 @@ #include "chromeos/dbus/concierge/service.pb.h" #include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "content/public/browser/browser_context.h"
diff --git a/chrome/browser/chromeos/concierge_helper_service_unittest.cc b/chrome/browser/chromeos/concierge_helper_service_unittest.cc index b0dde7db..9fb3a6bd 100644 --- a/chrome/browser/chromeos/concierge_helper_service_unittest.cc +++ b/chrome/browser/chromeos/concierge_helper_service_unittest.cc
@@ -12,7 +12,7 @@ #include "chromeos/dbus/concierge/service.pb.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "chromeos/dbus/fake_concierge_client.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" #include "dbus/bus.h" #include "dbus/object_proxy.h"
diff --git a/chrome/browser/chromeos/crostini/crostini_manager.cc b/chrome/browser/chromeos/crostini/crostini_manager.cc index 0ea761b4..beedf7b 100644 --- a/chrome/browser/chromeos/crostini/crostini_manager.cc +++ b/chrome/browser/chromeos/crostini/crostini_manager.cc
@@ -39,7 +39,7 @@ #include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/image_loader_client.h" #include "chromeos/disks/disk_mount_manager.h" #include "components/component_updater/component_updater_service.h"
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc index 67e2ca34..66ffb2e 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.cc
@@ -20,7 +20,6 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/extensions/api/file_manager_private.h" #include "chromeos/disks/disk_mount_manager.h" -#include "components/drive/chromeos/file_system_interface.h" #include "components/drive/event_logger.h" #include "content/public/browser/browser_thread.h" #include "google_apis/drive/task_util.h" @@ -73,113 +72,41 @@ if (path.empty()) return RespondNow(Error("Invalid path")); - // Check if the source path is under Drive cache directory. - if (drive::util::IsUnderDriveMountPoint(path)) { - drive::FileSystemInterface* file_system = - drive::util::GetFileSystemByProfile(chrome_details_.GetProfile()); - if (!file_system) - return RespondNow(Error("Drive not available")); + file_manager::VolumeManager* volume_manager = + file_manager::VolumeManager::Get(chrome_details_.GetProfile()); + DCHECK(volume_manager); - // Ensure that the cache file exists. - const base::FilePath drive_path = drive::util::ExtractDrivePath(path); - file_system->GetFile( - drive_path, - base::BindOnce( - &FileManagerPrivateAddMountFunction::RunAfterGetDriveFile, this, - drive_path)); + bool is_under_downloads = false; + const std::vector<base::WeakPtr<file_manager::Volume>> volumes = + volume_manager->GetVolumeList(); + for (const auto& volume : volumes) { + if (volume->type() == file_manager::VOLUME_TYPE_DOWNLOADS_DIRECTORY && + volume->mount_path().IsParent(path)) { + is_under_downloads = true; + break; + } + } + + if (is_under_downloads) { + // For files under downloads, change the file permission and make it + // readable from avfs/fuse if needed. + base::PostTask( + FROM_HERE, + {base::ThreadPool(), base::MayBlock(), + base::TaskPriority::USER_BLOCKING}, + base::BindOnce(&EnsureReadableFilePermissionAsync, path, + google_apis::CreateRelayCallback(base::BindOnce( + &FileManagerPrivateAddMountFunction:: + RunAfterEnsureReadableFilePermission, + this, path.BaseName())))); } else { - file_manager::VolumeManager* volume_manager = - file_manager::VolumeManager::Get(chrome_details_.GetProfile()); - DCHECK(volume_manager); - - bool is_under_downloads = false; - const std::vector<base::WeakPtr<file_manager::Volume>> volumes = - volume_manager->GetVolumeList(); - for (const auto& volume : volumes) { - if (volume->type() == file_manager::VOLUME_TYPE_DOWNLOADS_DIRECTORY && - volume->mount_path().IsParent(path)) { - is_under_downloads = true; - break; - } - } - - if (is_under_downloads) { - // For files under downloads, change the file permission and make it - // readable from avfs/fuse if needed. - base::PostTask( - FROM_HERE, - {base::ThreadPool(), base::MayBlock(), - base::TaskPriority::USER_BLOCKING}, - base::BindOnce(&EnsureReadableFilePermissionAsync, path, - google_apis::CreateRelayCallback(base::BindOnce( - &FileManagerPrivateAddMountFunction:: - RunAfterMarkCacheFileAsMounted, - this, path.BaseName())))); - } else { - RunAfterMarkCacheFileAsMounted( - path.BaseName(), drive::FILE_ERROR_OK, path); - } + RunAfterEnsureReadableFilePermission(path.BaseName(), drive::FILE_ERROR_OK, + path); } return RespondLater(); } -void FileManagerPrivateAddMountFunction::RunAfterGetDriveFile( - const base::FilePath& drive_path, - drive::FileError error, - const base::FilePath& cache_path, - std::unique_ptr<drive::ResourceEntry> entry) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (error != drive::FILE_ERROR_OK) { - Respond(Error(FileErrorToString(error))); - return; - } - - drive::FileSystemInterface* const file_system = - drive::util::GetFileSystemByProfile(chrome_details_.GetProfile()); - if (!file_system) { - Respond(Error("Drive not available")); - return; - } - - file_system->IsCacheFileMarkedAsMounted( - drive_path, base::BindOnce(&FileManagerPrivateAddMountFunction:: - RunAfterIsCacheFileMarkedAsMounted, - this, drive_path, cache_path)); -} - -void FileManagerPrivateAddMountFunction::RunAfterIsCacheFileMarkedAsMounted( - const base::FilePath& drive_path, - const base::FilePath& cache_path, - drive::FileError error, - bool is_marked_as_mounted) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - if (error != drive::FILE_ERROR_OK) { - Respond(Error(FileErrorToString(error))); - return; - } - if (is_marked_as_mounted) { - // When the file is already mounted, we call the mount function as usual, - // so that it can issue events containing the VolumeInfo, which is - // necessary to make the app navigate to the mounted volume. - RunAfterMarkCacheFileAsMounted(drive_path.BaseName(), drive::FILE_ERROR_OK, - cache_path); - return; - } - drive::FileSystemInterface* const file_system = - drive::util::GetFileSystemByProfile(chrome_details_.GetProfile()); - if (!file_system) { - Respond(Error("Drive not available")); - return; - } - file_system->MarkCacheFileAsMounted( - drive_path, - base::BindOnce( - &FileManagerPrivateAddMountFunction::RunAfterMarkCacheFileAsMounted, - this, drive_path.BaseName())); -} - -void FileManagerPrivateAddMountFunction::RunAfterMarkCacheFileAsMounted( +void FileManagerPrivateAddMountFunction::RunAfterEnsureReadableFilePermission( const base::FilePath& display_name, drive::FileError error, const base::FilePath& file_path) { @@ -266,110 +193,6 @@ return RespondNow(NoArguments()); } -FileManagerPrivateMarkCacheAsMountedFunction:: - FileManagerPrivateMarkCacheAsMountedFunction() - : chrome_details_(this) {} - -ExtensionFunction::ResponseAction -FileManagerPrivateMarkCacheAsMountedFunction::Run() { - using file_manager_private::MarkCacheAsMounted::Params; - const std::unique_ptr<Params> params(Params::Create(*args_)); - EXTENSION_FUNCTION_VALIDATE(params); - - const base::FilePath path(params->source_path); - bool is_mounted = params->is_mounted; - - if (path.empty()) - return RespondNow(Error("Invalid path")); - - if (!drive::util::IsUnderDriveMountPoint(path)) { - // Ignore non-drive files. Treated as success. - return RespondNow(NoArguments()); - } - - drive::FileSystemInterface* file_system = - drive::util::GetFileSystemByProfile(chrome_details_.GetProfile()); - if (!file_system) - return RespondNow(Error("Drive not available")); - - // Ensure that the cache file exists. - const base::FilePath drive_path = drive::util::ExtractDrivePath(path); - file_system->GetFile( - drive_path, - base::BindOnce( - &FileManagerPrivateMarkCacheAsMountedFunction::RunAfterGetDriveFile, - this, drive_path, is_mounted)); - return RespondLater(); -} - -void FileManagerPrivateMarkCacheAsMountedFunction::RunAfterGetDriveFile( - const base::FilePath& drive_path, - bool is_mounted, - drive::FileError error, - const base::FilePath& cache_path, - std::unique_ptr<drive::ResourceEntry> entry) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - if (error != drive::FILE_ERROR_OK) { - Respond(Error(FileErrorToString(error))); - return; - } - - drive::FileSystemInterface* const file_system = - drive::util::GetFileSystemByProfile(chrome_details_.GetProfile()); - if (!file_system) { - Respond(Error("Drive not available")); - return; - } - - // TODO(yamaguchi): Check the current status of the file. - // Currently calling this method twice will result in error, although it - // doesn't give bad side effect. - if (is_mounted) { - file_system->MarkCacheFileAsMounted( - drive_path, - base::BindOnce(&FileManagerPrivateMarkCacheAsMountedFunction:: - RunAfterMarkCacheFileAsMounted, - this)); - } else { - file_system->MarkCacheFileAsUnmounted( - cache_path, base::Bind(&FileManagerPrivateMarkCacheAsMountedFunction:: - RunAfterMarkCacheFileAsUnmounted, - this)); - } -} - -void FileManagerPrivateMarkCacheAsMountedFunction:: - RunAfterMarkCacheFileAsMounted(drive::FileError error, - const base::FilePath& file_path) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - switch (error) { - case drive::FILE_ERROR_INVALID_OPERATION: - // The file was already marked as mounted. Ignore and treat as success. - case drive::FILE_ERROR_OK: - Respond(NoArguments()); - break; - default: - Respond(Error(FileErrorToString(error))); - } -} - -void FileManagerPrivateMarkCacheAsMountedFunction:: - RunAfterMarkCacheFileAsUnmounted(drive::FileError error) { - DCHECK_CURRENTLY_ON(BrowserThread::UI); - - switch (error) { - case drive::FILE_ERROR_INVALID_OPERATION: - // The file was already marked as unmounted. Ignore and treat as success. - case drive::FILE_ERROR_OK: - Respond(NoArguments()); - break; - default: - Respond(Error(FileErrorToString(error))); - } -} - ExtensionFunction::ResponseAction FileManagerPrivateGetVolumeMetadataListFunction::Run() { if (args_->GetSize())
diff --git a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h index 348ebcd..cdb8eab8 100644 --- a/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h +++ b/chrome/browser/chromeos/extensions/file_manager/private_api_mount.h
@@ -33,24 +33,11 @@ ResponseAction Run() override; private: - // Part of Run(). Called after GetFile for Drive File System. - void RunAfterGetDriveFile(const base::FilePath& drive_path, - drive::FileError error, - const base::FilePath& cache_path, - std::unique_ptr<drive::ResourceEntry> entry); - - // Part of Run(). Called after IsCacheMarkedAsMounted for Drive File System. - void RunAfterIsCacheFileMarkedAsMounted(const base::FilePath& display_name, - const base::FilePath& cache_path, - drive::FileError error, - bool is_marked_as_mounted); - - // Part of Run(). Called after MarkCacheFielAsMounted for Drive File System. - // (or directly called from RunAsync() for other file system, or when the - // file is already marked as mounted). - void RunAfterMarkCacheFileAsMounted(const base::FilePath& display_name, - drive::FileError error, - const base::FilePath& file_path); + // Part of Run(). Called after EnsureReadableFilePermissionAsync or when the + // file is on an external drive. + void RunAfterEnsureReadableFilePermission(const base::FilePath& display_name, + drive::FileError error, + const base::FilePath& file_path); const ChromeExtensionFunctionDetails chrome_details_; }; @@ -69,40 +56,6 @@ ResponseAction Run() override; }; -// Implements chrome.fileManagerPrivate.markCacheAsMounted method. -// Marks a cached file as mounted or unmounted. -class FileManagerPrivateMarkCacheAsMountedFunction - : public LoggedExtensionFunction { - public: - FileManagerPrivateMarkCacheAsMountedFunction(); - - DECLARE_EXTENSION_FUNCTION("fileManagerPrivate.markCacheAsMounted", - FILEMANAGERPRIVATE_MARKCACHEASMOUNTED) - - protected: - ~FileManagerPrivateMarkCacheAsMountedFunction() override = default; - - // ExtensionFunction overrides. - ResponseAction Run() override; - - private: - // Part of Run(). Called after GetFile for Drive File System. - void RunAfterGetDriveFile(const base::FilePath& drive_path, - bool is_mounted, - drive::FileError error, - const base::FilePath& cache_path, - std::unique_ptr<drive::ResourceEntry> entry); - - // Part of Run(). Called after MarkCacheFielAsMounted for Drive File System. - void RunAfterMarkCacheFileAsMounted(drive::FileError error, - const base::FilePath& file_path); - - // Part of Run(). Called after MarkCacheFielAsUnmounted for Drive File System. - void RunAfterMarkCacheFileAsUnmounted(drive::FileError error); - - const ChromeExtensionFunctionDetails chrome_details_; -}; - // Implements chrome.fileManagerPrivate.getVolumeMetadataList method. class FileManagerPrivateGetVolumeMetadataListFunction : public LoggedExtensionFunction {
diff --git a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc index 34d4abd6..4253a45 100644 --- a/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc +++ b/chrome/browser/chromeos/file_manager/file_manager_browsertest.cc
@@ -486,6 +486,7 @@ TestCase("dirCreateWithContextMenu"), TestCase("dirCreateWithKeyboard"), TestCase("dirCreateWithoutChangingCurrent"), + TestCase("dirCreateMultipleFolders"), #if !(defined(ADDRESS_SANITIZER) || !defined(NDEBUG)) // Zip tests times out too often on ASAN and DEBUG. crbug.com/936429 // and crbug.com/944697
diff --git a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc index 14135e38..dac90e0 100644 --- a/chrome/browser/chromeos/login/enable_debugging_browsertest.cc +++ b/chrome/browser/chromeos/login/enable_debugging_browsertest.cc
@@ -27,7 +27,7 @@ #include "chrome/common/pref_names.h" #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/fake_update_engine_client.h" #include "chromeos/dbus/power/fake_power_manager_client.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/login/screens/fingerprint_setup_browsertest.cc b/chrome/browser/chromeos/login/screens/fingerprint_setup_browsertest.cc index 334eeb40..e86ce8b 100644 --- a/chrome/browser/chromeos/login/screens/fingerprint_setup_browsertest.cc +++ b/chrome/browser/chromeos/login/screens/fingerprint_setup_browsertest.cc
@@ -147,7 +147,8 @@ WaitForScreenExit(); } -IN_PROC_BROWSER_TEST_F(FingerprintSetupTest, FingerprintDisabled) { +// TODO(https://crbug.com/1009916): Fix flakes and re-enable. +IN_PROC_BROWSER_TEST_F(FingerprintSetupTest, DISABLED_FingerprintDisabled) { quick_unlock::EnabledForTesting(false); fingerprint_setup_screen_->Show();
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc index 8f7693c..2cedeca 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_image_manager.cc
@@ -23,7 +23,7 @@ #include "chrome/browser/download/download_service_factory.h" #include "chrome/browser/profiles/profile.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/download/public/background_service/download_metadata.h" #include "components/download/public/background_service/download_service.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager.cc b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager.cc index ae05f50..58afe21 100644 --- a/chrome/browser/chromeos/plugin_vm/plugin_vm_manager.cc +++ b/chrome/browser/chromeos/plugin_vm/plugin_vm_manager.cc
@@ -20,7 +20,7 @@ #include "chrome/browser/ui/ash/launcher/shelf_spinner_item_controller.h" #include "chrome/grit/generated_resources.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" #include "components/keyed_service/content/browser_context_keyed_service_factory.h" #include "components/prefs/pref_service.h"
diff --git a/chrome/browser/chromeos/printing/printer_configurer.cc b/chrome/browser/chromeos/printing/printer_configurer.cc index d99bb27c..750a7d0 100644 --- a/chrome/browser/chromeos/printing/printer_configurer.cc +++ b/chrome/browser/chromeos/printing/printer_configurer.cc
@@ -24,7 +24,7 @@ #include "chrome/browser/profiles/profile.h" #include "chrome/common/chrome_features.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/printing/ppd_provider.h" #include "chromeos/printing/printer_configuration.h" #include "components/device_event_log/device_event_log.h"
diff --git a/chrome/browser/chromeos/printing/usb_printer_detector.cc b/chrome/browser/chromeos/printing/usb_printer_detector.cc index 77fa7a1..be5d9913 100644 --- a/chrome/browser/chromeos/printing/usb_printer_detector.cc +++ b/chrome/browser/chromeos/printing/usb_printer_detector.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/chromeos/printing/synced_printers_manager_factory.h" #include "chrome/browser/chromeos/printing/usb_printer_util.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/printing/ppd_provider.h" #include "chromeos/printing/usb_printer_id.h" #include "content/public/browser/browser_task_traits.h"
diff --git a/chrome/browser/chromeos/scheduler_configuration_manager.cc b/chrome/browser/chromeos/scheduler_configuration_manager.cc index b2cfb62..57c7390 100644 --- a/chrome/browser/chromeos/scheduler_configuration_manager.cc +++ b/chrome/browser/chromeos/scheduler_configuration_manager.cc
@@ -10,7 +10,7 @@ #include "base/metrics/field_trial_params.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
diff --git a/chrome/browser/chromeos/scheduler_configuration_manager_unittest.cc b/chrome/browser/chromeos/scheduler_configuration_manager_unittest.cc index 842b58f..bbf341a7 100644 --- a/chrome/browser/chromeos/scheduler_configuration_manager_unittest.cc +++ b/chrome/browser/chromeos/scheduler_configuration_manager_unittest.cc
@@ -10,7 +10,7 @@ #include "base/test/task_environment.h" #include "chrome/common/chrome_features.h" #include "chrome/common/pref_names.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "components/prefs/testing_pref_service.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
diff --git a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc index 12b4767..7cd7e81 100644 --- a/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc +++ b/chrome/browser/chromeos/system_logs/debug_daemon_log_source.cc
@@ -19,7 +19,7 @@ #include "chrome/browser/chromeos/profiles/profile_helper.h" #include "chrome/common/chrome_switches.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/user_manager/user.h" #include "components/user_manager/user_manager.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/system_logs/debug_log_writer.cc b/chrome/browser/chromeos/system_logs/debug_log_writer.cc index 29ee057..ec4a8239 100644 --- a/chrome/browser/chromeos/system_logs/debug_log_writer.cc +++ b/chrome/browser/chromeos/system_logs/debug_log_writer.cc
@@ -20,7 +20,7 @@ #include "base/task/post_task.h" #include "chrome/common/logging_chrome.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h"
diff --git a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc index d62ae25..94fbe327 100644 --- a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc +++ b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source.cc
@@ -8,7 +8,7 @@ #include "base/bind.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "content/public/browser/browser_thread.h" namespace system_logs {
diff --git a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc index cf8f2d3..3654eb60 100644 --- a/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc +++ b/chrome/browser/chromeos/system_logs/single_debug_daemon_log_source_unittest.cc
@@ -11,7 +11,7 @@ #include "base/macros.h" #include "base/run_loop.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/chromeos/u2f_notification.cc b/chrome/browser/chromeos/u2f_notification.cc index 7c5a0fd..ccefb33 100644 --- a/chrome/browser/chromeos/u2f_notification.cc +++ b/chrome/browser/chromeos/u2f_notification.cc
@@ -22,7 +22,7 @@ #include "chrome/browser/ui/browser_navigator_params.h" #include "chrome/grit/generated_resources.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/policy/proto/chrome_device_policy.pb.h" #include "components/strings/grit/components_strings.h" #include "third_party/cros_system_api/dbus/debugd/dbus-constants.h"
diff --git a/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc b/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc index c9e2a02..8ee1b0a 100644 --- a/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc +++ b/chrome/browser/dom_distiller/lazy_dom_distiller_service.cc
@@ -50,22 +50,6 @@ return instance()->GetUrlForEntry(entry_id); } -const std::string LazyDomDistillerService::AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) { - return instance()->AddToList(url, std::move(distiller_page), article_cb); -} - -std::vector<ArticleEntry> LazyDomDistillerService::GetEntries() const { - return instance()->GetEntries(); -} - -std::unique_ptr<ArticleEntry> LazyDomDistillerService::RemoveEntry( - const std::string& entry_id) { - return instance()->RemoveEntry(entry_id); -} - std::unique_ptr<ViewerHandle> LazyDomDistillerService::ViewEntry( ViewRequestDelegate* delegate, std::unique_ptr<DistillerPage> distiller_page,
diff --git a/chrome/browser/dom_distiller/lazy_dom_distiller_service.h b/chrome/browser/dom_distiller/lazy_dom_distiller_service.h index 97a18f51..a7adba3 100644 --- a/chrome/browser/dom_distiller/lazy_dom_distiller_service.h +++ b/chrome/browser/dom_distiller/lazy_dom_distiller_service.h
@@ -36,15 +36,8 @@ public: // DomDistillerServiceInterface implementation: - const std::string AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) override; bool HasEntry(const std::string& entry_id) override; std::string GetUrlForEntry(const std::string& entry_id) override; - std::vector<ArticleEntry> GetEntries() const override; - std::unique_ptr<ArticleEntry> RemoveEntry( - const std::string& entry_id) override; std::unique_ptr<ViewerHandle> ViewEntry( ViewRequestDelegate* delegate, std::unique_ptr<DistillerPage> distiller_page,
diff --git a/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc b/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc index 103677b..59e65740 100644 --- a/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc +++ b/chrome/browser/media/webrtc/webrtc_video_display_perf_browsertest.cc
@@ -450,7 +450,15 @@ std::vector<double> webrtc_decode_latencies_; }; -INSTANTIATE_TEST_SUITE_P(WebRtcVideoDisplayPerfBrowserTests, +// TODO(https://crbug.com/993020): Fix flakes on Windows bots. +#if defined(OS_WIN) +#define MAYBE_WebRtcVideoDisplayPerfBrowserTests \ + DISABLED_WebRtcVideoDisplayPerfBrowserTests +#else +#define MAYBE_WebRtcVideoDisplayPerfBrowserTests \ + WebRtcVideoDisplayPerfBrowserTests +#endif +INSTANTIATE_TEST_SUITE_P(MAYBE_WebRtcVideoDisplayPerfBrowserTests, WebRtcVideoDisplayPerfBrowserTest, testing::Combine(testing::Values(gfx::Size(1280, 720), gfx::Size(1920,
diff --git a/chrome/browser/metrics/perf/perf_events_collector.cc b/chrome/browser/metrics/perf/perf_events_collector.cc index e7eae5b..b0f49d915 100644 --- a/chrome/browser/metrics/perf/perf_events_collector.cc +++ b/chrome/browser/metrics/perf/perf_events_collector.cc
@@ -21,6 +21,7 @@ #include "chrome/browser/metrics/perf/process_type_collector.h" #include "chrome/browser/metrics/perf/windowed_incognito_observer.h" #include "chrome/browser/ui/browser_list.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client_provider.h" #include "components/variations/variations_associated_data.h" #include "third_party/metrics_proto/sampled_profile.pb.h" @@ -256,7 +257,8 @@ // Create DebugdClientProvider to bind its private DBus connection to the // current sequence. - debugd_client_provider_ = std::make_unique<DebugdClientProvider>(); + debugd_client_provider_ = + std::make_unique<chromeos::DebugDaemonClientProvider>(); auto task_runner = base::SequencedTaskRunnerHandle::Get(); base::PostTask(
diff --git a/chrome/browser/metrics/perf/perf_events_collector.h b/chrome/browser/metrics/perf/perf_events_collector.h index 9f13c2e..2a13c9e 100644 --- a/chrome/browser/metrics/perf/perf_events_collector.h +++ b/chrome/browser/metrics/perf/perf_events_collector.h
@@ -19,10 +19,13 @@ class SequencedTaskRunner; } +namespace chromeos { +class DebugDaemonClientProvider; +} // namespace chromeos + namespace metrics { struct CPUIdentity; -class DebugdClientProvider; class WindowedIncognitoObserver; // Enables collection of perf events profile data. perf aka "perf events" is a @@ -112,7 +115,7 @@ RandomSelector command_selector_; // |debugd_client_provider_| hosts the private DBus connection to debugd. - std::unique_ptr<DebugdClientProvider> debugd_client_provider_; + std::unique_ptr<chromeos::DebugDaemonClientProvider> debugd_client_provider_; // An active call to perf/quipper, if set. std::unique_ptr<PerfOutputCall> perf_output_call_;
diff --git a/chrome/browser/metrics/perf/perf_output.cc b/chrome/browser/metrics/perf/perf_output.cc index 1bcf9b65..ed9e06f 100644 --- a/chrome/browser/metrics/perf/perf_output.cc +++ b/chrome/browser/metrics/perf/perf_output.cc
@@ -7,7 +7,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/task/post_task.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "dbus/bus.h" #include "dbus/message.h" #include "dbus/object_path.h" @@ -16,29 +16,6 @@ namespace metrics { -DebugdClientProvider::DebugdClientProvider() - : dbus_task_runner_(base::CreateSingleThreadTaskRunner( - {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, - base::MayBlock()})), - debug_daemon_client_(chromeos::DebugDaemonClient::Create()) { - dbus::Bus::Options dbus_options; - dbus_options.bus_type = dbus::Bus::SYSTEM; - dbus_options.connection_type = dbus::Bus::PRIVATE; - dbus_options.dbus_task_runner = dbus_task_runner_; - dbus_bus_ = base::MakeRefCounted<dbus::Bus>(dbus_options); - - debug_daemon_client_->Init(dbus_bus_.get()); -} - -DebugdClientProvider::~DebugdClientProvider() { - DCHECK(debug_daemon_client_); - DCHECK(dbus_bus_); - - debug_daemon_client_ = nullptr; - dbus_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&dbus::Bus::ShutdownAndBlock, dbus_bus_)); -} - PerfOutputCall::PerfOutputCall(chromeos::DebugDaemonClient* debug_daemon_client, base::TimeDelta duration, const std::vector<std::string>& perf_args,
diff --git a/chrome/browser/metrics/perf/perf_output.h b/chrome/browser/metrics/perf/perf_output.h index 0851e336..59729e5c 100644 --- a/chrome/browser/metrics/perf/perf_output.h +++ b/chrome/browser/metrics/perf/perf_output.h
@@ -21,32 +21,8 @@ class DebugDaemonClient; } // namespace chromeos -namespace dbus { -class Bus; -} // namespace dbus - namespace metrics { -// This class hosts a private DBus connection for perf collection. The collector -// sequence acts as the origin thread of the DBus Bus and ObjectProxy objects. -class DebugdClientProvider { - public: - DebugdClientProvider(); - ~DebugdClientProvider(); - - chromeos::DebugDaemonClient* debug_daemon_client() const { - return debug_daemon_client_.get(); - } - - private: - // The private bus. - scoped_refptr<dbus::Bus> dbus_bus_; - scoped_refptr<base::SequencedTaskRunner> dbus_task_runner_; - std::unique_ptr<chromeos::DebugDaemonClient> debug_daemon_client_; - - DISALLOW_COPY_AND_ASSIGN(DebugdClientProvider); -}; - // Class for handling getting output from perf over DBus. Manages the // asynchronous DBus call and retrieving data from quipper over a pipe. class PerfOutputCall {
diff --git a/chrome/browser/metrics/perf/perf_output_unittest.cc b/chrome/browser/metrics/perf/perf_output_unittest.cc index cf4012ba..8a771ce 100644 --- a/chrome/browser/metrics/perf/perf_output_unittest.cc +++ b/chrome/browser/metrics/perf/perf_output_unittest.cc
@@ -12,7 +12,7 @@ #include "base/task/post_task.h" #include "base/threading/sequenced_task_runner_handle.h" #include "base/threading/thread_restrictions.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h" #include "third_party/metrics_proto/sampled_profile.pb.h"
diff --git a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc index 7973a93..1efe4f7 100644 --- a/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc +++ b/chrome/browser/page_load_metrics/page_load_metrics_browsertest.cc
@@ -958,8 +958,14 @@ .empty()); } +// TODO(crbug.com/1009885): Flaky on Linux MSan builds. +#if defined(MEMORY_SANITIZER) && defined(OS_LINUX) +#define MAYBE_FirstMeaningfulPaintRecorded DISABLED_FirstMeaningfulPaintRecorded +#else +#define MAYBE_FirstMeaningfulPaintRecorded FirstMeaningfulPaintRecorded +#endif IN_PROC_BROWSER_TEST_F(PageLoadMetricsBrowserTest, - FirstMeaningfulPaintRecorded) { + MAYBE_FirstMeaningfulPaintRecorded) { ASSERT_TRUE(embedded_test_server()->Start()); auto waiter = CreatePageLoadMetricsTestWaiter();
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc index 7340dd2..dd2129c6 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator.cc +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator.cc
@@ -34,6 +34,49 @@ return base::FeatureList::IsEnabled(features::kPolicyFcmInvalidations); } +// Get the kMetricPolicyInvalidations histogram metric which should be +// incremented when an invalidation is received. +MetricPolicyRefresh GetPolicyRefreshMetric(bool invalidations_enabled, + bool policy_changed, + bool invalidated) { + if (policy_changed) { + if (invalidated) + return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED; + if (invalidations_enabled) + return METRIC_POLICY_REFRESH_CHANGED; + return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS; + } + if (invalidated) + return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED; + return METRIC_POLICY_REFRESH_UNCHANGED; +} + +void RecordPolicyRefreshMetric( + enterprise_management::DeviceRegisterRequest::Type type, + bool invalidations_enabled, + bool policy_changed, + bool invalidated) { + MetricPolicyRefresh metric_policy_refresh = GetPolicyRefreshMetric( + invalidations_enabled, policy_changed, invalidated); + if (type == enterprise_management::DeviceRegisterRequest::DEVICE) { + base::UmaHistogramEnumeration(kMetricDevicePolicyRefresh, + metric_policy_refresh, + METRIC_POLICY_REFRESH_SIZE); + base::UmaHistogramEnumeration( + IsFcmEnabled() ? kMetricDevicePolicyRefreshFcm + : kMetricDevicePolicyRefreshTicl, + metric_policy_refresh, METRIC_POLICY_REFRESH_SIZE); + } else { + base::UmaHistogramEnumeration(kMetricUserPolicyRefresh, + metric_policy_refresh, + METRIC_POLICY_REFRESH_SIZE); + base::UmaHistogramEnumeration(IsFcmEnabled() ? kMetricUserPolicyRefreshFcm + : kMetricUserPolicyRefreshTicl, + metric_policy_refresh, + METRIC_POLICY_REFRESH_SIZE); + } +} + } // namespace const int CloudPolicyInvalidator::kMissingPayloadDelay = 5; @@ -172,32 +215,18 @@ bool policy_changed = IsPolicyChanged(store->policy()); if (is_registered_) { - // Update the kMetricDevicePolicyRefresh/kMetricUserPolicyRefresh histogram. - MetricPolicyRefresh metric_policy_refresh = - GetPolicyRefreshMetric(policy_changed); - if (type_ == enterprise_management::DeviceRegisterRequest::DEVICE) { - base::UmaHistogramEnumeration(kMetricDevicePolicyRefresh, - metric_policy_refresh, - METRIC_POLICY_REFRESH_SIZE); - base::UmaHistogramEnumeration( - IsFcmEnabled() ? kMetricDevicePolicyRefreshFcm - : kMetricDevicePolicyRefreshTicl, - metric_policy_refresh, METRIC_POLICY_REFRESH_SIZE); - } else { - base::UmaHistogramEnumeration(kMetricUserPolicyRefresh, - metric_policy_refresh, - METRIC_POLICY_REFRESH_SIZE); - base::UmaHistogramEnumeration( - IsFcmEnabled() ? kMetricUserPolicyRefreshFcm - : kMetricUserPolicyRefreshTicl, - metric_policy_refresh, METRIC_POLICY_REFRESH_SIZE); - } - const int64_t store_invalidation_version = store->invalidation_version(); + // Whether the refresh was caused by invalidation. + const bool invalidated = + invalid_ && store_invalidation_version == invalidation_version_; + + bool invalidations_enabled = GetInvalidationsEnabled(); + RecordPolicyRefreshMetric(type_, invalidations_enabled, policy_changed, + invalidated); // If the policy was invalid and the version stored matches the latest // invalidation version, acknowledge the latest invalidation. - if (invalid_ && store_invalidation_version == invalidation_version_) + if (invalidated) AcknowledgeInvalidation(); // Update the highest invalidation version that was handled already. @@ -450,20 +479,6 @@ return invalidation_time < last_fetch_time; } -MetricPolicyRefresh CloudPolicyInvalidator::GetPolicyRefreshMetric( - bool policy_changed) { - if (policy_changed) { - if (invalid_) - return METRIC_POLICY_REFRESH_INVALIDATED_CHANGED; - if (GetInvalidationsEnabled()) - return METRIC_POLICY_REFRESH_CHANGED; - return METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS; - } - if (invalid_) - return METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED; - return METRIC_POLICY_REFRESH_UNCHANGED; -} - PolicyInvalidationType CloudPolicyInvalidator::GetInvalidationMetric( bool is_missing_payload, bool is_expired) {
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator.h b/chrome/browser/policy/cloud/cloud_policy_invalidator.h index d58ded6..06c4722c 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator.h +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator.h
@@ -156,10 +156,6 @@ // |version| is the version of the invalidation, or zero for unknown. bool IsInvalidationExpired(int64_t version); - // Get the kMetricPolicyRefresh histogram metric which should be incremented - // when a policy is stored. - MetricPolicyRefresh GetPolicyRefreshMetric(bool policy_changed); - // Get the kMetricPolicyInvalidations histogram metric which should be // incremented when an invalidation is received. PolicyInvalidationType GetInvalidationMetric(bool is_missing_payload,
diff --git a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc index c927d94..5b128e3 100644 --- a/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc +++ b/chrome/browser/policy/cloud/cloud_policy_invalidator_unittest.cc
@@ -1193,8 +1193,7 @@ } TEST_P(CloudPolicyInvalidatorUserTypedTest, RefreshMetricsInvalidation) { - // Store loads after an invalidation are counted as invalidated, even if - // the loads do not result in the invalidation being acknowledged. + // Store loads after an invalidation are not counted as invalidated. StartInvalidator(); StorePolicy(POLICY_OBJECT_A); AdvanceClock(base::TimeDelta::FromSeconds( @@ -1216,11 +1215,11 @@ StorePolicy(POLICY_OBJECT_A, 0, true /* policy_changed */); StorePolicy(POLICY_OBJECT_A, 0, false /* policy_changed */); - EXPECT_EQ(3, GetCount(METRIC_POLICY_REFRESH_CHANGED)); + EXPECT_EQ(4, GetCount(METRIC_POLICY_REFRESH_CHANGED)); EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_CHANGED_NO_INVALIDATIONS)); - EXPECT_EQ(4, GetCount(METRIC_POLICY_REFRESH_UNCHANGED)); - EXPECT_EQ(2, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED)); - EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED)); + EXPECT_EQ(5, GetCount(METRIC_POLICY_REFRESH_UNCHANGED)); + EXPECT_EQ(1, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_CHANGED)); + EXPECT_EQ(0, GetCount(METRIC_POLICY_REFRESH_INVALIDATED_UNCHANGED)); EXPECT_EQ(GetCount(METRIC_POLICY_REFRESH_CHANGED), is_fcm_enabled() ? GetCountFcm(METRIC_POLICY_REFRESH_CHANGED)
diff --git a/chrome/browser/profiles/profile_android.cc b/chrome/browser/profiles/profile_android.cc index 3a49222..32a0843 100644 --- a/chrome/browser/profiles/profile_android.cc +++ b/chrome/browser/profiles/profile_android.cc
@@ -11,6 +11,7 @@ #include "chrome/browser/profiles/profile_destroyer.h" #include "chrome/browser/profiles/profile_key_android.h" #include "chrome/browser/profiles/profile_manager.h" +#include "content/public/browser/web_contents.h" using base::android::AttachCurrentThread; using base::android::JavaParamRef; @@ -124,6 +125,23 @@ return ProfileAndroid::GetLastUsedProfile(env); } +// static +ScopedJavaLocalRef<jobject> JNI_Profile_FromWebContents( + JNIEnv* env, + const JavaParamRef<jobject>& jweb_contents) { + auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents); + if (!web_contents) + return ScopedJavaLocalRef<jobject>(); + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + if (!profile) + return ScopedJavaLocalRef<jobject>(); + ProfileAndroid* profile_android = ProfileAndroid::FromProfile(profile); + if (!profile_android) + return ScopedJavaLocalRef<jobject>(); + return profile_android->GetJavaObject(); +} + ProfileAndroid::ProfileAndroid(Profile* profile) : profile_(profile) { JNIEnv* env = AttachCurrentThread();
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h index c33a3d3eb..cc8d7c8 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos.h
@@ -24,7 +24,7 @@ #include "chrome/browser/resource_coordinator/lifecycle_unit_state.mojom.h" #include "chrome/browser/resource_coordinator/tab_manager.h" #include "chrome/browser/ui/browser_list_observer.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "components/arc/mojom/process.mojom.h" #include "content/public/browser/notification_observer.h" #include "content/public/browser/notification_registrar.h"
diff --git a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc index b4cb348..ce55819 100644 --- a/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc +++ b/chrome/browser/resource_coordinator/tab_manager_delegate_chromeos_unittest.cc
@@ -15,7 +15,7 @@ #include "base/time/time.h" #include "chrome/browser/resource_coordinator/test_lifecycle_unit.h" #include "chrome/browser/resource_coordinator/time.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/resources/chromeos/camera/.eslintrc.js b/chrome/browser/resources/chromeos/camera/.eslintrc.js index bb791539..7f96ae2 100644 --- a/chrome/browser/resources/chromeos/camera/.eslintrc.js +++ b/chrome/browser/resources/chromeos/camera/.eslintrc.js
@@ -147,6 +147,7 @@ }, 'extends': 'eslint:recommended', 'globals': { + 'arc': 'readable', // Adds BigInt64Array here since current version of eslint does not treat // BigInt64Array as a defined type. 'BigInt64Array': 'readable',
diff --git a/chrome/browser/resources/chromeos/camera/BUILD.gn b/chrome/browser/resources/chromeos/camera/BUILD.gn index 0aa961c3..83a2fb78 100644 --- a/chrome/browser/resources/chromeos/camera/BUILD.gn +++ b/chrome/browser/resources/chromeos/camera/BUILD.gn
@@ -112,6 +112,7 @@ "src/js/background.js", "src/js/gallerybutton.js", "src/js/google-analytics-bundle.js", + "src/js/intent.js", "src/js/main.js", "src/js/metrics.js", "src/js/nav.js", @@ -247,6 +248,7 @@ deps = [ "//components/arc/mojom:camera_intent_js", + "//components/arc/mojom:mojom_js", "//components/chromeos_camera/common:camera_app_helper_js", "//media/capture/mojom:image_capture_js", "//media/capture/video/chromeos/mojom:cros_camera_js",
diff --git a/chrome/browser/resources/chromeos/camera/Makefile b/chrome/browser/resources/chromeos/camera/Makefile index 0f44a224..721778c 100644 --- a/chrome/browser/resources/chromeos/camera/Makefile +++ b/chrome/browser/resources/chromeos/camera/Makefile
@@ -121,6 +121,7 @@ src/js/device/device_info_updater.js \ src/js/gallerybutton.js \ src/js/google-analytics-bundle.js \ + src/js/intent.js \ src/js/main.js \ src/js/metrics.js \ src/js/models/filenamer.js \
diff --git a/chrome/browser/resources/chromeos/camera/camera_resources.grd b/chrome/browser/resources/chromeos/camera/camera_resources.grd index 64a35da2..59f7a2a 100644 --- a/chrome/browser/resources/chromeos/camera/camera_resources.grd +++ b/chrome/browser/resources/chromeos/camera/camera_resources.grd
@@ -28,6 +28,7 @@ <structure name="IDR_CAMERA_GALLERY_JS" file="src/js/models/gallery.js" type="chrome_html" /> <structure name="IDR_CAMERA_GALLERYBUTTON_JS" file="src/js/gallerybutton.js" type="chrome_html" /> <structure name="IDR_CAMERA_IMAGECAPTURE_JS" file="src/js/mojo/image_capture.js" type="chrome_html" /> + <structure name="IDR_CAMERA_INTENT_JS" file="src/js/intent.js" type="chrome_html" /> <structure name="IDR_CAMERA_LAYOUT_JS" file="src/js/views/camera/layout.js" type="chrome_html" /> <structure name="IDR_CAMERA_MAIN_CSS" file="src/css/main.css" type="chrome_html" /> <structure name="IDR_CAMERA_MAIN_HTML" file="src/views/main.html" type="chrome_html" />
diff --git a/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json b/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json index f310dcc..74f0abc 100644 --- a/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json +++ b/chrome/browser/resources/chromeos/camera/src/_locales/en/messages.json
@@ -95,6 +95,14 @@ "message": "Grid type", "description": "Label for the button of grid-type options." }, + "LABEL_30FPS": { + "message": "30 FPS", + "description": "Label showing current state of 30 FPS on tooltip of toggle 60 FPS recording checkbox." + }, + "LABEL_60FPS": { + "message": "60 FPS", + "description": "Label showing current state of 60 FPS on tooltip of toggle 60 FPS recording checkbox." + }, "TOGGLE_60FPS_BUTTON": { "message": "60 FPS", "description": "Label for the checkbox to toggle 60 FPS recording."
diff --git a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn index 6b07399f..64d48a3 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn +++ b/chrome/browser/resources/chromeos/camera/src/js/BUILD.gn
@@ -17,6 +17,8 @@ js_type_check("compile_resources") { deps = [ + ":background", + ":intent", ":nav", ":resolution_event_broker", ":state", @@ -26,6 +28,12 @@ ] } +js_library("intent") { + deps = [ + "mojo:chrome_helper", + ] +} + js_library("resolution_event_broker") { } @@ -39,6 +47,12 @@ js_library("state") { } +js_library("background") { + deps = [ + ":intent", + ] +} + js_library("toast") { deps = [ ":util",
diff --git a/chrome/browser/resources/chromeos/camera/src/js/background.js b/chrome/browser/resources/chromeos/camera/src/js/background.js index ce7c134..173e4f05 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/background.js +++ b/chrome/browser/resources/chromeos/camera/src/js/background.js
@@ -38,53 +38,419 @@ /** * It's used in test to ensure that we won't connect to the main.html target * before the window is created, otherwise the window might disappear. - * @type {?function(): undefined} + * @type {?function(*): undefined} */ cca.bg.onAppWindowCreatedForTesting = null; /** - * Creates the window. Note, that only one window at once is supported. + * Background object for handling launch event. + * @type {?cca.bg.Background} */ -cca.bg.create = function() { - new Promise((resolve) => { - chrome.storage.local.get( - {maximized: false, fullscreen: false}, (values) => { - resolve(values.maximized || values.fullscreen); - }); - }).then((maximized) => { +cca.bg.background = null; + +/** + * State of cca.bg.Window. + * @enum {string} + */ +cca.bg.WindowState = { + UNINIT: 'uninitialized', + LAUNCHING: 'launching', + ACTIVE: 'active', + SUSPENDING: 'suspending', + SUSPENDED: 'suspended', + RESUMING: 'resuming', + CLOSING: 'closing', + CLOSED: 'closed', +}; + +/* eslint-disable no-unused-vars */ + +/** + * @typedef {{ + * suspend: !function(), + * resume: !function(), + * }} + */ +cca.bg.WindowOperations; + +/* eslint-enable no-unused-vars */ + +/** + * Wrapper of AppWindow for tracking its state. + */ +cca.bg.Window = class { + /** + * @param {!function(cca.bg.Window)} onActive Called when window become active + * state. + * @param {!function(cca.bg.Window)} onSuspended Called when window become + * suspended state. + * @param {!function(cca.bg.Window)} onClosed Called when window become closed + * state. + * @param {cca.intent.Intent=} intent Intent to be handled by the app window. + * Set to null for app window not launching from intent. + */ + constructor(onActive, onSuspended, onClosed, intent = null) { + /** + * @type {!function(!cca.bg.Window)} + * @private + */ + this.onActive_ = onActive; + + /** + * @type {!function(!cca.bg.Window)} + * @private + */ + this.onSuspended_ = onSuspended; + + /** + * @type {!function(!cca.bg.Window)} + * @private + */ + this.onClosed_ = onClosed; + + /** + * @type {?cca.intent.Intent} + * @private + */ + this.intent_ = intent; + + /** + * @type {?chrome.app.window.AppWindow} + * @private + */ + this.appWindow_ = null; + + /** + * @type {!cca.bg.WindowState} + * @private + */ + this.state_ = cca.bg.WindowState.UNINIT; + } + + /** + * Gets state of the window. + * @return {cca.bg.WindowState} + */ + get state() { + return this.state_; + } + + /** + * Creates app window and launches app. + */ + launch() { + this.state_ = cca.bg.WindowState.LAUNCHING; + // The height will be later calculated to match video aspect ratio once the // stream is available. - var initialHeight = Math.round( - cca.bg.MIN_WIDTH / cca.bg.INITIAL_ASPECT_RATIO); + var initialHeight = + Math.round(cca.bg.MIN_WIDTH / cca.bg.INITIAL_ASPECT_RATIO); - chrome.app.window.create('views/main.html', { - id: 'main', - frame: {color: cca.bg.TOPBAR_COLOR}, - hidden: true, // Will be shown from main.js once loaded. - innerBounds: { - width: cca.bg.MIN_WIDTH, - height: initialHeight, - minWidth: cca.bg.MIN_WIDTH, - left: Math.round((window.screen.availWidth - cca.bg.MIN_WIDTH) / 2), - top: Math.round((window.screen.availHeight - initialHeight) / 2), - }, - }, (inAppWindow) => { - // Temporary workaround for crbug.com/452737. - // 'state' option in CreateWindowOptions is ignored when a window is - // launched with 'hidden' option, so we restore window state here. - // Don't launch in fullscreen as the topbar might not work as expected. - if (maximized) { - inAppWindow.maximize(); + const windowId = + this.intent_ !== null ? `main-${this.intent_.intentId}` : 'main'; + const windowUrl = 'views/main.html' + + (this.intent_ !== null ? this.intent_.url.search : ''); + + chrome.app.window.create( + windowUrl, { + id: windowId, + frame: {color: cca.bg.TOPBAR_COLOR}, + hidden: true, // Will be shown from main.js once loaded. + innerBounds: { + width: cca.bg.MIN_WIDTH, + height: initialHeight, + minWidth: cca.bg.MIN_WIDTH, + left: Math.round((window.screen.availWidth - cca.bg.MIN_WIDTH) / 2), + top: Math.round((window.screen.availHeight - initialHeight) / 2), + }, + }, + (appWindow) => { + this.appWindow_ = appWindow; + this.appWindow_.onClosed.addListener(() => { + chrome.storage.local.set({maximized: appWindow.isMaximized()}); + chrome.storage.local.set({fullscreen: appWindow.isFullscreen()}); + this.state_ = cca.bg.WindowState.CLOSED; + if (this.intent_ !== null && !this.intent_.done) { + this.intent_.cancel(); + } + this.onClosed_(this); + }); + const wnd = appWindow.contentWindow; + wnd.intent = this.intent_; + wnd.onActive = () => { + this.state_ = cca.bg.WindowState.ACTIVE; + // For intent only requiring open camera with specific mode without + // returning the capture result, called onIntentHandled() right + // after app successfully launched. + if (this.intent_ !== null && !this.intent_.shouldHandleResult) { + this.intent_.finish(); + } + this.onActive_(this); + }; + wnd.onSuspended = () => { + this.state_ = cca.bg.WindowState.SUSPENDED; + this.onSuspended_(this); + }; + if (cca.bg.onAppWindowCreatedForTesting !== null) { + cca.bg.onAppWindowCreatedForTesting(null); + } + }); + } + + /** + * Gets WindowOperations associated with this window. + * @return {!cca.bg.WindowOperations} + * @throws {Error} Throws when no WindowOperations is associated with the + * window. + * @private + */ + getWindowOps_() { + const ops = + /** @type {(!cca.bg.WindowOperations|undefined)} */ ( + this.appWindow_.contentWindow['ops']); + if (ops === undefined) { + throw new Error('WindowOperations not found on target window.'); + } + return ops; + } + + /** + * Suspends the app window. + */ + suspend() { + if (this.state_ === cca.bg.WindowState.LAUNCHING) { + console.error('Call suspend() while window is still launching.'); + return; + } + this.state_ = cca.bg.WindowState.SUSPENDING; + this.getWindowOps_().suspend(); + } + + /** + * Resumes the app window. + */ + resume() { + this.state_ = cca.bg.WindowState.RESUMING; + this.getWindowOps_().resume(); + } + + /** + * Closes the app window. + */ + close() { + this.state_ = cca.bg.WindowState.CLOSING; + this.appWindow_.close(); + } +}; + +/** + * Launch event handler runs in background. + */ +cca.bg.Background = class { + /** + */ + constructor() { + /** + * Launch window handles launch event triggered from app launcher. + * @type {?cca.bg.Window} + * @private + */ + this.launcherWindow_ = null; + + /** + * Intent window handles launch event triggered from ARC++ intent. + * @type {?cca.bg.Window} + * @private + */ + this.intentWindow_ = null; + + /** + * The pending intent arrived when foreground window is busy. + * @type {?cca.intent.Intent} + */ + this.pendingIntent_ = null; + } + + /** + * Checks and logs any violation of background transition logic. + * @param {boolean} assertion Condition to be asserted. + * @param {string|function(): string} message Logged message. + * @private + */ + assert_(assertion, message) { + if (!assertion) { + console.error(typeof message === 'string' ? message : message()); + } + // TODO(inker): Cleans up states and starts over after any violation. + } + + /** + * Processes the pending intent. + * @private + */ + processPendingIntent_() { + if (!this.pendingIntent_) { + console.error('Call processPendingIntent_() without intent present.'); + return; + } + this.intentWindow_ = this.createIntentWindow_(this.pendingIntent_); + this.pendingIntent_ = null; + this.intentWindow_.launch(); + } + + /** + * Returns a Window object handling launch event triggered from app launcher. + * @return {!cca.bg.Window} + * @private + */ + createLauncherWindow_() { + const onActive = (wnd) => { + this.assert_(wnd === this.launcherWindow_, 'Wrong active launch window.'); + this.assert_( + !this.intentWindow_, + 'Launch window is active while handling intent window.'); + if (this.pendingIntent_ !== null) { + wnd.suspend(); } - inAppWindow.onClosed.addListener(() => { - chrome.storage.local.set({maximized: inAppWindow.isMaximized()}); - chrome.storage.local.set({fullscreen: inAppWindow.isFullscreen()}); - }); - if (cca.bg.onAppWindowCreatedForTesting !== null) { - cca.bg.onAppWindowCreatedForTesting(); + }; + const onSuspended = (wnd) => { + this.assert_( + wnd === this.launcherWindow_, 'Wrong suspended launch window.'); + this.assert_( + !this.intentWindow_, + 'Launch window is suspended while handling intent window.'); + if (this.pendingIntent_ === null) { + this.assert_( + false, 'Launch window is not suspended by some pending intent'); + wnd.resume(); + return; } - }); - }); + this.processPendingIntent_(); + }; + const onClosed = (wnd) => { + this.assert_(wnd === this.launcherWindow_, 'Wrong closed launch window.'); + this.launcherWindow_ = null; + if (this.pendingIntent_ !== null) { + this.processPendingIntent_(); + } + }; + return new cca.bg.Window(onActive, onSuspended, onClosed); + } + + /** + * Returns a Window object handling launch event triggered from ARC++ intent. + * @param {!cca.intent.Intent} intent Intent forwarding from ARC++. + * @return {!cca.bg.Window} + * @private + */ + createIntentWindow_(intent) { + const onActive = (wnd) => { + this.assert_(wnd === this.intentWindow_, 'Wrong active intent window.'); + this.assert_( + !this.launcherWindow_ || + this.launcherWindow_.state === cca.bg.WindowState.SUSPENDED, + () => `Launch window is ${ + this.launcherWindow_.state} when intent window is active.`); + if (this.pendingIntent_) { + wnd.close(); + } + }; + const onSuspended = (wnd) => { + this.assert_( + wnd === this.intentWindow_, 'Wrong suspended intent window.'); + this.assert_(false, 'Intent window should not be suspended.'); + }; + const onClosed = (wnd) => { + this.assert_(wnd === this.intentWindow_, 'Wrong closed intent window.'); + this.assert_( + !this.launcherWindow_ || + this.launcherWindow_.state === cca.bg.WindowState.SUSPENDED, + () => `Launch window is ${ + this.launcherWindow_.state} when intent window is closed.`); + this.intentWindow_ = null; + if (this.pendingIntent_) { + this.processPendingIntent_(); + } else if (this.launcherWindow_) { + this.launcherWindow_.resume(); + } + }; + return new cca.bg.Window(onActive, onSuspended, onClosed, intent); + } + + /** + * Handles launch event triggered from app launcher. + */ + launchApp() { + if (this.launcherWindow_ || this.intentWindow_) { + return; + } + this.assert_( + !this.pendingIntent_, + 'Pending intent is not processed when launch new window.'); + this.launcherWindow_ = this.createLauncherWindow_(); + this.launcherWindow_.launch(); + } + + /** + * Closes the existing pending intent and replaces it with a new incoming + * intent. + * @param {!cca.intent.Intent} intent New incoming intent. + * @private + */ + replacePendingIntent_(intent) { + if (this.pendingIntent_) { + this.pendingIntent_.cancel(); + } + this.pendingIntent_ = intent; + } + + /** + * Handles launch event triggered from ARC++ intent. + * @param {!cca.intent.Intent} intent Intent forwarding from ARC++. + */ + launchIntent(intent) { + if (this.intentWindow_) { + switch (this.intentWindow_.state) { + case cca.bg.WindowState.LAUNCHING: + case cca.bg.WindowState.CLOSING: + this.replacePendingIntent_(intent); + break; + case cca.bg.WindowState.ACTIVE: + this.replacePendingIntent_(intent); + this.intentWindow_.close(); + break; + default: + this.assert_( + false, + `Intent window is ${ + this.intentWindow_.state} when launch new intent window.`); + } + } else if (this.launcherWindow_) { + switch (this.launcherWindow_.state) { + case cca.bg.WindowState.LAUNCHING: + case cca.bg.WindowState.SUSPENDING: + case cca.bg.WindowState.RESUMING: + case cca.bg.WindowState.CLOSING: + this.replacePendingIntent_(intent); + break; + case cca.bg.WindowState.ACTIVE: + this.assert_( + !this.pendingIntent_, + 'Pending intent is not processed when launch window is active.'); + this.replacePendingIntent_(intent); + this.launcherWindow_.suspend(); + break; + default: + this.assert_( + false, + `Launch window is ${ + this.launcherWindow_.state} when launch new intent window.`); + } + } else { + this.intentWindow_ = this.createIntentWindow_(intent); + this.intentWindow_.launch(); + } + } }; /** @@ -109,6 +475,21 @@ } }; -chrome.app.runtime.onLaunched.addListener(cca.bg.create); +chrome.app.runtime.onLaunched.addListener((launchData) => { + if (!cca.bg.background) { + cca.bg.background = new cca.bg.Background(); + } + try { + if (launchData.url) { + const intent = cca.intent.Intent.create(new URL(launchData.url)); + cca.bg.background.launchIntent(intent); + } else { + cca.bg.background.launchApp(); + } + } catch (e) { + console.error(e.stack); + } +}); + chrome.runtime.onMessageExternal.addListener( cca.bg.handleExternalMessageFromTest);
diff --git a/chrome/browser/resources/chromeos/camera/src/js/intent.js b/chrome/browser/resources/chromeos/camera/src/js/intent.js new file mode 100644 index 0000000..2d42545 --- /dev/null +++ b/chrome/browser/resources/chromeos/camera/src/js/intent.js
@@ -0,0 +1,191 @@ +// Copyright (c) 2019 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'; + +/** + * Namespace for the Camera app. + */ +var cca = cca || {}; + +/** + * Namespace for the ARC++ intent. + */ +cca.intent = cca.intent || {}; + +/** + * Available intent modes. + * @enum {string} + */ +cca.intent.Mode = { + PHOTO: 'photo', + VIDEO: 'video', +}; + +/** + * Thrown when fails to parse intent url. + */ +cca.intent.ParseError = class extends Error { + /** + * @param {!URL} url Intent url. + */ + constructor(url) { + super(`Failed to parse intent url ${url}`); + /** + * @const {!URL} url + * @private + */ + this.url_ = url; + + this.name = 'ParseError'; + } +}; + +/** + * Intent from ARC++. + */ +cca.intent.Intent = class { + /** + * @param {!URL} url + * @param {number} intentId + * @param {cca.intent.Mode} mode + * @param {boolean} shouldHandleResult + * @param {boolean} shouldDownScale + * @param {boolean} isSecure + * @private + */ + constructor( + url, intentId, mode, shouldHandleResult, shouldDownScale, isSecure) { + /** + * @const {!URL} + */ + this.url = url; + + /** + * @const {number} + */ + this.intentId = intentId; + + /** + * Capture mode of intent. + * @const {!cca.intent.Mode} + */ + this.mode = mode; + + /** + * Whether the intent should return with the captured result. + * @const {boolean} + */ + this.shouldHandleResult = shouldHandleResult; + + /** + * Whether the captured image should be down-scaled. + * @const {boolean} + */ + this.shouldDownScale = shouldDownScale; + + /** + * If the intent is launched when the device is under secure mode. + * @const {boolean} + */ + this.isSecure = isSecure; + + /** + * Flag for avoiding intent being resolved by foreground and background + * twice. + * @type {boolean} + * @private + */ + this.done_ = false; + } + + /** + * @return {!cca.mojo.ChromeHelper} + * @private + */ + get chromeHelper_() { + return cca.mojo.ChromeHelper.getInstance(); + } + + /** + * Whether intent has been finished or canceled. + * @return {boolean} + */ + get done() { + return this.done_; + } + + /** + * Notifies ARC++ to finish the intent. + * @return {!Promise} + */ + async finish() { + if (this.done) { + return; + } + this.done_ = true; + await this.chromeHelper_.finish(this.intentId); + } + + /** + * Notifies ARC++ to cancel the intent. + * @return {!Promise} + */ + async cancel() { + if (this.done) { + return; + } + this.done_ = true; + await this.chromeHelper_.cancel(this.intentId); + } + + /** + * Notifies ARC++ to append data to the intent result. + * @param {!Uint8Array} data The data to be appended to intent result. + * @return {!Promise} + */ + async appendData(data) { + if (this.done) { + return; + } + await this.chromeHelper_.appendData(this.intentId, data); + } + + /** + * Notifies ARC++ to clear appended intent result data. + * @return {!Promise} + */ + async clearData() { + if (this.done) { + return; + } + await this.chromeHelper_.clearData(this.intentId); + } + + /** + * @param {!URL} url Url passed along with app launch event. + * @return {!cca.intent.Intent} Created intent object. Returns null if input + * is not a valid intent url. + * @throws {cca.intent.ParseError} + */ + static create(url) { + const params = url.searchParams; + const getBool = (key) => params.get(key) === '1'; + let param = params.get('intentId'); + if (param === null) { + throw new cca.intent.ParseError(url); + } + const intentId = parseInt(param, 10); + + param = params.get('mode'); + if (param === null || !Object.values(cca.intent.Mode).includes(param)) { + throw new cca.intent.ParseError(url); + } + const mode = /** @type {!cca.intent.Mode} */ (param); + + return new cca.intent.Intent( + url, intentId, mode, getBool('shouldHandleResult'), + getBool('shouldDownScale'), getBool('isSecure')); + } +};
diff --git a/chrome/browser/resources/chromeos/camera/src/js/main.js b/chrome/browser/resources/chromeos/camera/src/js/main.js index 7c1fbd4f..71539b16 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/main.js +++ b/chrome/browser/resources/chromeos/camera/src/js/main.js
@@ -195,6 +195,24 @@ }; /** + * Suspends app and hides app window. + * @return {!Promise} + */ +cca.App.prototype.suspend = async function() { + cca.state.set('suspend', true); + await this.cameraView_.restart(); + chrome.app.window.current().hide(); +}; + +/** + * Resumes app from suspension and shows app window. + */ +cca.App.prototype.resume = function() { + cca.state.set('suspend', false); + chrome.app.window.current().show(); +}; + +/** * Singleton of the App object. * @type {cca.App} * @private @@ -202,6 +220,12 @@ cca.App.instance_ = null; /** + * Intent associated with current app window. + * @type {?cca.intent.Intent} + */ +window.intent = window.intent || null; + +/** * Creates the App object and starts camera stream. */ document.addEventListener('DOMContentLoaded', async () => { @@ -209,5 +233,16 @@ cca.App.instance_ = new cca.App(); } cca.App.instance_.start(); + // Register methods called from background. + window.ops = { + suspend: () => { + cca.App.instance_.suspend().then(window.onSuspended); + }, + resume: () => { + cca.App.instance_.resume(); + window.onActive(); + }, + }; chrome.app.window.current().show(); + window.onActive(); });
diff --git a/chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js b/chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js index 9e70d267..afa238f 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js +++ b/chrome/browser/resources/chromeos/camera/src/js/mojo/chrome_helper.js
@@ -24,7 +24,7 @@ constructor() { /** * An interface remote that is used to communicate with Chrome. - * @type {chromeosCamera.mojom.CameraAppHelperRemote} + * @type {!chromeosCamera.mojom.CameraAppHelperRemote} */ this.remote_ = chromeosCamera.mojom.CameraAppHelper.getRemote(); } @@ -40,6 +40,80 @@ } /** + * Checks return value from |handleCameraResult|. + * @param {string} caller Caller identifier. + * @param {Promise<{isSuccess: boolean}>|null} value + * @return {!Promise} + */ + async checkReturn_(caller, value) { + const ret = await value; + if (ret === null) { + console.error(`Return null from calling intent ${caller}.`); + return; + } + if (!ret.isSuccess) { + console.error(`Return not isSuccess from calling intent ${caller}.`); + } + } + + /** + * Notifies ARC++ to finish the intent. + * @param {number} intentId Intent id of the intent to be finished. + * @return {!Promise} + */ + async finish(intentId) { + const ret = this.remote_.handleCameraResult( + intentId, arc.mojom.CameraIntentAction.FINISH, []); + await this.checkReturn_('finish()', ret); + } + + /** + * Notifies ARC++ to cancel the intent. + * @param {number} intentId Intent id of the intent to be canceled. + * @return {!Promise} + */ + async cancel(intentId) { + const ret = this.remote_.handleCameraResult( + intentId, arc.mojom.CameraIntentAction.CANCEL, []); + await this.checkReturn_('cancel()', ret); + } + + /** + * Forces casting type from Uint8Array to !Array<number>. + * @param {!Uint8Array} data + * @return {!Array<number>} + * @suppress {checkTypes} + * @private + */ + static castResultType_(data) { + return data; + } + + /** + * Notifies ARC++ to append data to intent result. + * @param {number} intentId Intent id of the intent to be appended data to. + * @param {!Uint8Array} data The data to be appended to intent result. + * @return {!Promise} + */ + async appendData(intentId, data) { + const ret = this.remote_.handleCameraResult( + intentId, arc.mojom.CameraIntentAction.APPEND_DATA, + this.constructor.castResultType_(data)); + await this.checkReturn_('appendData()', ret); + } + + /** + * Notifies ARC++ to clear appended intent result data. + * @param {number} intentId Intent id of the intent to be cleared its result. + * @return {!Promise} + */ + async clearData(intentId) { + const ret = this.remote_.handleCameraResult( + intentId, arc.mojom.CameraIntentAction.CLEAR_DATA, []); + await this.checkReturn_('clearData()', ret); + } + + /** * Creates a new instance of ChromeHelper if it is not set. Returns the * exist instance. * @return {!cca.mojo.ChromeHelper} The singleton instance.
diff --git a/chrome/browser/resources/chromeos/camera/src/js/tooltip.js b/chrome/browser/resources/chromeos/camera/src/js/tooltip.js index 7e664dbe..914dbc5 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/tooltip.js +++ b/chrome/browser/resources/chromeos/camera/src/js/tooltip.js
@@ -79,7 +79,14 @@ */ cca.tooltip.show_ = function(element) { cca.tooltip.hide(); - cca.tooltip.wrapper_.textContent = element.getAttribute('aria-label'); + let message = element.getAttribute('aria-label'); + if (element.hasAttribute('tooltip-true') && element.checked) { + message = element.getAttribute('tooltip-true'); + } + if (element.hasAttribute('tooltip-false') && !element.checked) { + message = element.getAttribute('tooltip-false'); + } + cca.tooltip.wrapper_.textContent = message; cca.tooltip.hovered_ = element; cca.tooltip.position_(); cca.tooltip.wrapper_.classList.add('visible');
diff --git a/chrome/browser/resources/chromeos/camera/src/js/util.js b/chrome/browser/resources/chromeos/camera/src/js/util.js index 3ae841901..ff80ad6e 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/util.js +++ b/chrome/browser/resources/chromeos/camera/src/js/util.js
@@ -884,6 +884,14 @@ .forEach( (element) => element.textContent = getMessage(element, 'i18n-content')); + getElements('i18n-tooltip-true') + .forEach( + (element) => element.setAttribute( + 'tooltip-true', getMessage(element, 'i18n-tooltip-true'))); + getElements('i18n-tooltip-false') + .forEach( + (element) => element.setAttribute( + 'tooltip-false', getMessage(element, 'i18n-tooltip-false'))); getElements('i18n-aria') .forEach((element) => setAriaLabel(element, 'i18n-aria')); cca.tooltip.setup(getElements('i18n-label'))
diff --git a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js index 41ff5c0..913648a 100644 --- a/chrome/browser/resources/chromeos/camera/src/js/views/camera.js +++ b/chrome/browser/resources/chromeos/camera/src/js/views/camera.js
@@ -162,7 +162,8 @@ * @return {boolean} */ get suspended() { - return this.locked_ || chrome.app.window.current().isMinimized(); + return this.locked_ || chrome.app.window.current().isMinimized() || + cca.state.get('suspend'); }, }; @@ -294,6 +295,9 @@ break; } for (const constraints of previewCandidates) { + if (this.suspended) { + throw new cca.views.CameraSuspendedError(); + } try { const deviceOperator = await cca.mojo.DeviceOperator.getInstance(); if (deviceOperator) {
diff --git a/chrome/browser/resources/chromeos/camera/src/manifest.json b/chrome/browser/resources/chromeos/camera/src/manifest.json index 412686f9..f0c5c27 100644 --- a/chrome/browser/resources/chromeos/camera/src/manifest.json +++ b/chrome/browser/resources/chromeos/camera/src/manifest.json
@@ -25,7 +25,14 @@ ], "app": { "background": { - "scripts": ["js/background.js"] + "scripts": [ + "js/mojo/mojo_bindings_lite.js", + "js/mojo/camera_intent.mojom-lite.js", + "js/mojo/camera_app_helper.mojom-lite.js", + "js/mojo/chrome_helper.js", + "js/intent.js", + "js/background.js" + ] } } }
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd index 491528e..b846531 100644 --- a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd +++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings.grd
@@ -297,6 +297,12 @@ <message desc="Label for the button of grid-type options." name="IDS_GRID_TYPE_BUTTON"> Grid type </message> + <message desc="Label showing current state of 30 FPS on tooltip of toggle 60 FPS recording checkbox." name="IDS_LABEL_30FPS"> + 30 FPS + </message> + <message desc="Label showing current state of 60 FPS on tooltip of toggle 60 FPS recording checkbox." name="IDS_LABEL_60FPS"> + 60 FPS + </message> <message desc="Label for the checkbox to toggle 60 FPS recording." name="IDS_TOGGLE_60FPS_BUTTON"> 60 FPS </message>
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1 new file mode 100644 index 0000000..233ebe16 --- /dev/null +++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_30FPS.png.sha1
@@ -0,0 +1 @@ +19d2c700625eb6d227af9eada492528ed5ec86ff \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1 b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1 new file mode 100644 index 0000000..dfc84634 --- /dev/null +++ b/chrome/browser/resources/chromeos/camera/src/strings/camera_strings_grd/ID_LABEL_60FPS.png.sha1
@@ -0,0 +1 @@ +3f9498a334c87daeab3d8b576c1462c7d49098ca \ No newline at end of file
diff --git a/chrome/browser/resources/chromeos/camera/src/views/main.html b/chrome/browser/resources/chromeos/camera/src/views/main.html index 5d3f398..33664d4 100644 --- a/chrome/browser/resources/chromeos/camera/src/views/main.html +++ b/chrome/browser/resources/chromeos/camera/src/views/main.html
@@ -153,7 +153,9 @@ <input type="checkbox" id="toggle-mirror" tabindex="0" i18n-label="toggle_mirror_button" data-state="mirror" checked> <input type="checkbox" id="toggle-fps" tabindex="0" - i18n-label="toggle_60fps_button"> + i18n-label="toggle_60fps_button" + i18n-tooltip-true="label_60fps" + i18n-tooltip-false="label_30fps"> </div> <div class="top-stripe left-stripe buttons"> <button id="open-settings" tabindex="0"
diff --git a/chrome/browser/resources/chromeos/zip_archiver/js/app.js b/chrome/browser/resources/chromeos/zip_archiver/js/app.js index fb8c1be..28275d2a 100644 --- a/chrome/browser/resources/chromeos/zip_archiver/js/app.js +++ b/chrome/browser/resources/chromeos/zip_archiver/js/app.js
@@ -487,54 +487,39 @@ */ unmountVolume: function(fileSystemId, opt_forceUnmount) { return new Promise(function(fulfill, reject) { - chrome.fileManagerPrivate.markCacheAsMounted( - fileSystemId, false /* isMounted */, function() { - if (chrome.runtime.lastError) { - console.error( - 'Unmount error: ' + chrome.runtime.lastError.message + - '.'); - reject('FAILED'); - return; - } - fulfill(); - }); - }) - .then(function() { - return new Promise(function(fulfill, reject) { - var volume = unpacker.app.volumes[fileSystemId]; - console.assert( - volume || opt_forceUnmount, - 'Unmount that is not forced must not be called for ', - 'volumes that are not restored.'); + var volume = unpacker.app.volumes[fileSystemId]; + console.assert( + volume || opt_forceUnmount, + 'Unmount that is not forced must not be called for ', + 'volumes that are not restored.'); - if (!opt_forceUnmount && volume.inUse()) { - reject('IN_USE'); - return; - } + if (!opt_forceUnmount && volume.inUse()) { + reject('IN_USE'); + return; + } - var options = {fileSystemId: fileSystemId}; - chrome.fileSystemProvider.unmount(options, function() { - if (chrome.runtime.lastError) { - console.error( - 'Unmount error: ' + chrome.runtime.lastError.message + '.'); - reject('FAILED'); - return; - } + var options = {fileSystemId: fileSystemId}; + chrome.fileSystemProvider.unmount(options, function() { + if (chrome.runtime.lastError) { + console.error( + 'Unmount error: ' + chrome.runtime.lastError.message + '.'); + reject('FAILED'); + return; + } - // In case of forced unmount volume can be undefined due to not - // being restored. An unmount that is not forced will be called - // only after restoring state. In the case of forced unmount when - // volume is not restored, we will not do a normal cleanup, but - // just remove the load volume promise to allow further mounts. - if (opt_forceUnmount) - delete unpacker.app.volumeLoadedPromises[fileSystemId]; - else - unpacker.app.cleanupVolume(fileSystemId); + // In case of forced unmount volume can be undefined due to not + // being restored. An unmount that is not forced will be called + // only after restoring state. In the case of forced unmount when + // volume is not restored, we will not do a normal cleanup, but + // just remove the load volume promise to allow further mounts. + if (opt_forceUnmount) + delete unpacker.app.volumeLoadedPromises[fileSystemId]; + else + unpacker.app.cleanupVolume(fileSystemId); - fulfill(); - }); - }); - }); + fulfill(); + }); + }); }, /** @@ -882,18 +867,6 @@ loadPromise .then(function() { unpacker.app.volumeLoadFinished[fileSystemId] = true; - return new Promise(function(fulfill, reject) { - chrome.fileManagerPrivate.markCacheAsMounted( - displayPath, true /* isMounted */, function() { - if (chrome.runtime.lastError) { - reject(chrome.runtime.lastError); - return; - } - fulfill(); - }); - }); - }) - .then(function() { chrome.fileSystemProvider.mount( { fileSystemId: fileSystemId,
diff --git a/chrome/browser/resources/print_preview/data/margins.js b/chrome/browser/resources/print_preview/data/margins.js index cbf2a02..ce38eb6 100644 --- a/chrome/browser/resources/print_preview/data/margins.js +++ b/chrome/browser/resources/print_preview/data/margins.js
@@ -21,7 +21,7 @@ * printing/print_job_constants.h. * @enum {number} */ - const MarginsTypeValue = { + const MarginsType = { DEFAULT: 0, NO_MARGINS: 1, MINIMUM: 2, @@ -30,7 +30,7 @@ return { CustomMarginsOrientation: CustomMarginsOrientation, - MarginsTypeValue: MarginsTypeValue, + MarginsType: MarginsType, }; });
diff --git a/chrome/browser/resources/print_preview/data/model.js b/chrome/browser/resources/print_preview/data/model.js index 6c355bc6..3d4b0bb 100644 --- a/chrome/browser/resources/print_preview/data/model.js +++ b/chrome/browser/resources/print_preview/data/model.js
@@ -60,7 +60,7 @@ * width_microns: number, * custom_display_name: (string | undefined), * is_default: (boolean | undefined)} | undefined), - * marginsType: (print_preview.MarginsTypeValue | undefined), + * marginsType: (print_preview.MarginsType | undefined), * customMargins: (print_preview.MarginsSetting | undefined), * isColorEnabled: (boolean | undefined), * isDuplexEnabled: (boolean | undefined), @@ -262,8 +262,8 @@ updatesPreview: true, }, margins: { - value: print_preview.MarginsTypeValue.DEFAULT, - unavailableValue: print_preview.MarginsTypeValue.DEFAULT, + value: print_preview.MarginsType.DEFAULT, + unavailableValue: print_preview.MarginsType.DEFAULT, valid: true, available: true, setByPolicy: false, @@ -790,20 +790,20 @@ // Otherwise, availability depends on the margins. let available = false; const marginsType = - /** @type {!print_preview.MarginsTypeValue} */ ( + /** @type {!print_preview.MarginsType} */ ( this.getSettingValue('margins')); switch (marginsType) { - case print_preview.MarginsTypeValue.DEFAULT: + case print_preview.MarginsType.DEFAULT: available = !this.margins || this.margins.get(print_preview.CustomMarginsOrientation.TOP) > 0 || this.margins.get(print_preview.CustomMarginsOrientation.BOTTOM) > 0; break; - case print_preview.MarginsTypeValue.NO_MARGINS: + case print_preview.MarginsType.NO_MARGINS: break; - case print_preview.MarginsTypeValue.MINIMUM: + case print_preview.MarginsType.MINIMUM: available = true; break; - case print_preview.MarginsTypeValue.CUSTOM: + case print_preview.MarginsType.CUSTOM: const margins = this.getSettingValue('customMargins'); available = margins.marginTop > 0 || margins.marginBottom > 0; break; @@ -1236,8 +1236,7 @@ ticket.cloudPrintID = destination.id; } - if (this.getSettingValue('margins') == - print_preview.MarginsTypeValue.CUSTOM) { + if (this.getSettingValue('margins') == print_preview.MarginsType.CUSTOM) { ticket.marginsCustom = this.getSettingValue('customMargins'); }
diff --git a/chrome/browser/resources/print_preview/ui/margin_control_container.js b/chrome/browser/resources/print_preview/ui/margin_control_container.js index f4e9c4bf..c675756 100644 --- a/chrome/browser/resources/print_preview/ui/margin_control_container.js +++ b/chrome/browser/resources/print_preview/ui/margin_control_container.js
@@ -136,8 +136,7 @@ */ computeAvailable_: function() { return this.previewLoaded && !!this.clipSize_ && - this.getSettingValue('margins') == - print_preview.MarginsTypeValue.CUSTOM && + this.getSettingValue('margins') == print_preview.MarginsType.CUSTOM && !!this.pageSize; }, @@ -185,9 +184,9 @@ this.resetMargins_ = true; const marginsSetting = this.getSetting('margins'); - if (marginsSetting.value == print_preview.MarginsTypeValue.CUSTOM) { + if (marginsSetting.value == print_preview.MarginsType.CUSTOM) { // Set the margins value to default first. - this.setSetting('margins', print_preview.MarginsTypeValue.DEFAULT); + this.setSetting('margins', print_preview.MarginsType.DEFAULT); } // Reset custom margins so that the sticky value is not restored for the // new paper size.
diff --git a/chrome/browser/resources/print_preview/ui/margins_settings.html b/chrome/browser/resources/print_preview/ui/margins_settings.html index f0284da7..a47ee581 100644 --- a/chrome/browser/resources/print_preview/ui/margins_settings.html +++ b/chrome/browser/resources/print_preview/ui/margins_settings.html
@@ -19,15 +19,19 @@ settings.pagesPerSheet.value)]]" value="{{selectedValue::change}}"> <!-- The order of these options must match the natural order of their - values, which come from print_preview.MarginsTypeValue. --> - <option value="[[MarginsValue.DEFAULT]]" selected> + values, which come from print_preview.MarginsType. --> + <option value="[[MarginsTypeEnum.DEFAULT]]" selected> $i18n{defaultMargins} </option> - <option value="[[MarginsValue.NO_MARGINS]]">$i18n{noMargins}</option> - <option value="[[MarginsValue.MINIMUM]]"> + <option value="[[MarginsTypeEnum.NO_MARGINS]]"> + $i18n{noMargins} + </option> + <option value="[[MarginsTypeEnum.MINIMUM]]"> $i18n{minimumMargins} </option> - <option value="[[MarginsValue.CUSTOM]]">$i18n{customMargins}</option> + <option value="[[MarginsTypeEnum.CUSTOM]]"> + $i18n{customMargins} + </option> </select> </div> </print-preview-settings-section>
diff --git a/chrome/browser/resources/print_preview/ui/margins_settings.js b/chrome/browser/resources/print_preview/ui/margins_settings.js index 98444fa..cd4e0ae 100644 --- a/chrome/browser/resources/print_preview/ui/margins_settings.js +++ b/chrome/browser/resources/print_preview/ui/margins_settings.js
@@ -11,14 +11,14 @@ disabled: Boolean, /** Mirroring the enum so that it can be used from HTML bindings. */ - MarginsValue: Object, + MarginsTypeEnum: Object, }, observers: ['onMarginsSettingChange_(settings.margins.value)'], /** @override */ ready: function() { - this.MarginsValue = print_preview.MarginsTypeValue; + this.MarginsTypeEnum = print_preview.MarginsType; }, /** @@ -27,7 +27,7 @@ */ onMarginsSettingChange_: function(newValue) { this.selectedValue = - /** @type {!print_preview.MarginsTypeValue} */ (newValue).toString(); + /** @type {!print_preview.MarginsType} */ (newValue).toString(); }, /** @param {string} value The new select value. */
diff --git a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js index 6cc6d89..97533754 100644 --- a/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js +++ b/chrome/browser/resources/print_preview/ui/pages_per_sheet_settings.js
@@ -19,7 +19,7 @@ */ onPagesPerSheetSettingChange_: function(newValue) { this.selectedValue = /** @type {number} */ (newValue).toString(); - this.setSetting('margins', print_preview.MarginsTypeValue.DEFAULT); + this.setSetting('margins', print_preview.MarginsType.DEFAULT); }, /** @param {string} value The new select value. */
diff --git a/chrome/browser/resources/print_preview/ui/preview_area.js b/chrome/browser/resources/print_preview/ui/preview_area.js index 487a40c5..23329ca7 100644 --- a/chrome/browser/resources/print_preview/ui/preview_area.js +++ b/chrome/browser/resources/print_preview/ui/preview_area.js
@@ -529,12 +529,12 @@ */ marginsValid_: function() { const type = this.getSettingValue('margins'); - if (!Object.values(print_preview.MarginsTypeValue).includes(type)) { + if (!Object.values(print_preview.MarginsType).includes(type)) { // Unrecognized margins type. return false; } - if (type !== print_preview.MarginsTypeValue.CUSTOM) { + if (type !== print_preview.MarginsType.CUSTOM) { return true; } @@ -566,11 +566,11 @@ // Margins const newMarginsType = this.getSettingValue('margins'); if (newMarginsType !== lastTicket.marginsType && - newMarginsType !== print_preview.MarginsTypeValue.CUSTOM) { + newMarginsType !== print_preview.MarginsType.CUSTOM) { return true; } - if (newMarginsType === print_preview.MarginsTypeValue.CUSTOM) { + if (newMarginsType === print_preview.MarginsType.CUSTOM) { const customMargins = /** @type {!print_preview.MarginsSetting} */ ( this.getSettingValue('customMargins')); @@ -626,8 +626,7 @@ // Pages per sheet. If margins are non-default, wait for the return to // default margins to trigger a request. if (this.getSettingValue('pagesPerSheet') !== lastTicket.pagesPerSheet && - this.getSettingValue('margins') === - print_preview.MarginsTypeValue.DEFAULT) { + this.getSettingValue('margins') === print_preview.MarginsType.DEFAULT) { return true; } @@ -639,7 +638,7 @@ newValue.width_microns != lastTicket.mediaSize.width_microns || (this.destination.id !== lastTicket.deviceName && this.getSettingValue('margins') === - print_preview.MarginsTypeValue.MINIMUM)) { + print_preview.MarginsType.MINIMUM)) { return true; } @@ -731,8 +730,7 @@ ticket.cloudPrintID = this.destination.id; } - if (this.getSettingValue('margins') == - print_preview.MarginsTypeValue.CUSTOM) { + if (this.getSettingValue('margins') == print_preview.MarginsType.CUSTOM) { ticket.marginsCustom = this.getSettingValue('customMargins'); } this.lastTicket_ = ticket;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js index a3ca577..5939d4c 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/constants.js
@@ -9,12 +9,6 @@ const NUMBER_OF_APPS_DISPLAYED_DEFAULT = 4; /** - * The maximum number of apps' titles previewed in notification sublabel. - * @const {number} - */ -const APP_LIST_PREVIEW_APP_TITLES = 3; - -/** * Enumeration of the different subpage types within the app management page. * @enum {number} * @const @@ -22,7 +16,6 @@ const PageType = { MAIN: 0, DETAIL: 1, - NOTIFICATIONS: 2, }; /**
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html index 0983379b..9d4780e3 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.html
@@ -3,42 +3,11 @@ <link rel="import" href="app_item.html"> <link rel="import" href="shared_style.html"> <link rel="import" href="store_client.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/iron-collapse/iron-collapse.html"> <link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> <dom-module id="app-management-main-view"> <template> <style include="app-management-shared-css"> - .notification-row-sublabel { - display: flex; - flex-direction: column; - overflow: hidden; - padding: 11px 0; - } - - .collapsible { - max-width: 250px; - overflow: hidden; - text-overflow: ellipsis; - } - - #notifications-sublabel { - display: flex; - overflow: hidden; - } - - #notifications-sublabel > span { - white-space: pre; - } - - .notification-row { - align-items: center; - cursor: pointer; - display: inline-flex; - justify-content: space-between; - padding: 0 24px; - } - .app-management-item-arrow { margin-inline-end: 8px; padding: 12px; @@ -67,18 +36,6 @@ $i18n{appManagementNoAppsFound} </div> </template> - - <div class="card-container" hidden> - <span class="notification-row" on-click="onClickNotificationSublabel_"> - <div class="notification-row-sublabel"> - <div class="header-text"> - $i18n{notifications} - </div> - <div id="notifications-sublabel" class="secondary-text"></div> - </div> - <cr-icon-button class="subpage-arrow" actionable></cr-icon-button> - </span> - </div> </template> <script src="main_view.js"></script> </dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js index 0f3af74..efcaadb 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/main_view.js
@@ -33,20 +33,10 @@ value: () => [], computed: 'computeAppList_(apps_, searchTerm)' }, - - /** - * A set containing the ids of all the apps with notifications enabled. - * @private {!Set<string>} - */ - notificationAppIds_: { - type: Object, - observer: 'getNotificationSublabel_', - }, }, attached: function() { this.watch('apps_', state => state.apps); - this.watch('notificationAppIds_', state => state.notifications.allowedIds); this.updateFromStore(); }, @@ -91,72 +81,4 @@ return filteredApps; }, - - /** @private */ - onClickNotificationSublabel_: function() { - this.dispatch(app_management.actions.changePage(PageType.NOTIFICATIONS)); - }, - - /** - * Show a string with apps' |title|(s) previewed into a label, with each - * title ellipsised if too long. - * @private - */ - getNotificationSublabelPieces_: async function() { - const notificationApps = - Array.from(this.notificationAppIds_, id => this.getState().apps[id]); - - // const /** @type {string} */ label = await cr.sendWithPromise( - // 'getPluralString', 'appListPreview', notificationApps.length); - // TODO(jshikaram): Add the get plural string handler to ossettingsui. - const label = ''; - - const substitutions = []; - for (let i = 0; - i < APP_LIST_PREVIEW_APP_TITLES && i < notificationApps.length; i++) { - substitutions.push(notificationApps[i].title); - } - - // Add X more apps if the length is more than APP_LIST_PREVIEW_APP_TITLES. - if (notificationApps.length >= APP_LIST_PREVIEW_APP_TITLES + 1) { - substitutions.push(notificationApps.length - APP_LIST_PREVIEW_APP_TITLES); - } - // Only APP_LIST_PREVIEW_APP_TITLES of apps' titles get ellipsised - // if too long. the element after that is "X other apps" - const placeholder = APP_LIST_PREVIEW_APP_TITLES + 1; - const pieces = - loadTimeData.getSubstitutedStringPieces(label, ...substitutions) - .map(function(p) { - // Make the titles of app collapsible but make the number in the - // "X other app(s)" part non-collapsible. - p.collapsible = !!p.arg && p.arg !== '$' + placeholder; - return p; - }); - return pieces; - }, - - /** - * Create <span> for each app title previewed, - * making certain text fragments collapsible. - */ - getNotificationSublabel_: async function() { - const pieces = await this.getNotificationSublabelPieces_(); - // Create <span> for each app title previewed, - // making certain text fragments collapsible. - const textContainer = this.$['notifications-sublabel']; - textContainer.textContent = ''; - for (const p of pieces) { - if (!p.value || p.value.length === 0) { - return; - } - - const span = document.createElement('span'); - span.textContent = p.value; - if (p.collapsible) { - span.classList.add('collapsible'); - } - - textContainer.appendChild(span); - } - }, });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.html b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.html deleted file mode 100644 index c66bcb2c..0000000 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.html +++ /dev/null
@@ -1,53 +0,0 @@ -<link rel="import" href="chrome://resources/html/polymer.html"> - -<link rel="import" href="expandable_app_list.html"> -<link rel="import" href="shared_style.html"> -<link rel="import" href="store_client.html"> -<link rel="import" href="chrome://resources/cr_elements/cr_icon_button/cr_icon_button.html"> - -<dom-module id="app-management-notifications-view"> - <template> - <style include="app-management-shared-css"> - cr-icon-button { - margin: 0; - } - - app-management-permission-toggle { - margin-inline-end: 24px; - } - - #notification-view-header { - align-items: center; - display: flex; - margin: 24px auto; - max-width: var(--card-max-width); - min-width: var(--card-min-width); - } - - #notification-title { - padding-inline-start: 12px; - } - </style> - <!-- TODO(crbug.com/906508): Implement display when there is no apps at - all --> - <div id="notification-view-header"> - <cr-icon-button class="icon-arrow-back" id="closeButton" - on-click="onClickBackButton_" aria-label="$i18n{back}"> - </cr-icon-button> - <div id="notification-title" class="page-title">$i18n{notifications}</div> - </div> - <app-management-expandable-app-list - apps="[[appsList_]]" - collapsed-size="[[getCollapsedSize_(appsList_)]]"> - <template is="dom-repeat" items="[[appsList_]]" as="app"> - <app-management-app-item app="[[app]]"> - <app-management-permission-toggle slot="right-content" - app="[[app]]" - permission-type="CONTENT_SETTINGS_TYPE_NOTIFICATIONS"> - </app-management-permission-toggle> - </app-management-app-item> - </template> - </app-management-expandable-app-list> - </template> - <script src="notifications_view.js"></script> -</dom-module>
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.js deleted file mode 100644 index aae8cff..0000000 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/notifications_view.js +++ /dev/null
@@ -1,166 +0,0 @@ -// Copyright 2018 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. - -Polymer({ - is: 'app-management-notifications-view', - - behaviors: [ - app_management.StoreClient, - ], - - properties: { - /** - * @private {AppMap} - */ - apps_: { - type: Object, - observer: 'onAppsChanged_', - }, - - /** @private {!Array<!App>} */ - appsList_: { - type: Array, - computed: 'calculateAppsList_(allowed_.*, blocked_.*)', - }, - - /** - * List of apps with notification permission - * displayed before expanding the app list. - * @private {!Array<App>} - */ - allowed_: { - type: Array, - value: () => [], - }, - - /** - * List of apps without notification permission - * displayed after expanding app list. - * @private {!Array<App>} - */ - blocked_: { - type: Array, - value: () => [], - }, - }, - - attached: function() { - this.watch('apps_', state => state.apps); - this.updateFromStore(); - - this.onViewLoaded_(); - }, - - /** - * Creates arrays of displayed and collapsed apps based on the sets of apps - * with notifications allowed and blocked in the Store. The orders of apps - * in these arrays should then remain fixed while this view is showing. - * - * If all the apps have / don't have notification permission, display the - * whole list, else display those with notification permission before - * expanding. - * @private - */ - onViewLoaded_: function() { - const state = this.getState(); - this.allowed_ = - Array.from(state.notifications.allowedIds, id => state.apps[id]); - this.blocked_ = - Array.from(state.notifications.blockedIds, id => state.apps[id]); - }, - - /** - * Updates the lists of displayed and collapsed apps when any changes occur - * to the apps in the Store, maintaining the original order of apps in the - * lists. New lists are created so that Polymer bindings will re-evaluate. - * @private - */ - onAppsChanged_() { - const unhandledAppIds = new Set(Object.keys(this.apps_)); - this.allowed_ = this.updateAppList_(this.allowed_, unhandledAppIds); - this.blocked_ = this.updateAppList_(this.blocked_, unhandledAppIds); - - // If any new apps have been added, append them to the appropriate list. - for (const appId of unhandledAppIds) { - const app = this.apps_[appId]; - const allowed = app_management.util.notificationsAllowed(app); - - if (allowed === OptionalBool.kUnknown) { - continue; - } - - if (allowed === OptionalBool.kTrue) { - this.push('allowed_', app); - } else { - this.push('blocked_', app); - } - } - }, - - /** - * @private - * @return {!Array<!App>} - */ - calculateAppsList_() { - return this.allowed_.concat(this.blocked_); - }, - - /** - * @private - * @return {number} - */ - getCollapsedSize_() { - return this.allowed_.length || this.blocked_.length; - }, - - /** - * Creates a new list of apps with the same order as the original appList, - * but using the updated apps from this.apps_. As each app is added to the - * new list, it is also removed from the unhandledAppIds set. - * @param {!Array<App>} appList - * @param {!Set<string>} unhandledAppIds - * @return {!Array<App>} - * @private - */ - updateAppList_(appList, unhandledAppIds) { - const newApps = []; - for (const app of appList) { - if (unhandledAppIds.has(app.id)) { - newApps.push(this.apps_[app.id]); - unhandledAppIds.delete(app.id); - } - } - return newApps; - }, - - /** @private */ - onClickBackButton_: function() { - if (!window.history.state) { - this.dispatch(app_management.actions.changePage(PageType.MAIN)); - } else { - window.history.back(); - } - }, - - /** - * Returns a boolean representation of the permission value, which used to - * determine the position of the permission toggle. - * @param {App} app - * @return {boolean} - * @private - */ - getNotificationValueBool_: function(app) { - return app_management.util.getPermissionValueBool( - app, this.notificationsPermissionType(app)); - }, - - /** - * @param {App} app - * @return {string} - * @private - */ - notificationsPermissionType_: function(app) { - return assert(app_management.util.notificationsPermissionType(app)); - }, -});
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js index 7052e18..bca6b4e 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/reducers.js
@@ -87,11 +87,6 @@ pageType: PageType.DETAIL, selectedAppId: action.id, }; - } else if (action.pageType === PageType.NOTIFICATIONS) { - return { - pageType: PageType.NOTIFICATIONS, - selectedAppId: null, - }; } else { return { pageType: PageType.MAIN, @@ -134,87 +129,6 @@ } }; - const NotificationsState = {}; - - /** - * @param {NotificationsState} notifications - * @param {Object} action - * @return {NotificationsState} - */ - NotificationsState.addApp = function(notifications, action) { - let {allowedIds, blockedIds} = notifications; - const allowed = app_management.util.notificationsAllowed(action.app); - - if (allowed === OptionalBool.kUnknown) { - return {allowedIds, blockedIds}; - } - - if (allowed === OptionalBool.kTrue) { - allowedIds = app_management.util.addIfNeeded(allowedIds, action.app.id); - } else { - blockedIds = app_management.util.addIfNeeded(blockedIds, action.app.id); - } - - return {allowedIds, blockedIds}; - }; - - /** - * @param {NotificationsState} notifications - * @param {Object} action - * @return {NotificationsState} - */ - NotificationsState.changeApp = function(notifications, action) { - let {allowedIds, blockedIds} = notifications; - const allowed = app_management.util.notificationsAllowed(action.app); - const id = action.app.id; - - if (allowed === OptionalBool.kUnknown) { - assert(!blockedIds.has(id) && !allowedIds.has(id)); - return {allowedIds, blockedIds}; - } - - if (allowed === OptionalBool.kTrue) { - allowedIds = app_management.util.addIfNeeded(allowedIds, id); - blockedIds = app_management.util.removeIfNeeded(blockedIds, id); - } else { - allowedIds = app_management.util.removeIfNeeded(allowedIds, id); - blockedIds = app_management.util.addIfNeeded(blockedIds, id); - } - - return {allowedIds, blockedIds}; - }; - - /** - * @param {NotificationsState} notifications - * @param {Object} action - * @return {NotificationsState} - */ - NotificationsState.removeApp = function(notifications, action) { - let {allowedIds, blockedIds} = notifications; - allowedIds = app_management.util.removeIfNeeded(allowedIds, action.id); - blockedIds = app_management.util.removeIfNeeded(blockedIds, action.id); - - return {allowedIds, blockedIds}; - }; - - /** - * @param {NotificationsState} notifications - * @param {Object} action - * @return {NotificationsState} - */ - NotificationsState.updateNotifications = function(notifications, action) { - switch (action.name) { - case 'add-app': - return NotificationsState.addApp(notifications, action); - case 'change-app': - return NotificationsState.changeApp(notifications, action); - case 'remove-app': - return NotificationsState.removeApp(notifications, action); - default: - return notifications; - } - }; - const ArcSupported = {}; /** @@ -244,8 +158,6 @@ currentPage: CurrentPageState.updateCurrentPage( state.apps, state.currentPage, action), arcSupported: ArcSupported.updateArcSupported(state.arcSupported, action), - notifications: - NotificationsState.updateNotifications(state.notifications, action), }; } @@ -254,6 +166,5 @@ AppState: AppState, CurrentPageState: CurrentPageState, ArcSupported: ArcSupported, - NotificationsState: NotificationsState, }; });
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js index 072e37c..d00cdde2 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/types.js
@@ -37,18 +37,9 @@ /** * @typedef {{ - * allowedIds: !Set<string>, - * blockedIds: !Set<string>, - * }} - */ -let NotificationsState; - -/** - * @typedef {{ * apps: !AppMap, * currentPage: !Page, * arcSupported: boolean, - * notifications: !NotificationsState, * }} */ let AppManagementPageState;
diff --git a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js index 032ccf4..6c0f679 100644 --- a/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js +++ b/chrome/browser/resources/settings/chromeos/os_apps_page/app_management_page/util.js
@@ -18,10 +18,6 @@ selectedAppId: null, }, arcSupported: false, - notifications: { - allowedIds: new Set(), - blockedIds: new Set(), - }, }; } @@ -38,18 +34,6 @@ for (const app of apps) { initialState.apps[app.id] = app; - - const allowed = notificationsAllowed(app); - - if (allowed === OptionalBool.kUnknown) { - continue; - } - - if (allowed === OptionalBool.kTrue) { - initialState.notifications.allowedIds.add(app.id); - } else { - initialState.notifications.blockedIds.add(app.id); - } } return initialState; @@ -112,53 +96,6 @@ } /** - * This function determines whether the given app should be treated by the - * notifications view as having notifications allowed or blocked, or not - * having a notifications permission at all. - * - * There are three possible cases: - * - kUnknown is returned if the given app does not have a notifications - * permission, due to how permissions work for its AppType. - * - kTrue is returned if the notifications permission of the app is allowed. - * - kFalse is returned if the notifications permission of the app is - * - blocked, or set to ask in the case of a tristate permission. - * - * @param {App} app - * @return {OptionalBool} - */ - function notificationsAllowed(app) { - const permissionType = notificationsPermissionType(app); - - if (!permissionType) { - return OptionalBool.kUnknown; - } - - if (getPermissionValueBool(app, permissionType)) { - return OptionalBool.kTrue; - } else { - return OptionalBool.kFalse; - } - } - - /** - * Returns a string corresponding to the notifications value of the - * appropriate permission type enum, based on the type of the app. - * Returns null if the app type doesn't have a notifications permission. - * @param {App} app - * @return {?string} - */ - function notificationsPermissionType(app) { - switch (app.type) { - case AppType.kWeb: - return 'CONTENT_SETTINGS_TYPE_NOTIFICATIONS'; - // TODO(rekanorman): Add another case once notifications permissions - // are implemented for ARC. - default: - return null; - } - } - - /** * @param {App} app * @param {string} permissionType * @return {boolean} @@ -264,8 +201,6 @@ getPermission: getPermission, getPermissionValueBool: getPermissionValueBool, getSelectedApp: getSelectedApp, - notificationsAllowed: notificationsAllowed, - notificationsPermissionType: notificationsPermissionType, permissionTypeHandle: permissionTypeHandle, removeIfNeeded: removeIfNeeded, toggleOptionalBool: toggleOptionalBool,
diff --git a/chrome/browser/resources/signin/signin_error/signin_error.html b/chrome/browser/resources/signin/signin_error/signin_error.html index 8510d635..fb8c5a7 100644 --- a/chrome/browser/resources/signin/signin_error/signin_error.html +++ b/chrome/browser/resources/signin/signin_error/signin_error.html
@@ -6,12 +6,17 @@ <link rel="import" href="chrome://resources/html/polymer.html"> <link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/color.html"> <link rel="import" href="signin_shared_css.html"> + <link rel="stylesheet" href="chrome://resources/css/md_colors.css"> <link rel="stylesheet" href="chrome://resources/css/text_defaults_md.css"> <link rel="import" href="chrome://resources/html/cr.html"> <link rel="import" href="chrome://resources/html/load_time_data.html"> <link rel="import" href="chrome://resources/html/util.html"> <custom-style> <style include="signin-dialog-shared"> + html { + background: var(--md-background-color); + } + .details { line-height: 20px; margin-bottom: 8px;
diff --git a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.cc b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.cc index 0493cc6..9462bddf 100644 --- a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.cc +++ b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.cc
@@ -3,10 +3,12 @@ // found in the LICENSE file. #include "chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.h" +#include <pthread.h> #include <algorithm> #include <iterator> +#include "base/i18n/case_conversion.h" #include "base/strings/strcat.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" @@ -15,7 +17,11 @@ namespace app_list { namespace { -const double kRelevanceThreshold = 0.6; +constexpr double kDefaultRelevanceThreshold = 0.35; +constexpr double kMinScore = 0.0; +constexpr double kMaxScore = 1.0; +constexpr double kFirstCharacterMatchPenalty = 0.2; +constexpr double kPrefixMatchPenalty = 0.1; // Returns sorted tokens from a TokenizedString. std::vector<base::string16> ProcessAndSort(const TokenizedString& text) { @@ -28,6 +34,61 @@ } } // namespace +namespace internal { +// Check if the query only contains first characters of the text, +// e.g. "coc" is a match of "Clash of Clan". Range of the score is [0, 1]. +double FirstCharacterMatch(const TokenizedString& query, + const TokenizedString& text) { + const base::string16 query_lower = base::i18n::ToLower(query.text()); + size_t query_index = 0; + for (size_t text_index = 0; text_index < text.tokens().size(); text_index++) { + if (query_index < query_lower.size() && + text.tokens()[text_index][0] == query_lower[query_index]) { + query_index++; + if (query_index == query_lower.size()) { + // Penalizes the score using the number of text's tokens that are + // needed. + return std::max(kMinScore, + kMaxScore - kFirstCharacterMatchPenalty * + (text_index + 1 - query_lower.size())); + } + } + } + return kMinScore; +} + +// Check if tokens of query are prefixes of text's tokens. Range of score is +// [0, 1]. +double PrefixMatch(const TokenizedString& query, const TokenizedString& text) { + const std::vector<base::string16> query_tokens(query.tokens()); + const std::vector<base::string16> text_tokens(text.tokens()); + double match_score = kMaxScore; + int previous_matched_index = -1; + // For every query token, check if it is a prefix of a text token. The newly + // matching text token must have higher index than the previous matched token. + for (const auto& query_token : query_tokens) { + bool matched = false; + for (size_t text_index = previous_matched_index + 1; + text_index < text_tokens.size(); text_index++) { + if (query_token.size() <= text_tokens[text_index].size() && + query_token == + text_tokens[text_index].substr(0, query_token.size())) { + matched = true; + // Penalizes the score based on the number of skipped tokens. + match_score -= + kPrefixMatchPenalty * (text_index - previous_matched_index - 1); + previous_matched_index = text_index; + break; + } + } + if (!matched) { + return kMinScore; + } + } + return std::max(kMinScore, match_score); +} +} // namespace internal + FuzzyTokenizedStringMatch::~FuzzyTokenizedStringMatch() {} FuzzyTokenizedStringMatch::FuzzyTokenizedStringMatch() {} @@ -100,7 +161,7 @@ double FuzzyTokenizedStringMatch::PartialRatio(const base::string16& query, const base::string16& text) { if (query.empty() || text.empty()) { - return 0.0; + return kMinScore; } base::string16 shorter = query; base::string16 longer = text; @@ -127,7 +188,7 @@ SequenceMatcher(shorter, longer.substr(long_start, shorter.size())) .Ratio(false /*use_edit_distance*/)); if (partial_ratio > 0.995) { - return 1; + return kMaxScore; } } return partial_ratio; @@ -136,11 +197,18 @@ double FuzzyTokenizedStringMatch::WeightedRatio(const TokenizedString& query, const TokenizedString& text) { const double unbase_scale = 0.95; - double weighted_ratio = SequenceMatcher(query.text(), text.text()) + // Since query.text() and text.text() is not normalized, we use query.tokens() + // and text.tokens() instead. + const base::string16 query_normalized( + base::JoinString(query.tokens(), base::UTF8ToUTF16(" "))); + const base::string16 text_normalized( + base::JoinString(text.tokens(), base::UTF8ToUTF16(" "))); + double weighted_ratio = SequenceMatcher(query_normalized, text_normalized) .Ratio(false /*use_edit_distance*/); const double length_ratio = - static_cast<double>(std::max(query.text().size(), text.text().size())) / - std::min(query.text().size(), text.text().size()); + static_cast<double>( + std::max(query_normalized.size(), text_normalized.size())) / + std::min(query_normalized.size(), text_normalized.size()); // Use partial if two strings are quite different in sizes. const bool use_partial = length_ratio >= 1.5; @@ -150,24 +218,30 @@ // If one string is much much shorter than the other, set |partial_scale| to // be 0.6, otherwise set it to be 0.9. partial_scale = length_ratio > 8 ? 0.6 : 0.9; - weighted_ratio = - std::max(weighted_ratio, - PartialRatio(query.text(), text.text()) * partial_scale); + weighted_ratio = std::max( + weighted_ratio, + PartialRatio(query_normalized, text_normalized) * partial_scale); } weighted_ratio = std::max( - weighted_ratio, TokenSortRatio(query, text, /*partial=*/use_partial) * + weighted_ratio, TokenSortRatio(query, text, use_partial /*partial*/) * unbase_scale * partial_scale); weighted_ratio = std::max( - weighted_ratio, TokenSetRatio(query, text, /*partial=*/use_partial) * + weighted_ratio, TokenSetRatio(query, text, use_partial /*partial*/) * unbase_scale * partial_scale); return weighted_ratio; } +double FuzzyTokenizedStringMatch::PrefixMatcher(const TokenizedString& query, + const TokenizedString& text) { + return std::max(internal::PrefixMatch(query, text), + internal::FirstCharacterMatch(query, text)); +} + bool FuzzyTokenizedStringMatch::IsRelevant(const TokenizedString& query, const TokenizedString& text) { - // TODO(crbug.com/990684): add prefix matching logic. - relevance_ = WeightedRatio(query, text); - return relevance_ > kRelevanceThreshold; + // |relevance_| is the average of WeightedRatio and PrefixMatcher scores. + relevance_ = (WeightedRatio(query, text) + PrefixMatcher(query, text)) / 2; + return relevance_ > kDefaultRelevanceThreshold; } } // namespace app_list
diff --git a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.h b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.h index 4a6192a..5c7bb0b 100644 --- a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.h +++ b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match.h
@@ -60,6 +60,12 @@ // The return score is in range of [0, 1]. double WeightedRatio(const TokenizedString& query, const TokenizedString& text); + // Since prefix match should always be favored over other matches, this + // function is dedicated to calculate a prefix match score in range of [0, 1]. + // This score has two components: first character match and whole prefix + // match. + double PrefixMatcher(const TokenizedString& query, + const TokenizedString& text); // Score in range of [0,1] representing how well the query matches the text. double relevance_ = 0; Hits hits_; @@ -67,6 +73,11 @@ DISALLOW_COPY_AND_ASSIGN(FuzzyTokenizedStringMatch); }; +namespace internal { +double FirstCharacterMatch(const TokenizedString& query, + const TokenizedString& text); +double PrefixMatch(const TokenizedString& query, const TokenizedString& text); +} // namespace internal } // namespace app_list #endif // CHROME_BROWSER_UI_APP_LIST_SEARCH_SEARCH_UTILS_FUZZY_TOKENIZED_STRING_MATCH_H_
diff --git a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match_unittest.cc b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match_unittest.cc index eb7cdef..db4dd78 100644 --- a/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match_unittest.cc +++ b/chrome/browser/ui/app_list/search/search_utils/fuzzy_tokenized_string_match_unittest.cc
@@ -121,8 +121,8 @@ 0.67, 0.01); } { - base::string16 query(base::UTF8ToUTF16("clash of clan")); - base::string16 text(base::UTF8ToUTF16("clash of titan")); + base::string16 query(base::UTF8ToUTF16("Clash.of.clan")); + base::string16 text(base::UTF8ToUTF16("ClashOfTitan")); EXPECT_NEAR( match.WeightedRatio(TokenizedString(query), TokenizedString(text)), 0.81, 0.01); @@ -135,7 +135,7 @@ 0.96, 0.01); } { - base::string16 query(base::UTF8ToUTF16("short text")); + base::string16 query(base::UTF8ToUTF16("short text!!!")); base::string16 text( base::UTF8ToUTF16("this sentence is much much much much much longer " "than the text before")); @@ -144,4 +144,59 @@ 0.85, 0.01); } } + +TEST_F(FuzzyTokenizedStringMatchTest, FirstCharacterMatchTest) { + { + base::string16 query(base::UTF8ToUTF16("COC")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ(internal::FirstCharacterMatch(TokenizedString(query), + TokenizedString(text)), + 1.0); + } + { + base::string16 query(base::UTF8ToUTF16("CC")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ(internal::FirstCharacterMatch(TokenizedString(query), + TokenizedString(text)), + 0.8); + } + { + base::string16 query(base::UTF8ToUTF16("C o C")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ(internal::FirstCharacterMatch(TokenizedString(query), + TokenizedString(text)), + 0.0); + } +} + +TEST_F(FuzzyTokenizedStringMatchTest, PrefixMatchTest) { + { + base::string16 query(base::UTF8ToUTF16("clas")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ( + internal::PrefixMatch(TokenizedString(query), TokenizedString(text)), + 1.0); + } + { + base::string16 query(base::UTF8ToUTF16("clash clan")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ( + internal::PrefixMatch(TokenizedString(query), TokenizedString(text)), + 0.9); + } + { + base::string16 query(base::UTF8ToUTF16("c o c")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ( + internal::PrefixMatch(TokenizedString(query), TokenizedString(text)), + 1.0); + } + { + base::string16 query(base::UTF8ToUTF16("clam")); + base::string16 text(base::UTF8ToUTF16("Clash of Clan")); + EXPECT_EQ( + internal::PrefixMatch(TokenizedString(query), TokenizedString(text)), + 0.0); + } +} } // namespace app_list
diff --git a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc index d43685a..b9b1fcd 100644 --- a/chrome/browser/ui/ash/launcher/launcher_context_menu.cc +++ b/chrome/browser/ui/ash/launcher/launcher_context_menu.cc
@@ -10,6 +10,8 @@ #include "ash/public/cpp/shelf_model.h" #include "ash/public/cpp/tablet_mode.h" #include "base/metrics/user_metrics.h" +#include "chrome/browser/apps/app_service/app_service_proxy.h" +#include "chrome/browser/apps/app_service/app_service_proxy_factory.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service.h" #include "chrome/browser/chromeos/crostini/crostini_registry_service_factory.h" #include "chrome/browser/profiles/profile.h" @@ -22,6 +24,7 @@ #include "chrome/browser/ui/ash/launcher/crostini_shelf_context_menu.h" #include "chrome/browser/ui/ash/launcher/extension_launcher_context_menu.h" #include "chrome/browser/ui/ash/launcher/internal_app_shelf_context_menu.h" +#include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "ui/display/types/display_constants.h" #include "ui/gfx/paint_vector_icon.h" @@ -30,6 +33,14 @@ namespace { void UninstallApp(Profile* profile, const std::string& app_id) { + if (base::FeatureList::IsEnabled(features::kAppServiceShelf)) { + apps::AppServiceProxy* proxy = + apps::AppServiceProxyFactory::GetForProfile(profile); + DCHECK(proxy); + proxy->Uninstall(app_id); + return; + } + // ExtensionUninstall deletes itself when done or aborted. ExtensionUninstaller* uninstaller = new ExtensionUninstaller(profile, app_id); uninstaller->Run();
diff --git a/chrome/browser/ui/chrome_pages.cc b/chrome/browser/ui/chrome_pages.cc index f9cae93..1e00104 100644 --- a/chrome/browser/ui/chrome_pages.cc +++ b/chrome/browser/ui/chrome_pages.cc
@@ -140,7 +140,7 @@ chromeos::default_web_apps::kReleaseNotesAppId, extensions::ExtensionRegistry::EVERYTHING); if (extension) { - AppLaunchParams params = CreateAppLaunchParamsWithEventFlags( + apps::AppLaunchParams params = CreateAppLaunchParamsWithEventFlags( profile, extension, 0, apps::mojom::AppLaunchSource::kSourceUntracked, -1); params.override_url = GURL(BuildQueryString(profile)); @@ -184,8 +184,8 @@ default: NOTREACHED() << "Unhandled help source" << source; } - apps::LaunchService::Get(profile)->OpenApplication(AppLaunchParams( - profile, extension_misc::kGeniusAppId, + apps::LaunchService::Get(profile)->OpenApplication(apps::AppLaunchParams( + extension_misc::kGeniusAppId, extensions::GetLaunchContainer(extensions::ExtensionPrefs::Get(profile), extension), WindowOpenDisposition::NEW_FOREGROUND_TAB, app_launch_source, true));
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc index edf821b1..2f61d11 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_bar_view_test.cc
@@ -17,7 +17,6 @@ #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/bookmarks/bookmark_model_factory.h" #include "chrome/browser/chrome_content_browser_client.h" -#include "chrome/browser/chrome_notification_types.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/ui/bookmarks/bookmark_utils.h" #include "chrome/browser/ui/bookmarks/bookmark_utils_desktop.h" @@ -26,6 +25,7 @@ #include "chrome/browser/ui/browser_window.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/views/bookmarks/bookmark_bar_view_observer.h" +#include "chrome/browser/ui/views/bookmarks/bookmark_context_menu.h" #include "chrome/browser/ui/views/bookmarks/bookmark_menu_controller_views.h" #include "chrome/browser/ui/views/chrome_constrained_window_views_client.h" #include "chrome/browser/ui/views/chrome_layout_provider.h" @@ -42,7 +42,6 @@ #include "components/bookmarks/test/bookmark_test_helpers.h" #include "components/constrained_window/constrained_window_views.h" #include "components/prefs/pref_service.h" -#include "content/public/browser/notification_service.h" #include "content/public/browser/page_navigator.h" #include "content/public/test/test_browser_thread.h" #include "ui/base/clipboard/clipboard.h" @@ -721,25 +720,21 @@ // which invokes the event loop. // Because |task| is a OnceClosure, callers should use a separate observer // instance for each successive context menu creation they wish to observe. -class BookmarkContextMenuNotificationObserver - : public content::NotificationObserver { +class BookmarkContextMenuNotificationObserver { public: explicit BookmarkContextMenuNotificationObserver(base::OnceClosure task) : task_(std::move(task)) { - registrar_.Add(this, - chrome::NOTIFICATION_BOOKMARK_CONTEXT_MENU_SHOWN, - content::NotificationService::AllSources()); + BookmarkContextMenu::InstallPreRunCallback(base::BindOnce( + &BookmarkContextMenuNotificationObserver::ScheduleCallback, + base::Unretained(this))); } - void Observe(int type, - const content::NotificationSource& source, - const content::NotificationDetails& details) override { + void ScheduleCallback() { DCHECK(!task_.is_null()); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, std::move(task_)); } private: - content::NotificationRegistrar registrar_; base::OnceClosure task_; DISALLOW_COPY_AND_ASSIGN(BookmarkContextMenuNotificationObserver);
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc index fad284c..40b1562 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc +++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.cc
@@ -6,6 +6,7 @@ #include "base/command_line.h" #include "base/i18n/rtl.h" +#include "base/lazy_instance.h" #include "base/strings/utf_string_conversions.h" #include "chrome/app/chrome_command_ids.h" #include "chrome/browser/chrome_notification_types.h" @@ -22,6 +23,9 @@ namespace { +base::LazyInstance<base::OnceClosure>::Leaky pre_run_callback = + LAZY_INSTANCE_INITIALIZER; + // Returns true if |command_id| corresponds to a command that causes one or more // bookmarks to be removed. bool IsRemoveBookmarksCommand(int command_id) { @@ -69,15 +73,19 @@ BookmarkContextMenu::~BookmarkContextMenu() { } +void BookmarkContextMenu::InstallPreRunCallback(base::OnceClosure callback) { + DCHECK(pre_run_callback.Get().is_null()); + pre_run_callback.Get() = std::move(callback); +} + void BookmarkContextMenu::RunMenuAt(const gfx::Point& point, ui::MenuSourceType source_type) { if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kKioskMode)) return; - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_BOOKMARK_CONTEXT_MENU_SHOWN, - content::Source<BookmarkContextMenu>(this), - content::NotificationService::NoDetails()); + if (!pre_run_callback.Get().is_null()) + std::move(pre_run_callback.Get()).Run(); + // width/height don't matter here. menu_runner_->RunMenuAt(parent_widget_, nullptr, gfx::Rect(point.x(), point.y(), 0, 0),
diff --git a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.h b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.h index 09203bb..4b97f3f 100644 --- a/chrome/browser/ui/views/bookmarks/bookmark_context_menu.h +++ b/chrome/browser/ui/views/bookmarks/bookmark_context_menu.h
@@ -50,6 +50,11 @@ bool close_on_remove); ~BookmarkContextMenu() override; + // Installs a callback to be run before the context menu is run. The callback + // runs only once, and only one such callback can be set at any time. Once the + // installed callback is run, another callback can be installed. + static void InstallPreRunCallback(base::OnceClosure callback); + // Shows the context menu at the specified point. void RunMenuAt(const gfx::Point& point, ui::MenuSourceType source_type);
diff --git a/chrome/browser/ui/views/frame/browser_frame.h b/chrome/browser/ui/views/frame/browser_frame.h index d168479..1a19ebe 100644 --- a/chrome/browser/ui/views/frame/browser_frame.h +++ b/chrome/browser/ui/views/frame/browser_frame.h
@@ -10,13 +10,13 @@ #include "base/macros.h" #include "base/scoped_observer.h" #include "build/build_config.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "content/public/browser/keyboard_event_processing_result.h" #include "ui/base/material_design/material_design_controller.h" #include "ui/base/material_design/material_design_controller_observer.h" #include "ui/views/context_menu_controller.h" #include "ui/views/widget/widget.h" +class BrowserNonClientFrameView; class BrowserRootView; class BrowserView; class NativeBrowserFrame;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc index bf7274b8..6529f4d 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.cc
@@ -87,7 +87,7 @@ } bool BrowserNonClientFrameView::HasVisibleBackgroundTabShapes( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { DCHECK(browser_view_->IsTabStripVisible()); TabStrip* const tab_strip = browser_view_->tabstrip(); @@ -128,8 +128,8 @@ } bool BrowserNonClientFrameView::EverHasVisibleBackgroundTabShapes() const { - return HasVisibleBackgroundTabShapes(kActive) || - HasVisibleBackgroundTabShapes(kInactive); + return HasVisibleBackgroundTabShapes(BrowserFrameActiveState::kActive) || + HasVisibleBackgroundTabShapes(BrowserFrameActiveState::kInactive); } bool BrowserNonClientFrameView::CanDrawStrokes() const { @@ -138,12 +138,12 @@ } SkColor BrowserNonClientFrameView::GetCaptionColor( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { return color_utils::GetColorWithMaxContrast(GetFrameColor(active_state)); } SkColor BrowserNonClientFrameView::GetFrameColor( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { ThemeProperties::OverwritableByUserThemeProperty color_id; color_id = ShouldPaintAsActive(active_state) @@ -182,7 +182,7 @@ } base::Optional<int> BrowserNonClientFrameView::GetCustomBackgroundId( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); const bool incognito = browser_view_->IsIncognito(); const bool active = ShouldPaintAsActive(active_state); @@ -246,13 +246,14 @@ } bool BrowserNonClientFrameView::ShouldPaintAsActive( - ActiveState active_state) const { - return (active_state == kUseCurrent) ? ShouldPaintAsActive() - : (active_state == kActive); + BrowserFrameActiveState active_state) const { + return (active_state == BrowserFrameActiveState::kUseCurrent) + ? ShouldPaintAsActive() + : (active_state == BrowserFrameActiveState::kActive); } gfx::ImageSkia BrowserNonClientFrameView::GetFrameImage( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProviderForProfile(); const int frame_image_id = ShouldPaintAsActive(active_state) ? IDR_THEME_FRAME @@ -264,7 +265,7 @@ } gfx::ImageSkia BrowserNonClientFrameView::GetFrameOverlayImage( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { if (browser_view_->IsIncognito() || !browser_view_->IsBrowserTypeNormal()) return gfx::ImageSkia();
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h index 125e343..8c3db647 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view.h
@@ -16,20 +16,20 @@ class BrowserView; class WebAppFrameToolbarView; +// Type used for functions whose return values depend on the active state of +// the frame. +enum class BrowserFrameActiveState { + kUseCurrent, // Use current frame active state. + kActive, // Treat frame as active regardless of current state. + kInactive, // Treat frame as inactive regardless of current state. +}; + // A specialization of the NonClientFrameView object that provides additional // Browser-specific methods. class BrowserNonClientFrameView : public views::NonClientFrameView, public ProfileAttributesStorage::Observer, public TabStripObserver { public: - // Type used for functions whose return values depend on the active state of - // the frame. - enum ActiveState { - kUseCurrent, // Use current frame active state. - kActive, // Treat frame as active regardless of current state. - kInactive, // Treat frame as inactive regardless of current state. - }; - // The minimum total height users should have to use as a drag handle to move // the window with. static constexpr int kMinimumDragHeight = 8; @@ -85,7 +85,7 @@ // Returns whether the shapes of background tabs are visible against the // frame, given an active state of |active|. virtual bool HasVisibleBackgroundTabShapes( - ActiveState active_state = kUseCurrent) const; + BrowserFrameActiveState active_state) const; // Returns whether the shapes of background tabs are visible against the frame // for either active or inactive windows. @@ -96,11 +96,12 @@ // Returns the color to use for text, caption buttons, and other title bar // elements. - virtual SkColor GetCaptionColor(ActiveState active_state = kUseCurrent) const; + virtual SkColor GetCaptionColor(BrowserFrameActiveState active_state) const; // Returns the color of the browser frame, which is also the color of the // tabstrip background. - SkColor GetFrameColor(ActiveState active_state = kUseCurrent) const; + SkColor GetFrameColor(BrowserFrameActiveState active_state = + BrowserFrameActiveState::kUseCurrent) const; // Called by BrowserView to signal the frame color has changed and needs // to be repainted. @@ -112,7 +113,8 @@ // For non-transparent windows, returns the background tab image resource ID // if the image has been customized, directly or indirectly, by the theme. - base::Optional<int> GetCustomBackgroundId(ActiveState active_state) const; + base::Optional<int> GetCustomBackgroundId( + BrowserFrameActiveState active_state) const; // Updates the throbber. virtual void UpdateThrobber(bool running) = 0; @@ -134,12 +136,14 @@ protected: // Converts an ActiveState to a bool representing whether the frame should be // treated as active. - bool ShouldPaintAsActive(ActiveState active_state) const; + bool ShouldPaintAsActive(BrowserFrameActiveState active_state) const; // Compute aspects of the frame needed to paint the frame background. - gfx::ImageSkia GetFrameImage(ActiveState active_state = kUseCurrent) const; + gfx::ImageSkia GetFrameImage(BrowserFrameActiveState active_state = + BrowserFrameActiveState::kUseCurrent) const; gfx::ImageSkia GetFrameOverlayImage( - ActiveState active_state = kUseCurrent) const; + BrowserFrameActiveState active_state = + BrowserFrameActiveState::kUseCurrent) const; // views::NonClientFrameView: void ChildPreferredSizeChanged(views::View* child) override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc index 6ae027a..ef6caa3 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.cc
@@ -222,8 +222,8 @@ aura::Window* window = frame()->GetNativeWindow(); base::Optional<SkColor> active_color, inactive_color; if (!UsePackagedAppHeaderStyle(browser_view()->browser())) { - active_color = GetFrameColor(kActive); - inactive_color = GetFrameColor(kInactive); + active_color = GetFrameColor(BrowserFrameActiveState::kActive); + inactive_color = GetFrameColor(BrowserFrameActiveState::kInactive); } else if (browser_view()->IsBrowserTypeWebApp()) { active_color = browser_view()->browser()->app_controller()->GetThemeColor(); } else if (!browser_view()->browser()->deprecated_is_app()) { @@ -257,7 +257,7 @@ } SkColor BrowserNonClientFrameViewAsh::GetCaptionColor( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { bool active = ShouldPaintAsActive(active_state); SkColor active_color = @@ -448,11 +448,13 @@ } SkColor BrowserNonClientFrameViewAsh::GetFrameHeaderColor(bool active) { - return GetFrameColor(active ? kActive : kInactive); + return GetFrameColor(active ? BrowserFrameActiveState::kActive + : BrowserFrameActiveState::kInactive); } gfx::ImageSkia BrowserNonClientFrameViewAsh::GetFrameHeaderImage(bool active) { - return GetFrameImage(active ? kActive : kInactive); + return GetFrameImage(active ? BrowserFrameActiveState::kActive + : BrowserFrameActiveState::kInactive); } int BrowserNonClientFrameViewAsh::GetFrameHeaderImageYInset() { @@ -461,7 +463,8 @@ gfx::ImageSkia BrowserNonClientFrameViewAsh::GetFrameHeaderOverlayImage( bool active) { - return GetFrameOverlayImage(active ? kActive : kInactive); + return GetFrameOverlayImage(active ? BrowserFrameActiveState::kActive + : BrowserFrameActiveState::kInactive); } /////////////////////////////////////////////////////////////////////////////// @@ -700,8 +703,9 @@ // Add the container for extra web app buttons (e.g app menu button). set_web_app_frame_toolbar(new WebAppFrameToolbarView( - frame(), browser_view(), GetCaptionColor(kActive), - GetCaptionColor(kInactive))); + frame(), browser_view(), + GetCaptionColor(BrowserFrameActiveState::kActive), + GetCaptionColor(BrowserFrameActiveState::kInactive))); AddChildView(web_app_frame_toolbar()); }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h index 9d2383c7..1b0243d 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_ash.h
@@ -58,7 +58,7 @@ void UpdateFrameColor() override; void UpdateThrobber(bool running) override; bool CanUserExitFullscreen() const override; - SkColor GetCaptionColor(ActiveState active_state) const override; + SkColor GetCaptionColor(BrowserFrameActiveState active_state) const override; // views::NonClientFrameView: gfx::Rect GetBoundsForClientView() const override;
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc index d1ec73b..90bc434 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_browsertest.cc
@@ -93,9 +93,9 @@ theme_provider->GetColor(ThemeProperties::COLOR_FRAME_INACTIVE); EXPECT_EQ(expected_active_color, - frame_view->GetFrameColor(BrowserNonClientFrameView::kActive)); + frame_view->GetFrameColor(BrowserFrameActiveState::kActive)); EXPECT_EQ(expected_inactive_color, - frame_view->GetFrameColor(BrowserNonClientFrameView::kInactive)); + frame_view->GetFrameColor(BrowserFrameActiveState::kInactive)); } // Tests the frame color for a bookmark app when a theme is applied. @@ -108,7 +108,7 @@ // Note: This is checking for the bookmark app's theme color, not the user's // theme color. EXPECT_EQ(*app_theme_color_, - app_frame_view_->GetFrameColor(BrowserNonClientFrameView::kActive)); + app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive)); } // Tests the frame color for a bookmark app when a theme is applied, with the @@ -121,7 +121,7 @@ // Bookmark apps are not affected by browser themes. EXPECT_EQ( ThemeProperties::GetDefaultColor(ThemeProperties::COLOR_FRAME, false), - app_frame_view_->GetFrameColor(BrowserNonClientFrameView::kActive)); + app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive)); } // Tests the frame color for a bookmark app when the system theme is applied. @@ -144,10 +144,10 @@ const SkColor frame_color = theme_provider->GetColor(ThemeProperties::COLOR_FRAME); EXPECT_EQ(frame_color, - app_frame_view_->GetFrameColor(BrowserNonClientFrameView::kActive)); + app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive)); #else EXPECT_EQ(*app_theme_color_, - app_frame_view_->GetFrameColor(BrowserNonClientFrameView::kActive)); + app_frame_view_->GetFrameColor(BrowserFrameActiveState::kActive)); #endif }
diff --git a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm index edd7f1f..f5a1d59 100644 --- a/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm +++ b/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.mm
@@ -71,8 +71,10 @@ if (browser_view->browser()->app_controller()->HasTitlebarToolbar()) { set_web_app_frame_toolbar( AddChildView(std::make_unique<WebAppFrameToolbarView>( - frame, browser_view, GetCaptionColor(kActive), - GetCaptionColor(kInactive), kHostedAppMenuMargin))); + frame, browser_view, + GetCaptionColor(BrowserFrameActiveState::kActive), + GetCaptionColor(BrowserFrameActiveState::kInactive), + kHostedAppMenuMargin))); } DCHECK(browser_view->ShouldShowWindowTitle()); @@ -307,7 +309,8 @@ if (window_title_) { window_title_->SetBackgroundColor(frame_color); - window_title_->SetEnabledColor(GetCaptionColor(kUseCurrent)); + window_title_->SetEnabledColor( + GetCaptionColor(BrowserFrameActiveState::kUseCurrent)); } auto* theme_service =
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc index 731d064..610c668b 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.cc
@@ -123,8 +123,9 @@ // delegate interface. set_web_app_frame_toolbar( AddChildView(std::make_unique<WebAppFrameToolbarView>( - frame, browser_view, GetCaptionColor(kActive), - GetCaptionColor(kInactive)))); + frame, browser_view, + GetCaptionColor(BrowserFrameActiveState::kActive), + GetCaptionColor(BrowserFrameActiveState::kInactive)))); } minimize_button_ = @@ -180,7 +181,7 @@ } bool GlassBrowserFrameView::HasVisibleBackgroundTabShapes( - ActiveState active_state) const { + BrowserFrameActiveState active_state) const { // Pre-Win 8, tabs never match the glass frame appearance. if (base::win::GetVersion() < base::win::Version::WIN8) return true; @@ -206,7 +207,8 @@ return BrowserNonClientFrameView::CanDrawStrokes(); } -SkColor GlassBrowserFrameView::GetCaptionColor(ActiveState active_state) const { +SkColor GlassBrowserFrameView::GetCaptionColor( + BrowserFrameActiveState active_state) const { const SkAlpha title_alpha = ShouldPaintAsActive(active_state) ? SK_AlphaOPAQUE : kInactiveTitlebarFeatureAlpha; @@ -640,7 +642,8 @@ } if (ShowCustomTitle()) - window_title_->SetEnabledColor(GetCaptionColor(kUseCurrent)); + window_title_->SetEnabledColor( + GetCaptionColor(BrowserFrameActiveState::kUseCurrent)); } void GlassBrowserFrameView::LayoutTitleBar() {
diff --git a/chrome/browser/ui/views/frame/glass_browser_frame_view.h b/chrome/browser/ui/views/frame/glass_browser_frame_view.h index 7ba19c7..27fc288 100644 --- a/chrome/browser/ui/views/frame/glass_browser_frame_view.h +++ b/chrome/browser/ui/views/frame/glass_browser_frame_view.h
@@ -39,9 +39,10 @@ const views::View* tabstrip) const override; int GetTopInset(bool restored) const override; int GetThemeBackgroundXInset() const override; - bool HasVisibleBackgroundTabShapes(ActiveState active_state) const override; + bool HasVisibleBackgroundTabShapes( + BrowserFrameActiveState active_state) const override; bool CanDrawStrokes() const override; - SkColor GetCaptionColor(ActiveState active_state) const override; + SkColor GetCaptionColor(BrowserFrameActiveState active_state) const override; void UpdateThrobber(bool running) override; gfx::Size GetMinimumSize() const override;
diff --git a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc index b2cca4c..6d26633d1 100644 --- a/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc +++ b/chrome/browser/ui/views/frame/opaque_browser_frame_view.cc
@@ -186,8 +186,9 @@ if (controller && controller->HasTitlebarToolbar()) { set_web_app_frame_toolbar( AddChildView(std::make_unique<WebAppFrameToolbarView>( - frame(), browser_view(), GetCaptionColor(kActive), - GetCaptionColor(kInactive)))); + frame(), browser_view(), + GetCaptionColor(BrowserFrameActiveState::kActive), + GetCaptionColor(BrowserFrameActiveState::kInactive)))); } } @@ -497,7 +498,8 @@ const bool active = ShouldPaintAsActive(); SkColor frame_color = GetFrameColor(); - window_title_->SetEnabledColor(GetCaptionColor(kUseCurrent)); + window_title_->SetEnabledColor( + GetCaptionColor(BrowserFrameActiveState::kUseCurrent)); window_title_->SetBackgroundColor(frame_color); frame_background_->set_frame_color(frame_color); frame_background_->set_use_custom_frame(frame()->UseCustomFrame());
diff --git a/chrome/browser/ui/views/frame/top_container_view.cc b/chrome/browser/ui/views/frame/top_container_view.cc index 188132c..e22f845 100644 --- a/chrome/browser/ui/views/frame/top_container_view.cc +++ b/chrome/browser/ui/views/frame/top_container_view.cc
@@ -5,6 +5,7 @@ #include "chrome/browser/ui/views/frame/top_container_view.h" #include "chrome/browser/ui/views/frame/browser_frame.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/immersive_mode_controller.h" #include "ui/views/paint_info.h"
diff --git a/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view_browsertest.cc b/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view_browsertest.cc index b10076a7..29264e8 100644 --- a/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view_browsertest.cc +++ b/chrome/browser/ui/views/plugin_vm/plugin_vm_launcher_view_browsertest.cc
@@ -23,8 +23,8 @@ #include "chrome/common/chrome_features.h" #include "chrome/grit/generated_resources.h" #include "chromeos/dbus/dbus_thread_manager.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/fake_concierge_client.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" #include "chromeos/tpm/stub_install_attributes.h" #include "components/account_id/account_id.h" #include "components/download/public/background_service/download_metadata.h"
diff --git a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc index 5010883..862f0c5 100644 --- a/chrome/browser/ui/views/profiles/profile_menu_view_base.cc +++ b/chrome/browser/ui/views/profiles/profile_menu_view_base.cc
@@ -80,17 +80,31 @@ return gfx::ImageSkiaOperations::CreateColorMask(image, color); } -gfx::ImageSkia CreateCircle(int size, SkColor color = SK_ColorWHITE) { - float radius = size / 2.0f; - gfx::Canvas canvas(gfx::Size(size, size), /*image_scale=*/1.0f, - /*is_opaque=*/false); - cc::PaintFlags flags; - flags.setAntiAlias(true); - flags.setStyle(cc::PaintFlags::kFill_Style); - flags.setColor(color); - canvas.DrawCircle(gfx::PointF(radius, radius), radius, flags); +class CircleImageSource : public gfx::CanvasImageSource { + public: + CircleImageSource(int size, SkColor color) + : gfx::CanvasImageSource(gfx::Size(size, size)), color_(color) {} + ~CircleImageSource() override = default; - return gfx::ImageSkia::CreateFrom1xBitmap(canvas.GetBitmap()); + void Draw(gfx::Canvas* canvas) override; + + private: + SkColor color_; + + DISALLOW_COPY_AND_ASSIGN(CircleImageSource); +}; + +void CircleImageSource::Draw(gfx::Canvas* canvas) { + float radius = size().width() / 2.0f; + cc::PaintFlags flags; + flags.setStyle(cc::PaintFlags::kFill_Style); + flags.setAntiAlias(true); + flags.setColor(color_); + canvas->DrawCircle(gfx::PointF(radius, radius), radius, flags); +} + +gfx::ImageSkia CreateCircle(int size, SkColor color = SK_ColorWHITE) { + return gfx::CanvasImageSource::MakeImageSkia<CircleImageSource>(size, color); } gfx::ImageSkia CropCircle(const gfx::ImageSkia& image) {
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc index 249f006..f4d1f8e 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.cc
@@ -412,7 +412,7 @@ bool BrowserTabStripController::HasVisibleBackgroundTabShapes() const { return GetFrameView()->HasVisibleBackgroundTabShapes( - BrowserNonClientFrameView::kUseCurrent); + BrowserFrameActiveState::kUseCurrent); } bool BrowserTabStripController::EverHasVisibleBackgroundTabShapes() const { @@ -428,7 +428,7 @@ } SkColor BrowserTabStripController::GetFrameColor( - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { return GetFrameView()->GetFrameColor(active_state); } @@ -437,7 +437,7 @@ } base::Optional<int> BrowserTabStripController::GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { return GetFrameView()->GetCustomBackgroundId(active_state); }
diff --git a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h index bb06179..1212ebd 100644 --- a/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/browser_tab_strip_controller.h
@@ -82,12 +82,10 @@ bool EverHasVisibleBackgroundTabShapes() const override; bool ShouldPaintAsActiveFrame() const override; bool CanDrawStrokes() const override; - SkColor GetFrameColor( - BrowserNonClientFrameView::ActiveState active_state = - BrowserNonClientFrameView::kUseCurrent) const override; + SkColor GetFrameColor(BrowserFrameActiveState active_state) const override; SkColor GetToolbarTopSeparatorColor() const override; base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const override; + BrowserFrameActiveState active_state) const override; base::string16 GetAccessibleTabName(const Tab* tab) const override; Profile* GetProfile() const override;
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc index e0c1472..d849d41 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.cc
@@ -200,7 +200,7 @@ } SkColor FakeBaseTabStripController::GetFrameColor( - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { return gfx::kPlaceholderColor; } @@ -209,7 +209,7 @@ } base::Optional<int> FakeBaseTabStripController::GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { return base::nullopt; }
diff --git a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h index dcae87a9..86e3c56 100644 --- a/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/fake_base_tab_strip_controller.h
@@ -66,12 +66,10 @@ bool EverHasVisibleBackgroundTabShapes() const override; bool ShouldPaintAsActiveFrame() const override; bool CanDrawStrokes() const override; - SkColor GetFrameColor( - BrowserNonClientFrameView::ActiveState active_state = - BrowserNonClientFrameView::kUseCurrent) const override; + SkColor GetFrameColor(BrowserFrameActiveState active_state) const override; SkColor GetToolbarTopSeparatorColor() const override; base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const override; + BrowserFrameActiveState active_state) const override; base::string16 GetAccessibleTabName(const Tab* tab) const override; Profile* GetProfile() const override;
diff --git a/chrome/browser/ui/views/tabs/new_tab_button.cc b/chrome/browser/ui/views/tabs/new_tab_button.cc index 89e1946..9e7af696 100644 --- a/chrome/browser/ui/views/tabs/new_tab_button.cc +++ b/chrome/browser/ui/views/tabs/new_tab_button.cc
@@ -230,7 +230,7 @@ const float scale = canvas->image_scale(); const base::Optional<int> bg_id = - tab_strip_->GetCustomBackgroundId(BrowserNonClientFrameView::kUseCurrent); + tab_strip_->GetCustomBackgroundId(BrowserFrameActiveState::kUseCurrent); if (bg_id.has_value() && !new_tab_promo_observer_.IsObservingSources()) { float x_scale = scale; const gfx::Rect& contents_bounds = GetContentsBounds(); @@ -258,7 +258,7 @@ void NewTabButton::PaintPlusIcon(gfx::Canvas* canvas) const { const SkColor background_color = tab_strip_->GetTabBackgroundColor( - TabActive::kInactive, BrowserNonClientFrameView::kUseCurrent); + TabActive::kInactive, BrowserFrameActiveState::kUseCurrent); cc::PaintFlags flags; flags.setAntiAlias(true); @@ -292,7 +292,7 @@ return GetThemeProvider()->GetDisplayProperty( ThemeProperties::SHOULD_FILL_BACKGROUND_TAB_COLOR) ? tab_strip_->GetTabBackgroundColor( - TabActive::kInactive, BrowserNonClientFrameView::kUseCurrent) + TabActive::kInactive, BrowserFrameActiveState::kUseCurrent) : SK_ColorTRANSPARENT; }
diff --git a/chrome/browser/ui/views/tabs/tab_controller.h b/chrome/browser/ui/views/tabs/tab_controller.h index ad37b89..f342729 100644 --- a/chrome/browser/ui/views/tabs/tab_controller.h +++ b/chrome/browser/ui/views/tabs/tab_controller.h
@@ -6,7 +6,6 @@ #define CHROME_BROWSER_UI_VIEWS_TABS_TAB_CONTROLLER_H_ #include "chrome/browser/ui/tabs/tab_types.h" -#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/tabs/tab_strip_types.h" #include "third_party/skia/include/core/SkColor.h" #include "ui/base/ui_base_types.h" @@ -15,6 +14,8 @@ class TabGroupVisualData; class TabGroupId; +enum class BrowserFrameActiveState; + namespace gfx { class Point; class Rect; @@ -136,7 +137,7 @@ // |active_state| of the window. virtual SkColor GetTabBackgroundColor( TabActive active, - BrowserNonClientFrameView::ActiveState active_state) const = 0; + BrowserFrameActiveState active_state) const = 0; // Returns the tab foreground color of the the text based on the |tab_state|, // the activation state of the window, and the current |background_color|. @@ -146,7 +147,7 @@ // Returns the background tab image resource ID if the image has been // customized, directly or indirectly, by the theme. virtual base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const = 0; + BrowserFrameActiveState active_state) const = 0; // If the given tab is animating to its target destination, this returns the // target bounds. If the tab isn't moving this will return the current bounds
diff --git a/chrome/browser/ui/views/tabs/tab_drag_controller.cc b/chrome/browser/ui/views/tabs/tab_drag_controller.cc index 59b2ab8..2c1b8c9 100644 --- a/chrome/browser/ui/views/tabs/tab_drag_controller.cc +++ b/chrome/browser/ui/views/tabs/tab_drag_controller.cc
@@ -27,6 +27,7 @@ #include "chrome/browser/ui/tabs/tab_group_id.h" #include "chrome/browser/ui/tabs/tab_strip_model.h" #include "chrome/browser/ui/tabs/tab_strip_model_delegate.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_strip.h"
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc index 6eb5874e..e4129e70 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.cc +++ b/chrome/browser/ui/views/tabs/tab_strip.cc
@@ -1238,9 +1238,9 @@ // the window activation state changes. constexpr float kMinimumContrastRatioForOutlines = 1.3f; const SkColor background_color = GetTabBackgroundColor( - TabActive::kActive, BrowserNonClientFrameView::kActive); + TabActive::kActive, BrowserFrameActiveState::kActive); const SkColor frame_color = - controller_->GetFrameColor(BrowserNonClientFrameView::kActive); + controller_->GetFrameColor(BrowserFrameActiveState::kActive); const float contrast_ratio = color_utils::GetContrastRatio(background_color, frame_color); if (contrast_ratio < kMinimumContrastRatioForOutlines) @@ -1634,7 +1634,7 @@ SkColor TabStrip::GetTabBackgroundColor( TabActive active, - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { const ui::ThemeProvider* tp = GetThemeProvider(); if (!tp) return SK_ColorBLACK; @@ -1643,10 +1643,10 @@ return tp->GetColor(ThemeProperties::COLOR_TOOLBAR); bool is_active_frame; - if (active_state == BrowserNonClientFrameView::kUseCurrent) + if (active_state == BrowserFrameActiveState::kUseCurrent) is_active_frame = ShouldPaintAsActiveFrame(); else - is_active_frame = active_state == BrowserNonClientFrameView::kActive; + is_active_frame = active_state == BrowserFrameActiveState::kActive; const int color_id = is_active_frame ? ThemeProperties::COLOR_BACKGROUND_TAB @@ -1718,7 +1718,7 @@ } base::Optional<int> TabStrip::GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const { + BrowserFrameActiveState active_state) const { if (!TitlebarBackgroundIsTransparent()) return controller_->GetCustomBackgroundId(active_state); @@ -2539,14 +2539,14 @@ return; const SkColor inactive_bg = GetTabBackgroundColor( - TabActive::kInactive, BrowserNonClientFrameView::kUseCurrent); + TabActive::kInactive, BrowserFrameActiveState::kUseCurrent); const auto get_blend = [inactive_bg](SkColor target, float contrast) { return color_utils::BlendForMinContrast(inactive_bg, inactive_bg, target, contrast); }; const SkColor active_bg = GetTabBackgroundColor( - TabActive::kActive, BrowserNonClientFrameView::kUseCurrent); + TabActive::kActive, BrowserFrameActiveState::kUseCurrent); const auto get_hover_opacity = [active_bg, &get_blend](float contrast) { return get_blend(active_bg, contrast).alpha / 255.0f; };
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h index 30fd9d0..a09afc05 100644 --- a/chrome/browser/ui/views/tabs/tab_strip.h +++ b/chrome/browser/ui/views/tabs/tab_strip.h
@@ -270,12 +270,12 @@ SkColor GetTabSeparatorColor() const override; SkColor GetTabBackgroundColor( TabActive active, - BrowserNonClientFrameView::ActiveState active_state) const override; + BrowserFrameActiveState active_state) const override; SkColor GetTabForegroundColor(TabActive active, SkColor background_color) const override; base::string16 GetAccessibleTabName(const Tab* tab) const override; base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const override; + BrowserFrameActiveState active_state) const override; gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override; float GetHoverOpacityForTab(float range_parameter) const override; float GetHoverOpacityForRadialHighlight() const override;
diff --git a/chrome/browser/ui/views/tabs/tab_strip_controller.h b/chrome/browser/ui/views/tabs/tab_strip_controller.h index c131527..7d424a3 100644 --- a/chrome/browser/ui/views/tabs/tab_strip_controller.h +++ b/chrome/browser/ui/views/tabs/tab_strip_controller.h
@@ -144,9 +144,7 @@ // Returns the color of the browser frame for the given window activation // state. - virtual SkColor GetFrameColor( - BrowserNonClientFrameView::ActiveState active_state = - BrowserNonClientFrameView::kUseCurrent) const = 0; + virtual SkColor GetFrameColor(BrowserFrameActiveState active_state) const = 0; // Returns COLOR_TOOLBAR_TOP_SEPARATOR[,_INACTIVE] depending on the activation // state of the window. @@ -155,7 +153,7 @@ // For non-transparent windows, returns the background tab image resource ID // if the image has been customized, directly or indirectly, by the theme. virtual base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const = 0; + BrowserFrameActiveState active_state) const = 0; // Returns the accessible tab name. virtual base::string16 GetAccessibleTabName(const Tab* tab) const = 0;
diff --git a/chrome/browser/ui/views/tabs/tab_style_views.cc b/chrome/browser/ui/views/tabs/tab_style_views.cc index 55b17d6..350c1d5 100644 --- a/chrome/browser/ui/views/tabs/tab_style_views.cc +++ b/chrome/browser/ui/views/tabs/tab_style_views.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/ui/tabs/tab_group_visual_data.h" #include "chrome/browser/ui/tabs/tab_types.h" #include "chrome/browser/ui/ui_features.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/tabs/glow_hover_controller.h" #include "chrome/browser/ui/views/tabs/tab.h" #include "chrome/browser/ui/views/tabs/tab_close_button.h" @@ -683,7 +684,7 @@ SkColor GM2TabStyle::GetTabBackgroundColor(TabActive active) const { SkColor color = tab_->controller()->GetTabBackgroundColor( - active, BrowserNonClientFrameView::kUseCurrent); + active, BrowserFrameActiveState::kUseCurrent); return color; } @@ -709,7 +710,7 @@ void GM2TabStyle::PaintInactiveTabBackground(gfx::Canvas* canvas) const { PaintTabBackground(canvas, TabActive::kInactive, tab_->controller()->GetCustomBackgroundId( - BrowserNonClientFrameView::kUseCurrent), + BrowserFrameActiveState::kUseCurrent), 0); }
diff --git a/chrome/browser/ui/views/tabs/tab_unittest.cc b/chrome/browser/ui/views/tabs/tab_unittest.cc index 7b6a0dc..525400c2 100644 --- a/chrome/browser/ui/views/tabs/tab_unittest.cc +++ b/chrome/browser/ui/views/tabs/tab_unittest.cc
@@ -88,7 +88,7 @@ SkColor GetTabSeparatorColor() const override { return SK_ColorBLACK; } SkColor GetTabBackgroundColor( TabActive active, - BrowserNonClientFrameView::ActiveState active_state) const override { + BrowserFrameActiveState active_state) const override { return active == TabActive::kActive ? tab_bg_color_active_ : tab_bg_color_inactive_; } @@ -98,7 +98,7 @@ : tab_fg_color_inactive_; } base::Optional<int> GetCustomBackgroundId( - BrowserNonClientFrameView::ActiveState active_state) const override { + BrowserFrameActiveState active_state) const override { return base::nullopt; } gfx::Rect GetTabAnimationTargetBounds(const Tab* tab) override { @@ -828,7 +828,7 @@ tab.UpdateForegroundColors(); const SkColor fg_color = tab.title_->GetEnabledColor(); const SkColor bg_color = controller.GetTabBackgroundColor( - active, BrowserNonClientFrameView::kUseCurrent); + active, BrowserFrameActiveState::kUseCurrent); const float contrast = color_utils::GetContrastRatio(fg_color, bg_color); EXPECT_GE(contrast, color_utils::kMinimumReadableContrastRatio); }
diff --git a/chrome/browser/ui/views/toolbar/toolbar_view.cc b/chrome/browser/ui/views/toolbar/toolbar_view.cc index ae36df4..6930256 100644 --- a/chrome/browser/ui/views/toolbar/toolbar_view.cc +++ b/chrome/browser/ui/views/toolbar/toolbar_view.cc
@@ -38,6 +38,7 @@ #include "chrome/browser/ui/views/extensions/extension_popup.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_button.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/global_media_controls/media_toolbar_button_view.h" #include "chrome/browser/ui/views/location_bar/star_view.h"
diff --git a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc index a6a333b6..ebcf005 100644 --- a/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc +++ b/chrome/browser/ui/views/web_apps/web_app_frame_toolbar_view.cc
@@ -16,6 +16,7 @@ #include "chrome/browser/ui/ui_features.h" #include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/extensions/extensions_toolbar_container.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/location_bar/content_setting_image_view.h" #include "chrome/browser/ui/views/page_action/page_action_icon_container_view.h" @@ -298,10 +299,9 @@ void WebAppFrameToolbarView::UpdateCaptionColors() { const BrowserNonClientFrameView* frame_view = browser_view_->frame()->GetFrameView(); - active_color_ = frame_view->GetCaptionColor( - BrowserNonClientFrameView::ActiveState::kActive); - inactive_color_ = frame_view->GetCaptionColor( - BrowserNonClientFrameView::ActiveState::kInactive); + active_color_ = frame_view->GetCaptionColor(BrowserFrameActiveState::kActive); + inactive_color_ = + frame_view->GetCaptionColor(BrowserFrameActiveState::kInactive); UpdateChildrenColor(); }
diff --git a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc index 38ffca2a..4954acc 100644 --- a/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc +++ b/chrome/browser/ui/web_applications/web_app_badging_browsertest.cc
@@ -72,9 +72,8 @@ // The delegate is owned by the badge manager. We hold a pointer to it for // the test. std::unique_ptr<badging::TestBadgeManagerDelegate> owned_delegate = - std::make_unique<badging::TestBadgeManagerDelegate>( - profile(), badge_manager, - &WebAppProviderBase::GetProviderBase(profile())->registrar()); + std::make_unique<badging::TestBadgeManagerDelegate>(profile(), + badge_manager); owned_delegate->SetOnBadgeChanged(base::BindRepeating( &WebAppBadgingBrowserTest::OnBadgeChanged, base::Unretained(this))); delegate_ = owned_delegate.get(); @@ -85,18 +84,18 @@ void OnBadgeChanged() { // This is only set up to deal with one badge change at a time, in order to // make asserting the result of a badge change easier. - int total_changes = delegate_->cleared_app_badges().size() + - delegate_->set_app_badges().size(); + int total_changes = + delegate_->cleared_badges().size() + delegate_->set_badges().size(); ASSERT_EQ(total_changes, 1); - if (delegate_->cleared_app_badges().size()) { - changed_app_id_ = delegate_->cleared_app_badges()[0]; + if (delegate_->cleared_badges().size()) { + changed_app_id_ = delegate_->cleared_badges()[0]; was_cleared_ = true; } - if (delegate_->set_app_badges().size() == 1) { - changed_app_id_ = delegate_->set_app_badges()[0].first; - last_badge_content_ = delegate_->set_app_badges()[0].second; + if (delegate_->set_badges().size() == 1) { + changed_app_id_ = delegate_->set_badges()[0].first; + last_badge_content_ = delegate_->set_badges()[0].second; was_flagged_ = last_badge_content_ == base::nullopt; }
diff --git a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc index 35e1595..49edf06 100644 --- a/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc +++ b/chrome/browser/ui/webui/chromeos/login/enable_debugging_screen_handler.cc
@@ -21,7 +21,7 @@ #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/cryptohome/cryptohome_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/power/power_manager_client.h" #include "components/login/localized_values_builder.h" #include "components/prefs/pref_registry_simple.h"
diff --git a/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc b/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc index 4a50ff5..7270b11 100644 --- a/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc +++ b/chrome/browser/ui/webui/chromeos/smb_shares/smb_shares_localized_strings_provider.cc
@@ -44,6 +44,8 @@ IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_URL_MESSAGE}, {"smbShareAddedInvalidSSOURLMessage", IDS_SETTINGS_DOWNLOADS_SHARE_ADDED_MOUNT_INVALID_SSO_URL_MESSAGE}, + {"smbShareDiscoveryMessage", + IDS_SETTINGS_DOWNLOADS_ADD_SHARE_DISCOVERY_MESSAGE}, }; AddLocalizedStringsBulk(html_source, kLocalizedStrings, base::size(kLocalizedStrings));
diff --git a/chrome/browser/ui/webui/crashes_ui.cc b/chrome/browser/ui/webui/crashes_ui.cc index ba48748..08075f51 100644 --- a/chrome/browser/ui/webui/crashes_ui.cc +++ b/chrome/browser/ui/webui/crashes_ui.cc
@@ -34,7 +34,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #endif #if defined(OS_LINUX)
diff --git a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc index 8c5bfd5d..f433a77 100644 --- a/chrome/browser/ui/webui/net_internals/net_internals_ui.cc +++ b/chrome/browser/ui/webui/net_internals/net_internals_ui.cc
@@ -44,7 +44,7 @@ #include "chrome/browser/policy/policy_conversions.h" #include "chrome/common/logging_chrome.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/network/onc/onc_certificate_importer_impl.h" #include "chromeos/network/onc/onc_parsed_certificates.h" #include "chromeos/network/onc/onc_utils.h"
diff --git a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc index 9b926a8..22efad2c 100644 --- a/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc +++ b/chrome/browser/ui/webui/print_preview/local_printer_handler_chromeos.cc
@@ -25,7 +25,7 @@ #include "chrome/browser/ui/webui/print_preview/print_preview_utils.h" #include "chrome/common/pref_names.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/printing/printer_configuration.h" #include "components/prefs/pref_service.h" #include "components/printing/browser/printer_capabilities.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc index 49139ae..b9660fb 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler.cc
@@ -36,7 +36,7 @@ #include "chrome/common/chrome_paths.h" #include "chrome/common/pref_names.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/printing/ppd_cache.h" #include "chromeos/printing/ppd_line_reader.h" #include "chromeos/printing/ppd_provider.h"
diff --git a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc index c9c52df5..e861529 100644 --- a/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc +++ b/chrome/browser/ui/webui/settings/chromeos/cups_printers_handler_unittest.cc
@@ -12,7 +12,7 @@ #include "chrome/browser/chromeos/printing/printing_stubs.h" #include "chrome/test/base/testing_profile.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "content/public/test/browser_task_environment.h" #include "content/public/test/test_web_ui.h" #include "testing/gtest/include/gtest/gtest.h"
diff --git a/chrome/browser/web_applications/components/app_registry_controller.h b/chrome/browser/web_applications/components/app_registry_controller.h index 045afc12..cd3b182 100644 --- a/chrome/browser/web_applications/components/app_registry_controller.h +++ b/chrome/browser/web_applications/components/app_registry_controller.h
@@ -36,6 +36,10 @@ virtual void SetAppLaunchContainer(const AppId& app_id, LaunchContainer launch_container) = 0; + virtual void SetAppIsLocallyInstalledForTesting( + const AppId& app_id, + bool is_locally_installed) = 0; + // Safe downcast: virtual WebAppSyncBridge* AsWebAppSyncBridge() = 0;
diff --git a/chrome/browser/web_applications/components/manifest_update_manager.cc b/chrome/browser/web_applications/components/manifest_update_manager.cc index e66b864..f56b65a 100644 --- a/chrome/browser/web_applications/components/manifest_update_manager.cc +++ b/chrome/browser/web_applications/components/manifest_update_manager.cc
@@ -36,7 +36,7 @@ if (!base::FeatureList::IsEnabled(features::kDesktopPWAsLocalUpdating)) return; - if (app_id.empty()) { + if (app_id.empty() || !registrar_->IsLocallyInstalled(app_id)) { NotifyResult(url, ManifestUpdateResult::kNoAppInScope); return; }
diff --git a/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc b/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc index 25d7dfd..d4473909 100644 --- a/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc +++ b/chrome/browser/web_applications/components/manifest_update_manager_browsertest.cc
@@ -14,6 +14,7 @@ #include "chrome/browser/installable/installable_metrics.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/browser_commands.h" +#include "chrome/browser/web_applications/components/app_registry_controller.h" #include "chrome/browser/web_applications/components/install_finalizer.h" #include "chrome/browser/web_applications/components/install_manager.h" #include "chrome/browser/web_applications/components/web_app_provider_base.h" @@ -138,8 +139,6 @@ GURL app_url = GetAppURL(); ui_test_utils::NavigateToURL(browser(), app_url); - auto* provider = WebAppProviderBase::GetProviderBase(browser()->profile()); - AppId app_id; base::RunLoop run_loop; InstallManager::InstallParams params; @@ -148,7 +147,7 @@ params.add_to_quick_launch_bar = false; params.bypass_service_worker_check = true; params.require_manifest = false; - provider->install_manager().InstallWebAppWithParams( + GetProvider().install_manager().InstallWebAppWithParams( browser()->tab_strip_model()->GetActiveWebContents(), params, WebappInstallSource::OMNIBOX_INSTALL_ICON, base::BindLambdaForTesting( @@ -173,6 +172,10 @@ return std::move(awaiter).AwaitNextResult(); } + WebAppProviderBase& GetProvider() { + return *WebAppProviderBase::GetProviderBase(browser()->profile()); + } + private: base::test::ScopedFeatureList scoped_feature_list_; @@ -245,9 +248,7 @@ GURL url = GetAppURL(); UpdateCheckResultAwaiter awaiter(browser(), url); ui_test_utils::NavigateToURL(browser(), url); - WebAppProviderBase::GetProviderBase(browser()->profile()) - ->install_finalizer() - .UninstallWebApp(app_id, base::DoNothing()); + GetProvider().install_finalizer().UninstallWebApp(app_id, base::DoNothing()); EXPECT_EQ(std::move(awaiter).AwaitNextResult(), ManifestUpdateResult::kAppUninstalled); } @@ -371,6 +372,30 @@ } IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest, + CheckIgnoresNonLocalApps) { + const char* manifest_template = R"( + { + "name": "Test app name", + "start_url": ".", + "scope": "/", + "display": "standalone", + "icons": $1, + "theme_color": "$2" + } + )"; + OverrideManifest(manifest_template, {kInstallableIconList, "blue"}); + AppId app_id = InstallWebApp(); + + GetProvider().registry_controller().SetAppIsLocallyInstalledForTesting(app_id, + false); + EXPECT_FALSE(GetProvider().registrar().IsLocallyInstalled(app_id)); + + OverrideManifest(manifest_template, {kInstallableIconList, "red"}); + EXPECT_EQ(GetResultAfterPageLoad(GetAppURL(), &app_id), + ManifestUpdateResult::kNoAppInScope); +} + +IN_PROC_BROWSER_TEST_F(ManifestUpdateManagerBrowserTest, CheckFindsThemeColorChange) { const char* manifest_template = R"( {
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc index 5645df4..6c6d537 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc +++ b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.cc
@@ -9,6 +9,7 @@ #include "base/one_shot_event.h" #include "chrome/browser/extensions/launch_util.h" #include "chrome/browser/profiles/profile.h" +#include "chrome/browser/web_applications/extensions/bookmark_app_util.h" #include "extensions/browser/extension_prefs.h" #include "extensions/browser/extension_registry.h" #include "extensions/browser/extension_system.h" @@ -55,6 +56,13 @@ } } +void BookmarkAppRegistryController::SetAppIsLocallyInstalledForTesting( + const web_app::AppId& app_id, + bool is_locally_installed) { + SetBookmarkAppIsLocallyInstalled(profile(), GetExtension(app_id), + is_locally_installed); +} + web_app::WebAppSyncBridge* BookmarkAppRegistryController::AsWebAppSyncBridge() { return nullptr; }
diff --git a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h index cf1dbb88..3717c59 100644 --- a/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h +++ b/chrome/browser/web_applications/extensions/bookmark_app_registry_controller.h
@@ -23,6 +23,8 @@ void SetAppLaunchContainer( const web_app::AppId& app_id, web_app::LaunchContainer launch_container) override; + void SetAppIsLocallyInstalledForTesting(const web_app::AppId& app_id, + bool is_locally_installed) override; web_app::WebAppSyncBridge* AsWebAppSyncBridge() override; private:
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc index 0859c5be..2b3de972 100644 --- a/chrome/browser/web_applications/web_app.cc +++ b/chrome/browser/web_applications/web_app.cc
@@ -30,6 +30,10 @@ return sources_.any(); } +bool WebApp::IsSynced() const { + return sources_[Source::kSync]; +} + void WebApp::SetName(const std::string& name) { name_ = name; }
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h index 59effc0f..d73ce65 100644 --- a/chrome/browser/web_applications/web_app.h +++ b/chrome/browser/web_applications/web_app.h
@@ -49,6 +49,8 @@ void RemoveSource(Source::Type source); bool HasAnySources() const; + bool IsSynced() const; + void SetName(const std::string& name); void SetDescription(const std::string& description); void SetLaunchUrl(const GURL& launch_url);
diff --git a/chrome/browser/web_applications/web_app_database.cc b/chrome/browser/web_applications/web_app_database.cc index 9156bb4..bba54f5 100644 --- a/chrome/browser/web_applications/web_app_database.cc +++ b/chrome/browser/web_applications/web_app_database.cc
@@ -12,13 +12,16 @@ #include "chrome/browser/web_applications/web_app_database_factory.h" #include "chrome/browser/web_applications/web_app_registry_update.h" #include "components/sync/base/model_type.h" +#include "components/sync/model/metadata_batch.h" #include "components/sync/model/model_error.h" #include "components/sync/protocol/web_app_specifics.pb.h" namespace web_app { -WebAppDatabase::WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory) - : database_factory_(database_factory) { +WebAppDatabase::WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory, + ReportErrorCallback error_callback) + : database_factory_(database_factory), + error_callback_(std::move(error_callback)) { DCHECK(database_factory_); } @@ -232,11 +235,14 @@ std::unique_ptr<syncer::ModelTypeStore> store) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (error) { + error_callback_.Run(*error); DLOG(ERROR) << "WebApps LevelDB opening error: " << error->ToString(); return; } store_ = std::move(store); + // TODO(loyso): Use ReadAllDataAndPreprocess to parse protos in the background + // sequence. store_->ReadAllData(base::BindOnce(&WebAppDatabase::OnAllDataRead, weak_ptr_factory_.GetWeakPtr(), std::move(callback))); @@ -248,7 +254,25 @@ std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); if (error) { - DLOG(ERROR) << "WebApps LevelDB read error: " << error->ToString(); + error_callback_.Run(*error); + DLOG(ERROR) << "WebApps LevelDB data read error: " << error->ToString(); + return; + } + + store_->ReadAllMetadata(base::BindOnce( + &WebAppDatabase::OnAllMetadataRead, weak_ptr_factory_.GetWeakPtr(), + std::move(data_records), std::move(callback))); +} + +void WebAppDatabase::OnAllMetadataRead( + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records, + RegistryOpenedCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (error) { + error_callback_.Run(*error); + DLOG(ERROR) << "WebApps LevelDB metadata read error: " << error->ToString(); return; } @@ -260,7 +284,7 @@ registry.emplace(app_id, std::move(web_app)); } - std::move(callback).Run(std::move(registry)); + std::move(callback).Run(std::move(registry), std::move(metadata_batch)); opened_ = true; } @@ -268,8 +292,10 @@ CompletionCallback callback, const base::Optional<syncer::ModelError>& error) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); - if (error) + if (error) { + error_callback_.Run(*error); DLOG(ERROR) << "WebApps LevelDB write error: " << error->ToString(); + } std::move(callback).Run(!error); }
diff --git a/chrome/browser/web_applications/web_app_database.h b/chrome/browser/web_applications/web_app_database.h index 881cd7c2..bca34a5 100644 --- a/chrome/browser/web_applications/web_app_database.h +++ b/chrome/browser/web_applications/web_app_database.h
@@ -18,6 +18,7 @@ namespace syncer { class ModelError; +class MetadataBatch; } // namespace syncer namespace web_app { @@ -30,10 +31,16 @@ // Exclusively used from the UI thread. class WebAppDatabase { public: - explicit WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory); + using ReportErrorCallback = + base::RepeatingCallback<void(const syncer::ModelError&)>; + + WebAppDatabase(AbstractWebAppDatabaseFactory* database_factory, + ReportErrorCallback error_callback); ~WebAppDatabase(); - using RegistryOpenedCallback = base::OnceCallback<void(Registry registry)>; + using RegistryOpenedCallback = base::OnceCallback<void( + Registry registry, + std::unique_ptr<syncer::MetadataBatch> metadata_batch)>; // Open existing or create new DB. Read all data and return it via callback. void OpenDatabase(RegistryOpenedCallback callback); @@ -61,6 +68,11 @@ RegistryOpenedCallback callback, const base::Optional<syncer::ModelError>& error, std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records); + void OnAllMetadataRead( + std::unique_ptr<syncer::ModelTypeStore::RecordList> data_records, + RegistryOpenedCallback callback, + const base::Optional<syncer::ModelError>& error, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); void OnDataWritten(CompletionCallback callback, const base::Optional<syncer::ModelError>& error); @@ -68,6 +80,7 @@ std::unique_ptr<syncer::ModelTypeStore> store_; std::unique_ptr<syncer::ModelTypeStore::WriteBatch> write_batch_; AbstractWebAppDatabaseFactory* database_factory_; + ReportErrorCallback error_callback_; // Database is opened if store is created and all data read. bool opened_ = false;
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.cc b/chrome/browser/web_applications/web_app_sync_bridge.cc index be0010a..07b52fd 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge.cc +++ b/chrome/browser/web_applications/web_app_sync_bridge.cc
@@ -4,23 +4,54 @@ #include "chrome/browser/web_applications/web_app_sync_bridge.h" +#include <memory> + #include "base/bind.h" #include "base/bind_helpers.h" #include "base/callback.h" #include "base/logging.h" #include "base/optional.h" -#include "chrome/browser/web_applications/web_app.h" +#include "chrome/browser/web_applications/components/web_app_constants.h" +#include "chrome/browser/web_applications/components/web_app_helpers.h" #include "chrome/browser/web_applications/web_app_database.h" #include "chrome/browser/web_applications/web_app_database_factory.h" #include "chrome/browser/web_applications/web_app_registry_update.h" #include "chrome/common/channel_info.h" #include "components/sync/base/model_type.h" #include "components/sync/base/report_unrecoverable_error.h" +#include "components/sync/model/entity_data.h" +#include "components/sync/model/metadata_batch.h" #include "components/sync/model/metadata_change_list.h" +#include "components/sync/model/model_type_store.h" +#include "components/sync/model/mutable_data_batch.h" #include "components/sync/model_impl/client_tag_based_model_type_processor.h" +#include "components/sync/protocol/web_app_specifics.pb.h" +#include "url/gurl.h" namespace web_app { +namespace { + +std::unique_ptr<syncer::EntityData> CreateSyncEntityData(const WebApp& app) { + auto entity_data = std::make_unique<syncer::EntityData>(); + entity_data->name = app.name(); + + sync_pb::WebAppSpecifics* specifics = + entity_data->specifics.mutable_web_app(); + specifics->set_launch_url(app.launch_url().spec()); + specifics->set_name(app.name()); + specifics->set_launch_container(app.launch_container() == + LaunchContainer::kWindow + ? sync_pb::WebAppSpecifics::WINDOW + : sync_pb::WebAppSpecifics::TAB); + if (app.theme_color().has_value()) + specifics->set_theme_color(app.theme_color().value()); + + return entity_data; +} + +} // namespace + WebAppSyncBridge::WebAppSyncBridge( Profile* profile, AbstractWebAppDatabaseFactory* database_factory, @@ -44,7 +75,10 @@ registrar_(registrar) { DCHECK(database_factory); DCHECK(registrar_); - database_ = std::make_unique<WebAppDatabase>(database_factory); + database_ = std::make_unique<WebAppDatabase>( + database_factory, + base::BindRepeating(&WebAppSyncBridge::ReportErrorToChangeProcessor, + base::Unretained(this))); } WebAppSyncBridge::~WebAppSyncBridge() = default; @@ -98,6 +132,15 @@ web_app->SetLaunchContainer(launch_container); } +void WebAppSyncBridge::SetAppIsLocallyInstalledForTesting( + const AppId& app_id, + bool is_locally_installed) { + ScopedRegistryUpdate update(this); + WebApp* web_app = update->UpdateApp(app_id); + if (web_app) + web_app->SetIsLocallyInstalled(is_locally_installed); +} + WebAppSyncBridge* WebAppSyncBridge::AsWebAppSyncBridge() { return this; } @@ -131,8 +174,13 @@ } } -void WebAppSyncBridge::OnDatabaseOpened(base::OnceClosure callback, - Registry registry) { +void WebAppSyncBridge::OnDatabaseOpened( + base::OnceClosure callback, + Registry registry, + std::unique_ptr<syncer::MetadataBatch> metadata_batch) { + // Provide sync metadata to the processor _before_ any local changes occur. + change_processor()->ModelReadyToSync(std::move(metadata_batch)); + registrar_->InitRegistry(std::move(registry)); std::move(callback).Run(); } @@ -144,10 +192,14 @@ std::move(callback).Run(success); } +void WebAppSyncBridge::ReportErrorToChangeProcessor( + const syncer::ModelError& error) { + change_processor()->ReportError(error); +} + std::unique_ptr<syncer::MetadataChangeList> WebAppSyncBridge::CreateMetadataChangeList() { - NOTIMPLEMENTED(); - return nullptr; + return syncer::ModelTypeStore::WriteBatch::CreateMetadataChangeList(); } base::Optional<syncer::ModelError> WebAppSyncBridge::MergeSyncData( @@ -166,23 +218,42 @@ void WebAppSyncBridge::GetData(StorageKeyList storage_keys, DataCallback callback) { - NOTIMPLEMENTED(); + auto data_batch = std::make_unique<syncer::MutableDataBatch>(); + + for (const AppId& app_id : storage_keys) { + const WebApp* app = registrar_->GetAppById(app_id); + if (app && app->IsSynced()) + data_batch->Put(app->app_id(), CreateSyncEntityData(*app)); + } + + std::move(callback).Run(std::move(data_batch)); } void WebAppSyncBridge::GetAllDataForDebugging(DataCallback callback) { - NOTIMPLEMENTED(); + auto data_batch = std::make_unique<syncer::MutableDataBatch>(); + + for (const WebApp& app : registrar_->AllApps()) { + if (app.IsSynced()) + data_batch->Put(app.app_id(), CreateSyncEntityData(app)); + } + + std::move(callback).Run(std::move(data_batch)); } std::string WebAppSyncBridge::GetClientTag( const syncer::EntityData& entity_data) { - NOTIMPLEMENTED(); - return std::string(); + DCHECK(entity_data.specifics.has_web_app()); + + const GURL launch_url(entity_data.specifics.web_app().launch_url()); + DCHECK(!launch_url.is_empty()); + DCHECK(launch_url.is_valid()); + + return GenerateAppIdFromURL(launch_url); } std::string WebAppSyncBridge::GetStorageKey( const syncer::EntityData& entity_data) { - NOTIMPLEMENTED(); - return std::string(); + return GetClientTag(entity_data); } } // namespace web_app
diff --git a/chrome/browser/web_applications/web_app_sync_bridge.h b/chrome/browser/web_applications/web_app_sync_bridge.h index ec4d60b..fda2308 100644 --- a/chrome/browser/web_applications/web_app_sync_bridge.h +++ b/chrome/browser/web_applications/web_app_sync_bridge.h
@@ -19,8 +19,10 @@ class Profile; namespace syncer { +class MetadataBatch; +class ModelError; class ModelTypeChangeProcessor; -} +} // namespace syncer namespace web_app { @@ -56,6 +58,8 @@ void Init(base::OnceClosure callback) override; void SetAppLaunchContainer(const AppId& app_id, LaunchContainer launch_container) override; + void SetAppIsLocallyInstalledForTesting(const AppId& app_id, + bool is_locally_installed) override; WebAppSyncBridge* AsWebAppSyncBridge() override; private: @@ -63,9 +67,13 @@ // Update the in-memory model. void UpdateRegistrar(std::unique_ptr<RegistryUpdateData> update_data); - void OnDatabaseOpened(base::OnceClosure callback, Registry registry); + void OnDatabaseOpened(base::OnceClosure callback, + Registry registry, + std::unique_ptr<syncer::MetadataBatch> metadata_batch); void OnDataWritten(CommitCallback callback, bool success); + void ReportErrorToChangeProcessor(const syncer::ModelError& error); + // syncer::ModelTypeSyncBridge: std::unique_ptr<syncer::MetadataChangeList> CreateMetadataChangeList() override;
diff --git a/chrome/common/chrome_features.cc b/chrome/common/chrome_features.cc index 1de6029..0797391 100644 --- a/chrome/common/chrome_features.cc +++ b/chrome/common/chrome_features.cc
@@ -249,8 +249,8 @@ // Enables local PWA installs to update their app manifest data if the site // changes its manifest. -const base::Feature kDesktopPWAsLocalUpdating{ - "DesktopPWAsLocalUpdating", base::FEATURE_DISABLED_BY_DEFAULT}; +const base::Feature kDesktopPWAsLocalUpdating{"DesktopPWAsLocalUpdating", + base::FEATURE_ENABLED_BY_DEFAULT}; // Enables or disables use of new Desktop PWAs browser controller (that uses the // universal web_app::AppRegistrar) by extensions-based bookmark apps. Note that
diff --git a/chrome/common/extensions/api/file_manager_private.idl b/chrome/common/extensions/api/file_manager_private.idl index b7835d7..a83fb65c 100644 --- a/chrome/common/extensions/api/file_manager_private.idl +++ b/chrome/common/extensions/api/file_manager_private.idl
@@ -726,8 +726,6 @@ // |sourcePath| Source path of the mount. callback AddMountCallback = void(DOMString sourcePath); -callback MarkCacheAsMountedCallback = void(); - // |volumeMetadataList| The list of VolumeMetadata representing mounted volumes. callback GetVolumeMetadataListCallback = void(VolumeMetadata[] volumeMetadataList); @@ -956,16 +954,6 @@ // |volumeId| An ID of the volume. static void removeMount(DOMString volumeId); - // Marks a cache file of Drive as mounted or unmounted. - // Does nothing if the file is not under Drive directory. - // |sourcePath| Mounted source file. Relative file path within external file - // system. - // |isMounted| Mark as mounted if true. Mark as unmounted otherwise. - // |callback| Completion callback. $(ref:runtime.lastError) will be set if - // there was an error. - static void markCacheAsMounted(DOMString sourcePath, boolean isMounted, - MarkCacheAsMountedCallback callback); - // Get the list of mounted volumes. // |callback| static void getVolumeMetadataList(GetVolumeMetadataListCallback callback);
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 564c7c7a..8a6c99e 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn
@@ -3665,7 +3665,6 @@ # !is_android sources += [ # Badging isn't supported on Android. - "../browser/badging/badge_manager_delegate_unittest.cc", "../browser/badging/badge_manager_unittest.cc", "../browser/badging/test_badge_manager_delegate.cc", "../browser/badging/test_badge_manager_delegate.h",
diff --git a/chrome/test/data/password/filled_simple_signup_form.html b/chrome/test/data/password/filled_simple_signup_form.html new file mode 100644 index 0000000..9eb3097 --- /dev/null +++ b/chrome/test/data/password/filled_simple_signup_form.html
@@ -0,0 +1,27 @@ +<!-- + A mock signup form. Essentially the same as filled_simple_password_form.html, + but includes an additional text field which will cause it to be treated differently. + --> +<html> +<head> + <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0"/> +</head> +<body> +<!-- This form should trigger automatic generation --> +<form method="POST" action="done.html"> + <input type="text" id="other_info" name="other_info" value="info"> + <input type="text" id="username_field" name="username_field" value="username" autocomplete="username"> + <input type="password" id="password_field" name="password_field" autocomplete="new-password"> + <input type="submit" id="input_submit_button" name="input_submit_button"> +</form> +<!-- + This form is used to test manual generation and ideally shouldn't trigger automatic generation. +--> +<form method="POST" action="done.html"> + <input type="text" id="other_info_manual" name="other_info_manual" value="info"> + <input type="text" id="username_field_manual" name="username_field_manual" value="username"> + <input type="password" id="password_field_manual" name="password_field_manual"> + <input type="submit" id="input_submit_button_manual" name="input_submit_button_manual"> +</form> +</body> +</html>
diff --git a/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.js b/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.js index 40373b7..a6412a0 100644 --- a/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.js +++ b/chrome/test/data/webui/cr_elements/cr_searchable_drop_down_tests.js
@@ -274,9 +274,9 @@ }); // The show-loading attribute should determine whether or not the loading - // progress bar is shown. - test('progress bar is shown and hidden', function() { - const progress = dropDown.$.loading; + // spinner and message are shown. + test('loading spinner is shown and hidden', function() { + const progress = dropDown.shadowRoot.querySelector('#loading-box'); assertTrue(progress.hidden); dropDown.showLoading = true;
diff --git a/chrome/test/data/webui/print_preview/custom_margins_test.js b/chrome/test/data/webui/print_preview/custom_margins_test.js index 3782fe3..671e7560 100644 --- a/chrome/test/data/webui/print_preview/custom_margins_test.js +++ b/chrome/test/data/webui/print_preview/custom_margins_test.js
@@ -231,8 +231,7 @@ const marginValues = setupCustomMargins(); return finishSetup().then(() => { // Simulate setting custom margins. - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); // Validate control positions are set based on the custom values. const controls = getControls(); @@ -249,7 +248,7 @@ // Margins should be reset to default and custom margins values should // be cleared. expectEquals( - print_preview.MarginsTypeValue.DEFAULT, + print_preview.MarginsType.DEFAULT, container.getSettingValue('margins')); expectEquals( '{}', JSON.stringify(container.getSettingValue('customMargins'))); @@ -279,8 +278,7 @@ let onTransitionEnd = getAllTransitions(controls); // Controls become visible when margin type CUSTOM is selected. model.set( - 'settings.margins.value', - print_preview.MarginsTypeValue.CUSTOM); + 'settings.margins.value', print_preview.MarginsType.CUSTOM); // Wait for the opacity transitions to finish. return onTransitionEnd; @@ -336,8 +334,7 @@ const controls = getControls(); // Simulate setting custom margins from sticky settings. - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); const marginValues = setupCustomMargins(); model.notifyPath('settings.customMargins.value'); Polymer.dom.flush(); @@ -382,8 +379,7 @@ return finishSetup().then(() => { const controls = getControls(); - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); Polymer.dom.flush(); @@ -441,8 +437,7 @@ controls.forEach(c => { c.getInput().setAttribute('data-timeout-delay', 1); }); - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); Polymer.dom.flush(); // Verify entering a new value updates the settings. @@ -487,8 +482,7 @@ controls.forEach(c => { c.getInput().setAttribute('data-timeout-delay', 1); }); - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); Polymer.dom.flush(); // Verify entering a new value updates the settings. @@ -538,8 +532,7 @@ return finishSetup().then(() => { // Simulate setting custom margins. const controls = getControls(); - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); // Validate control positions are set based on the custom values. controls.forEach((control, index) => { @@ -549,8 +542,7 @@ }); // Simulate setting minimum margins. - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.MINIMUM); + model.set('settings.margins.value', print_preview.MarginsType.MINIMUM); // Validate control positions still reflect the custom values. controls.forEach((control, index) => { @@ -568,8 +560,7 @@ .then(() => { // Simulate setting custom margins again. model.set( - 'settings.margins.value', - print_preview.MarginsTypeValue.CUSTOM); + 'settings.margins.value', print_preview.MarginsType.CUSTOM); // Validate control positions are initialized based on the default // values. @@ -586,8 +577,7 @@ test(assert(TestNames.LayoutClearsCustomMargins), function() { return validateMarginsClearedForSetting('layout', true).then(() => { // Simulate setting custom margins again - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); // Validate control positions are initialized based on the default // values. @@ -637,8 +627,7 @@ // Controls become visible when margin type CUSTOM is selected. model.set( - 'settings.margins.value', - print_preview.MarginsTypeValue.CUSTOM); + 'settings.margins.value', print_preview.MarginsType.CUSTOM); container.notifyPath('settings.customMargins.value'); Polymer.dom.flush(); return onTransitionEnd; @@ -683,8 +672,7 @@ test(assert(TestNames.ControlsDisabledOnError), function() { return finishSetup().then(() => { // Simulate setting custom margins. - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); const controls = getControls(); controls.forEach(control => assertFalse(control.disabled));
diff --git a/chrome/test/data/webui/print_preview/margins_settings_test.js b/chrome/test/data/webui/print_preview/margins_settings_test.js index 4b63882..e55b1ca 100644 --- a/chrome/test/data/webui/print_preview/margins_settings_test.js +++ b/chrome/test/data/webui/print_preview/margins_settings_test.js
@@ -19,7 +19,7 @@ marginsSection.settings = model.settings; marginsSection.disabled = false; test_util.fakeDataBind(model, marginsSection, 'settings'); - marginsTypeEnum = print_preview.MarginsTypeValue; + marginsTypeEnum = print_preview.MarginsType; }); // Tests that setting the setting updates the UI.
diff --git a/chrome/test/data/webui/print_preview/model_settings_availability_test.js b/chrome/test/data/webui/print_preview/model_settings_availability_test.js index dd28b14..d9ff578e 100644 --- a/chrome/test/data/webui/print_preview/model_settings_availability_test.js +++ b/chrome/test/data/webui/print_preview/model_settings_availability_test.js
@@ -375,13 +375,11 @@ assertTrue(model.settings.headerFooter.available); // Set margins to NONE - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.NO_MARGINS); + model.set('settings.margins.value', print_preview.MarginsType.NO_MARGINS); assertFalse(model.settings.headerFooter.available); // Custom margins of 0. - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.CUSTOM); + model.set('settings.margins.value', print_preview.MarginsType.CUSTOM); model.set( 'settings.customMargins.value', {marginTop: 0, marginLeft: 0, marginRight: 0, marginBottom: 0}); @@ -426,8 +424,7 @@ ] }; model.set('destination.capabilities', capabilities); - model.set( - 'settings.margins.value', print_preview.MarginsTypeValue.DEFAULT); + model.set('settings.margins.value', print_preview.MarginsType.DEFAULT); // Header/footer should be available for default big label with // default margins.
diff --git a/chrome/test/data/webui/print_preview/model_test.js b/chrome/test/data/webui/print_preview/model_test.js index 63773b1..fd5ebbf8 100644 --- a/chrome/test/data/webui/print_preview/model_test.js +++ b/chrome/test/data/webui/print_preview/model_test.js
@@ -188,7 +188,7 @@ layout: true, color: false, mediaSize: testDestination.capabilities.printer.media_size.option[1], - margins: print_preview.MarginsTypeValue.CUSTOM, + margins: print_preview.MarginsType.CUSTOM, customMargins: { marginTop: 100, marginRight: 200, @@ -278,7 +278,7 @@ landscape: false, color: testDestination.getNativeColorModel(true), headerFooterEnabled: false, // Only used in print preview - marginsType: print_preview.MarginsTypeValue.DEFAULT, + marginsType: print_preview.MarginsType.DEFAULT, duplex: print_preview.DuplexMode.SIMPLEX, copies: 1, collate: true, @@ -319,7 +319,7 @@ landscape: true, color: testDestination.getNativeColorModel(false), headerFooterEnabled: false, - marginsType: print_preview.MarginsTypeValue.CUSTOM, + marginsType: print_preview.MarginsType.CUSTOM, duplex: print_preview.DuplexMode.SHORT_EDGE, copies: 2, collate: false,
diff --git a/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js b/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js index 26e62d42..7b5a972 100644 --- a/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js +++ b/chrome/test/data/webui/print_preview/pages_per_sheet_settings_test.js
@@ -34,14 +34,14 @@ // Tests that setting the pages per sheet setting resets margins to DEFAULT. test('resets margins setting', async () => { pagesPerSheetSection.setSetting( - 'margins', print_preview.MarginsTypeValue.NO_MARGINS); + 'margins', print_preview.MarginsType.NO_MARGINS); assertEquals(1, pagesPerSheetSection.getSettingValue('pagesPerSheet')); pagesPerSheetSection.setSetting('pagesPerSheet', 4); await test_util.eventToPromise( 'process-select-change', pagesPerSheetSection); assertEquals(4, pagesPerSheetSection.getSettingValue('pagesPerSheet')); assertEquals( - print_preview.MarginsTypeValue.DEFAULT, + print_preview.MarginsType.DEFAULT, pagesPerSheetSection.getSettingValue('margins')); });
diff --git a/chrome/test/data/webui/print_preview/preview_generation_test.js b/chrome/test/data/webui/print_preview/preview_generation_test.js index 8d6d57b..b34cee46 100644 --- a/chrome/test/data/webui/print_preview/preview_generation_test.js +++ b/chrome/test/data/webui/print_preview/preview_generation_test.js
@@ -151,10 +151,9 @@ /** Validate changing the margins updates the preview. */ test(assert(TestNames.Margins), function() { return testSimpleSetting( - 'margins', print_preview.MarginsTypeValue.DEFAULT, - print_preview.MarginsTypeValue.MINIMUM, 'marginsType', - print_preview.MarginsTypeValue.DEFAULT, - print_preview.MarginsTypeValue.MINIMUM); + 'margins', print_preview.MarginsType.DEFAULT, + print_preview.MarginsType.MINIMUM, 'marginsType', + print_preview.MarginsType.DEFAULT, print_preview.MarginsType.MINIMUM); }); /** @@ -166,14 +165,13 @@ .then(function(args) { const originalTicket = JSON.parse(args.printTicket); assertEquals( - print_preview.MarginsTypeValue.DEFAULT, - originalTicket.marginsType); + print_preview.MarginsType.DEFAULT, originalTicket.marginsType); // Custom margins should not be set in the ticket. assertEquals(undefined, originalTicket.marginsCustom); assertEquals(0, originalTicket.requestID); // This should do nothing. - page.setSetting('margins', print_preview.MarginsTypeValue.CUSTOM); + page.setSetting('margins', print_preview.MarginsType.CUSTOM); // Sets only 1 side, not valid. page.setSetting('customMargins', {marginTop: 25}); // 2 sides, still not valid. @@ -190,17 +188,16 @@ }) .then(function(args) { const ticket = JSON.parse(args.printTicket); - assertEquals( - print_preview.MarginsTypeValue.CUSTOM, ticket.marginsType); + assertEquals(print_preview.MarginsType.CUSTOM, ticket.marginsType); assertEquals(25, ticket.marginsCustom.marginTop); assertEquals(40, ticket.marginsCustom.marginRight); assertEquals(20, ticket.marginsCustom.marginBottom); assertEquals(50, ticket.marginsCustom.marginLeft); assertEquals(1, ticket.requestID); - page.setSetting('margins', print_preview.MarginsTypeValue.DEFAULT); + page.setSetting('margins', print_preview.MarginsType.DEFAULT); // Set setting to something invalid and then set margins to CUSTOM. page.setSetting('customMargins', {marginTop: 25, marginRight: 40}); - page.setSetting('margins', print_preview.MarginsTypeValue.CUSTOM); + page.setSetting('margins', print_preview.MarginsType.CUSTOM); nativeLayer.resetResolver('getPreview'); page.setSetting('customMargins', { marginTop: 25, @@ -212,8 +209,7 @@ }) .then(function(args) { const ticket = JSON.parse(args.printTicket); - assertEquals( - print_preview.MarginsTypeValue.CUSTOM, ticket.marginsType); + assertEquals(print_preview.MarginsType.CUSTOM, ticket.marginsType); assertEquals(25, ticket.marginsCustom.marginTop); assertEquals(40, ticket.marginsCustom.marginRight); assertEquals(20, ticket.marginsCustom.marginBottom); @@ -227,10 +223,10 @@ /** * Validate changing the pages per sheet updates the preview, and resets - * margins to print_preview.MarginsTypeValue.DEFAULT. + * margins to print_preview.MarginsType.DEFAULT. */ test(assert(TestNames.ChangeMarginsByPagesPerSheet), function() { - const MarginsTypeEnum = print_preview.MarginsTypeValue; + const MarginsTypeEnum = print_preview.MarginsType; return initialize() .then(function(args) { const originalTicket = JSON.parse(args.printTicket); @@ -466,7 +462,7 @@ /** * @param {Object} ticket The parsed print ticket * @param {number} expectedId The expected ticket request ID - * @param {!print_preview.MarginsTypeValue} expectedMargins + * @param {!print_preview.MarginsType} expectedMargins * The expected ticket margins type * @param {boolean} expectedHeaderFooter The expected ticket * header/footer value @@ -491,7 +487,7 @@ printableAreaHeight: 792, }); - const MarginsTypeEnum = print_preview.MarginsTypeValue; + const MarginsTypeEnum = print_preview.MarginsType; let previewArgs = await initialize(); let ticket = JSON.parse(previewArgs.printTicket);
diff --git a/chrome/test/data/webui/print_preview/restore_state_test.js b/chrome/test/data/webui/print_preview/restore_state_test.js index 6435f5e55..649383a 100644 --- a/chrome/test/data/webui/print_preview/restore_state_test.js +++ b/chrome/test/data/webui/print_preview/restore_state_test.js
@@ -219,7 +219,7 @@ section: 'print-preview-margins-settings', settingName: 'margins', key: 'marginsType', - value: print_preview.MarginsTypeValue.MINIMUM, + value: print_preview.MarginsType.MINIMUM, }, { section: 'print-preview-dpi-settings',
diff --git a/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js b/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js index 6cb1518..62e99d1 100644 --- a/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js +++ b/chrome/test/data/webui/settings/chromeos/app_management/reducers_test.js
@@ -128,138 +128,4 @@ assertEquals(null, state.currentPage.selectedAppId); assertEquals(PageType.MAIN, state.currentPage.pageType); }); - - test('current page updates when changing to notifications page', function() { - const action = app_management.actions.changePage(PageType.NOTIFICATIONS); - state = app_management.reduceAction(state, action); - - assertEquals(PageType.NOTIFICATIONS, state.currentPage.pageType); - }); -}); - -suite('notifications state', function() { - let state; - - function createAppWithNotifications(id, allowed) { - const permissionValue = allowed ? TriState.kAllow : TriState.kBlock; - const notificationsPermissionType = - PwaPermissionType.CONTENT_SETTINGS_TYPE_NOTIFICATIONS; - - const notificationsPermission = app_management.util.createPermission( - notificationsPermissionType, PermissionValueType.kTriState, - permissionValue); - - const permissions = {}; - permissions[notificationsPermissionType] = notificationsPermission; - return createApp(id, {permissions: permissions}); - } - - setup(function() { - state = app_management.util.createInitialState([ - createAppWithNotifications('1', false), - createAppWithNotifications('2', true), - ]); - }); - - test('notifications state updates when an app is added', function() { - // Check that the sets are initialised correctly. - let {allowedIds, blockedIds} = state.notifications; - - assertEquals(1, allowedIds.size); - assertTrue(allowedIds.has('2')); - - assertEquals(1, blockedIds.size); - assertTrue(blockedIds.has('1')); - - // Add an app and update the sets. - let newApp = createAppWithNotifications('3', true); - let action = app_management.actions.addApp(newApp); - let {allowedIds: newAllowedIds, blockedIds: newBlockedIds} = - app_management.NotificationsState.updateNotifications( - {allowedIds, blockedIds}, action); - - // Check that the new id was added to the allowed set, and its reference - // has changed. - assertEquals(2, newAllowedIds.size); - assertTrue(newAllowedIds.has('3')); - assertNotEquals(newAllowedIds, allowedIds); - - // Check that the blocked set hasn't changed, and that its reference is - // the same. - assertEquals(1, newBlockedIds.size); - assertEquals(newBlockedIds, blockedIds); - - // If the added doesn't have a notifications permission, the sets don't - // change. - allowedIds = newAllowedIds; - blockedIds = newBlockedIds; - - newApp = createApp('4', {type: AppType.kUnknown, permissions: {}}); - action = app_management.actions.addApp(newApp); - ({allowedIds: newAllowedIds, blockedIds: newBlockedIds} = - app_management.NotificationsState.updateNotifications( - {allowedIds, blockedIds}, action)); - - assertEquals(2, newAllowedIds.size); - assertEquals(newAllowedIds, allowedIds); - - assertEquals(1, newBlockedIds.size); - assertEquals(newBlockedIds, blockedIds); - }); - - test('notifications state updates when an app is changed', function() { - // If the change doesn't affect the notifications permission, the sets - // are unchanged and still have the same references. - let {allowedIds, blockedIds} = state.notifications; - - let changedApp = createAppWithNotifications('2', true); - changedApp.title = 'New App Title'; - let action = app_management.actions.changeApp(changedApp); - let {allowedIds: newAllowedIds, blockedIds: newBlockedIds} = - app_management.NotificationsState.updateNotifications( - {allowedIds, blockedIds}, action); - - assertEquals(1, newAllowedIds.size); - assertTrue(newAllowedIds.has('2')); - assertEquals(newAllowedIds, allowedIds); - - assertEquals(1, newBlockedIds.size); - assertTrue(newBlockedIds.has('1')); - assertEquals(newBlockedIds, blockedIds); - - // If the notifications permission value of an app is changed, the sets - // update correctly. - blockedIds = newBlockedIds; - allowedIds = newAllowedIds; - - changedApp = createAppWithNotifications('1', true); - action = app_management.actions.changeApp(changedApp); - ({allowedIds: newAllowedIds, blockedIds: newBlockedIds} = - app_management.NotificationsState.updateNotifications( - {allowedIds, blockedIds}, action)); - - assertEquals(2, newAllowedIds.size); - assertTrue(newAllowedIds.has('1')); - assertNotEquals(newAllowedIds, allowedIds); - - assertEquals(0, newBlockedIds.size); - assertNotEquals(newBlockedIds, blockedIds); - }); - - test('notifications state updates when an app is removed', function() { - // When an app is removed, the sets update correctly. - const {allowedIds, blockedIds} = state.notifications; - - const action = app_management.actions.removeApp('1'); - const {allowedIds: newAllowedIds, blockedIds: newBlockedIds} = - app_management.NotificationsState.updateNotifications( - {allowedIds, blockedIds}, action); - - assertEquals(1, newAllowedIds.size); - assertTrue(newAllowedIds.has('2')); - assertEquals(newAllowedIds, allowedIds); - - assertEquals(0, newBlockedIds.size); - assertNotEquals(newBlockedIds, blockedIds); - }); });
diff --git a/chromeos/dbus/BUILD.gn b/chromeos/dbus/BUILD.gn index bc4097f..95d22b7 100644 --- a/chromeos/dbus/BUILD.gn +++ b/chromeos/dbus/BUILD.gn
@@ -18,6 +18,7 @@ public_deps = [ ":common", "//chromeos/dbus/constants", + "//chromeos/dbus/debug_daemon", "//chromeos/dbus/shill", "//dbus", ] @@ -61,14 +62,11 @@ "concierge_client.h", "cros_disks_client.cc", "cros_disks_client.h", - "dbus_client.h", "dbus_client_implementation_type.h", "dbus_clients_browser.cc", "dbus_clients_browser.h", "dbus_thread_manager.cc", "dbus_thread_manager.h", - "debug_daemon_client.cc", - "debug_daemon_client.h", "easy_unlock_client.cc", "easy_unlock_client.h", "fake_arc_appfuse_provider_client.cc", @@ -91,8 +89,6 @@ "fake_concierge_client.h", "fake_cros_disks_client.cc", "fake_cros_disks_client.h", - "fake_debug_daemon_client.cc", - "fake_debug_daemon_client.h", "fake_easy_unlock_client.cc", "fake_easy_unlock_client.h", "fake_gnubby_client.cc", @@ -177,6 +173,7 @@ sources = [ "blocking_method_caller.cc", "blocking_method_caller.h", + "dbus_client.h", "dbus_method_call_status.cc", "dbus_method_call_status.h", "initialize_dbus_client.h",
diff --git a/chromeos/dbus/dbus_clients_browser.cc b/chromeos/dbus/dbus_clients_browser.cc index a563468..f6c3bc4 100644 --- a/chromeos/dbus/dbus_clients_browser.cc +++ b/chromeos/dbus/dbus_clients_browser.cc
@@ -16,7 +16,8 @@ #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/dbus_client_implementation_type.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/dbus/fake_arc_appfuse_provider_client.h" #include "chromeos/dbus/fake_arc_keymaster_client.h" @@ -27,7 +28,6 @@ #include "chromeos/dbus/fake_cicerone_client.h" #include "chromeos/dbus/fake_concierge_client.h" #include "chromeos/dbus/fake_cros_disks_client.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" #include "chromeos/dbus/fake_easy_unlock_client.h" #include "chromeos/dbus/fake_gnubby_client.h" #include "chromeos/dbus/fake_image_burner_client.h"
diff --git a/chromeos/dbus/dbus_thread_manager.cc b/chromeos/dbus/dbus_thread_manager.cc index aefd933..b47d7b0 100644 --- a/chromeos/dbus/dbus_thread_manager.cc +++ b/chromeos/dbus/dbus_thread_manager.cc
@@ -22,7 +22,7 @@ #include "chromeos/dbus/cros_disks_client.h" #include "chromeos/dbus/dbus_client.h" #include "chromeos/dbus/dbus_clients_browser.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/easy_unlock_client.h" #include "chromeos/dbus/gnubby_client.h" #include "chromeos/dbus/image_burner_client.h"
diff --git a/chromeos/dbus/debug_daemon/BUILD.gn b/chromeos/dbus/debug_daemon/BUILD.gn new file mode 100644 index 0000000..a8b94d8 --- /dev/null +++ b/chromeos/dbus/debug_daemon/BUILD.gn
@@ -0,0 +1,24 @@ +# Copyright 2019 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. + +assert(is_chromeos, "Non-ChromeOS builds cannot depend on //chromeos") + +component("debug_daemon") { + defines = [ "IS_DEBUG_DAEMON_IMPL" ] + + deps = [ + "//base", + "//chromeos/dbus:common", + "//dbus", + ] + + sources = [ + "debug_daemon_client.cc", + "debug_daemon_client.h", + "debug_daemon_client_provider.cc", + "debug_daemon_client_provider.h", + "fake_debug_daemon_client.cc", + "fake_debug_daemon_client.h", + ] +}
diff --git a/chromeos/dbus/debug_daemon_client.cc b/chromeos/dbus/debug_daemon/debug_daemon_client.cc similarity index 96% rename from chromeos/dbus/debug_daemon_client.cc rename to chromeos/dbus/debug_daemon/debug_daemon_client.cc index 5905a5dd..c86e445 100644 --- a/chromeos/dbus/debug_daemon_client.cc +++ b/chromeos/dbus/debug_daemon/debug_daemon_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include <dbus/dbus-protocol.h> #include <fcntl.h> @@ -163,8 +163,7 @@ bool numeric, bool ipv6, DBusMethodCallback<std::vector<std::string>> callback) override { - dbus::MethodCall method_call(debugd::kDebugdInterface, - debugd::kGetRoutes); + dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kGetRoutes); dbus::MessageWriter writer(&method_call); dbus::MessageWriter sub_writer(NULL); writer.OpenArray("{sv}", &sub_writer); @@ -255,8 +254,7 @@ } void GetAllLogs(GetLogsCallback callback) override { - dbus::MethodCall method_call(debugd::kDebugdInterface, - debugd::kGetAllLogs); + dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kGetAllLogs); debugdaemon_proxy_->CallMethod( &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, base::BindOnce(&DebugDaemonClientImpl::OnGetAllLogs, @@ -280,9 +278,8 @@ void StartAgentTracing(const base::trace_event::TraceConfig& trace_config, StartAgentTracingCallback callback) override { - dbus::MethodCall method_call( - debugd::kDebugdInterface, - debugd::kSystraceStart); + dbus::MethodCall method_call(debugd::kDebugdInterface, + debugd::kSystraceStart); dbus::MessageWriter writer(&method_call); if (trace_config.systrace_events().empty()) { writer.AppendString("all"); // TODO(sleffler) parameterize category list @@ -341,8 +338,7 @@ void TestICMP(const std::string& ip_address, TestICMPCallback callback) override { - dbus::MethodCall method_call(debugd::kDebugdInterface, - debugd::kTestICMP); + dbus::MethodCall method_call(debugd::kDebugdInterface, debugd::kTestICMP); dbus::MessageWriter writer(&method_call); writer.AppendString(ip_address); debugdaemon_proxy_->CallMethod( @@ -630,9 +626,9 @@ while (sub_reader.HasMoreData()) { dbus::MessageReader sub_sub_reader(NULL); std::string key, value; - if (!sub_reader.PopDictEntry(&sub_sub_reader) - || !sub_sub_reader.PopString(&key) - || !sub_sub_reader.PopString(&value)) { + if (!sub_reader.PopDictEntry(&sub_sub_reader) || + !sub_sub_reader.PopString(&key) || + !sub_sub_reader.PopString(&value)) { broken = true; break; } @@ -699,18 +695,16 @@ std::move(callback).Run(std::move(result)); } - void OnEnableDebuggingFeatures( - const EnableDebuggingCallback& callback, - dbus::Response* response) { + void OnEnableDebuggingFeatures(const EnableDebuggingCallback& callback, + dbus::Response* response) { if (callback.is_null()) return; callback.Run(response != NULL); } - void OnQueryDebuggingFeatures( - const QueryDevFeaturesCallback& callback, - dbus::Response* response) { + void OnQueryDebuggingFeatures(const QueryDevFeaturesCallback& callback, + dbus::Response* response) { if (callback.is_null()) return; @@ -723,9 +717,8 @@ callback.Run(true, feature_mask); } - void OnRemoveRootfsVerification( - const EnableDebuggingCallback& callback, - dbus::Response* response) { + void OnRemoveRootfsVerification(const EnableDebuggingCallback& callback, + dbus::Response* response) { if (callback.is_null()) return;
diff --git a/chromeos/dbus/debug_daemon_client.h b/chromeos/dbus/debug_daemon/debug_daemon_client.h similarity index 96% rename from chromeos/dbus/debug_daemon_client.h rename to chromeos/dbus/debug_daemon/debug_daemon_client.h index e23537f..92b3054 100644 --- a/chromeos/dbus/debug_daemon_client.h +++ b/chromeos/dbus/debug_daemon/debug_daemon_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ -#define CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ +#ifndef CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_H_ +#define CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_H_ #include <stdint.h> #include <sys/types.h> @@ -23,10 +23,6 @@ #include "chromeos/dbus/dbus_method_call_status.h" #include "third_party/cros_system_api/dbus/service_constants.h" -namespace metrics { -class DebugdClientProvider; -} // namespace metrics - namespace chromeos { // A DbusLibraryError represents an error response received from D-Bus. @@ -37,7 +33,7 @@ }; // DebugDaemonClient is used to communicate with the debug daemon. -class COMPONENT_EXPORT(CHROMEOS_DBUS) DebugDaemonClient +class COMPONENT_EXPORT(DEBUG_DAEMON) DebugDaemonClient : public DBusClient, public base::trace_event::TracingAgent { public: @@ -153,8 +149,8 @@ // Called once QueryDebuggingFeatures() is complete. |succeeded| will be true // if debugging features have been successfully enabled. |feature_mask| is a // bitmask made out of DebuggingFeature enum values. - typedef base::Callback<void(bool succeeded, - int feature_mask)> QueryDevFeaturesCallback; + typedef base::Callback<void(bool succeeded, int feature_mask)> + QueryDevFeaturesCallback; // Checks which debugging features have been already enabled. virtual void QueryDebuggingFeatures( const QueryDevFeaturesCallback& callback) = 0; @@ -274,7 +270,7 @@ protected: // For calling Init() in initiating a DebugDaemonClient instance for private // connections. - friend class metrics::DebugdClientProvider; + friend class DebugDaemonClientProvider; // Create() should be used instead. DebugDaemonClient(); @@ -285,4 +281,4 @@ } // namespace chromeos -#endif // CHROMEOS_DBUS_DEBUG_DAEMON_CLIENT_H_ +#endif // CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_H_
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client_provider.cc b/chromeos/dbus/debug_daemon/debug_daemon_client_provider.cc new file mode 100644 index 0000000..cf1369fa --- /dev/null +++ b/chromeos/dbus/debug_daemon/debug_daemon_client_provider.cc
@@ -0,0 +1,40 @@ +// Copyright (c) 2019 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 "chromeos/dbus/debug_daemon/debug_daemon_client_provider.h" + +#include "base/task/post_task.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" +#include "dbus/bus.h" +#include "dbus/message.h" +#include "dbus/object_path.h" +#include "dbus/object_proxy.h" +#include "third_party/cros_system_api/dbus/service_constants.h" + +namespace chromeos { + +DebugDaemonClientProvider::DebugDaemonClientProvider() + : dbus_task_runner_(base::CreateSingleThreadTaskRunner( + {base::ThreadPool(), base::TaskPriority::BEST_EFFORT, + base::MayBlock()})), + debug_daemon_client_(DebugDaemonClient::Create()) { + dbus::Bus::Options dbus_options; + dbus_options.bus_type = dbus::Bus::SYSTEM; + dbus_options.connection_type = dbus::Bus::PRIVATE; + dbus_options.dbus_task_runner = dbus_task_runner_; + dbus_bus_ = base::MakeRefCounted<dbus::Bus>(dbus_options); + + debug_daemon_client_->Init(dbus_bus_.get()); +} + +DebugDaemonClientProvider::~DebugDaemonClientProvider() { + DCHECK(debug_daemon_client_); + DCHECK(dbus_bus_); + + debug_daemon_client_ = nullptr; + dbus_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&dbus::Bus::ShutdownAndBlock, dbus_bus_)); +} + +} // namespace chromeos
diff --git a/chromeos/dbus/debug_daemon/debug_daemon_client_provider.h b/chromeos/dbus/debug_daemon/debug_daemon_client_provider.h new file mode 100644 index 0000000..7d572a2 --- /dev/null +++ b/chromeos/dbus/debug_daemon/debug_daemon_client_provider.h
@@ -0,0 +1,53 @@ +// Copyright (c) 2019 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 CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_PROVIDER_H_ +#define CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_PROVIDER_H_ + +#include <memory> + +#include "base/component_export.h" +#include "base/memory/scoped_refptr.h" + +namespace dbus { +class Bus; +} // namespace dbus + +namespace chromeos { +class DebugDaemonClient; + +// This class hosts an instance of DebugDaemonClient used to connect to debugd +// using a private DBus connection. The private connection uses the sequence +// on which DebugDaemonClientProvider is instantiated as the origin thread. Use +// this class if you need to connect to debugd from non-UI thread. +// +// Example: +// // From non-UI thread. The private dbus::Bus binds the current sequence as +// // its origin thread. +// std::unique_ptr<DebugDaemonClientProvider> provider = +// std::make_unique<DebugDaemonClientProvider>(); +// DebugDaemonClient* client = provider->debug_daemon_client(); +// client->GetPerfOutput(...); +// +class COMPONENT_EXPORT(DEBUG_DAEMON) DebugDaemonClientProvider { + public: + DebugDaemonClientProvider(); + ~DebugDaemonClientProvider(); + + DebugDaemonClient* debug_daemon_client() const { + return debug_daemon_client_.get(); + } + + private: + // The private bus. + scoped_refptr<dbus::Bus> dbus_bus_; + scoped_refptr<base::SequencedTaskRunner> dbus_task_runner_; + std::unique_ptr<DebugDaemonClient> debug_daemon_client_; + + DISALLOW_COPY_AND_ASSIGN(DebugDaemonClientProvider); +}; + +} // namespace chromeos + +#endif // CHROMEOS_DBUS_DEBUG_DAEMON_DEBUG_DAEMON_CLIENT_PROVIDER_H_
diff --git a/chromeos/dbus/fake_debug_daemon_client.cc b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc similarity index 98% rename from chromeos/dbus/fake_debug_daemon_client.cc rename to chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc index f08c61d..33a4941 100644 --- a/chromeos/dbus/fake_debug_daemon_client.cc +++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.cc
@@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include <stddef.h> #include <stdint.h> @@ -32,8 +32,7 @@ FakeDebugDaemonClient::FakeDebugDaemonClient() : features_mask_(DebugDaemonClient::DEV_FEATURE_NONE), - service_is_available_(true) { -} + service_is_available_(true) {} FakeDebugDaemonClient::~FakeDebugDaemonClient() = default; @@ -140,8 +139,7 @@ FROM_HERE, base::BindOnce(std::move(callback), base::nullopt)); } -void FakeDebugDaemonClient::UploadCrashes() { -} +void FakeDebugDaemonClient::UploadCrashes() {} void FakeDebugDaemonClient::EnableDebuggingFeatures( const std::string& password,
diff --git a/chromeos/dbus/fake_debug_daemon_client.h b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h similarity index 93% rename from chromeos/dbus/fake_debug_daemon_client.h rename to chromeos/dbus/debug_daemon/fake_debug_daemon_client.h index 34edb31e8..e2b7a19 100644 --- a/chromeos/dbus/fake_debug_daemon_client.h +++ b/chromeos/dbus/debug_daemon/fake_debug_daemon_client.h
@@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROMEOS_DBUS_FAKE_DEBUG_DAEMON_CLIENT_H_ -#define CHROMEOS_DBUS_FAKE_DEBUG_DAEMON_CLIENT_H_ +#ifndef CHROMEOS_DBUS_DEBUG_DAEMON_FAKE_DEBUG_DAEMON_CLIENT_H_ +#define CHROMEOS_DBUS_DEBUG_DAEMON_FAKE_DEBUG_DAEMON_CLIENT_H_ #include <stdint.h> #include <sys/types.h> @@ -16,13 +16,13 @@ #include "base/compiler_specific.h" #include "base/macros.h" #include "chromeos/dbus/dbus_method_call_status.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" namespace chromeos { // The DebugDaemonClient implementation used on Linux desktop, // which does nothing. -class COMPONENT_EXPORT(CHROMEOS_DBUS) FakeDebugDaemonClient +class COMPONENT_EXPORT(DEBUG_DAEMON) FakeDebugDaemonClient : public DebugDaemonClient { public: FakeDebugDaemonClient(); @@ -125,4 +125,4 @@ } // namespace chromeos -#endif // CHROMEOS_DBUS_FAKE_DEBUG_DAEMON_CLIENT_H_ +#endif // CHROMEOS_DBUS_DEBUG_DAEMON_FAKE_DEBUG_DAEMON_CLIENT_H_
diff --git a/chromeos/dbus/shill/fake_shill_device_client.cc b/chromeos/dbus/shill/fake_shill_device_client.cc index a364be4..3951808 100644 --- a/chromeos/dbus/shill/fake_shill_device_client.cc +++ b/chromeos/dbus/shill/fake_shill_device_client.cc
@@ -419,9 +419,9 @@ return; } - base::Value* properties = GetDeviceProperties(device_path.value()); - properties->SetKey(shill::kUsbEthernetMacAddressSourceProperty, - base::Value(source)); + SetDeviceProperty(device_path.value(), + shill::kUsbEthernetMacAddressSourceProperty, + base::Value(source), /*notify_changed=*/true); base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, callback); }
diff --git a/chromeos/network/device_state.cc b/chromeos/network/device_state.cc index 936b2d2b..1b18bc2 100644 --- a/chromeos/network/device_state.cc +++ b/chromeos/network/device_state.cc
@@ -114,6 +114,8 @@ return GetBooleanValue(key, value, &link_up_); } else if (key == shill::kDeviceBusTypeProperty) { return GetStringValue(key, value, &device_bus_type_); + } else if (key == shill::kUsbEthernetMacAddressSourceProperty) { + return GetStringValue(key, value, &mac_address_source_); } return false; }
diff --git a/chromeos/network/device_state.h b/chromeos/network/device_state.h index df3a4f89..4aa84ed 100644 --- a/chromeos/network/device_state.h +++ b/chromeos/network/device_state.h
@@ -66,6 +66,7 @@ } bool link_up() const { return link_up_; } const std::string& device_bus_type() const { return device_bus_type_; } + const std::string& mac_address_source() const { return mac_address_source_; } // WiFi specific accessors const std::string& available_managed_network_path() const { @@ -113,6 +114,7 @@ bool eap_authentication_completed_ = false; bool link_up_ = false; std::string device_bus_type_; + std::string mac_address_source_; // WiFi specific properties std::string available_managed_network_path_;
diff --git a/chromeos/network/network_device_handler_impl.cc b/chromeos/network/network_device_handler_impl.cc index bb46d0a3..3d87a2e 100644 --- a/chromeos/network/network_device_handler_impl.cc +++ b/chromeos/network/network_device_handler_impl.cc
@@ -575,39 +575,37 @@ } void NetworkDeviceHandlerImpl::ApplyUsbEthernetMacAddressSourceToShill() { - const std::string new_primary_enabled_usb_ethernet_device_path = - FindPrimaryEnabledUsbEthernetDevicePath(); - // Restore USB Ethernet MAC address source value to "builtin" at the old - // device path if primary enabled USB Ethernet device path has changed. - if (new_primary_enabled_usb_ethernet_device_path != - primary_enabled_usb_ethernet_device_path_ && - !primary_enabled_usb_ethernet_device_path_.empty()) { - ShillDeviceClient::Get()->SetUsbEthernetMacAddressSource( - dbus::ObjectPath(primary_enabled_usb_ethernet_device_path_), - shill::kUsbEthernetMacAddressSourceUsbAdapterMac, base::DoNothing(), - base::Bind(&HandleShillCallFailure, - primary_enabled_usb_ethernet_device_path_, - network_handler::ErrorCallback())); + // Do nothing else if MAC address source is not specified yet. + if (usb_ethernet_mac_address_source_.empty()) { + NET_LOG(DEBUG) << "Empty USB Ethernet MAC address source."; + return; } + std::string previous_primary_enabled_usb_ethernet_device_path = + primary_enabled_usb_ethernet_device_path_; + + UpdatePrimaryEnabledUsbEthernetDevice(); + ResetMacAddressSourceForSecondaryUsbEthernetDevices(); + // Do nothing else if device path and MAC address source have not changed. if (!usb_ethernet_mac_address_source_needs_update_ && - new_primary_enabled_usb_ethernet_device_path == + previous_primary_enabled_usb_ethernet_device_path == primary_enabled_usb_ethernet_device_path_) { return; } - primary_enabled_usb_ethernet_device_path_ = - new_primary_enabled_usb_ethernet_device_path; usb_ethernet_mac_address_source_needs_update_ = false; const DeviceState* primary_enabled_usb_ethernet_device_state = network_state_handler_->GetDeviceState( primary_enabled_usb_ethernet_device_path_); - // Do nothing else if device path is empty or device state is nullptr. + // Do nothing else if device path is empty or device state is nullptr or + // device MAC address source property equals to needed value. if (primary_enabled_usb_ethernet_device_path_.empty() || - !primary_enabled_usb_ethernet_device_state) { + !primary_enabled_usb_ethernet_device_state || + primary_enabled_usb_ethernet_device_state->mac_address_source() == + usb_ethernet_mac_address_source_) { return; } @@ -628,10 +626,12 @@ const network_handler::ErrorCallback& error_callback, const std::string& shill_error_name, const std::string& shill_error_message) { - mac_address_change_not_supported_.insert(device_mac_address); HandleShillCallFailure(device_path, error_callback, shill_error_name, shill_error_message); - ApplyUsbEthernetMacAddressSourceToShill(); + if (shill_error_name == NetworkDeviceHandler::kErrorNotSupported) { + mac_address_change_not_supported_.insert(device_mac_address); + ApplyUsbEthernetMacAddressSourceToShill(); + } } bool NetworkDeviceHandlerImpl::IsUsbEnabledDevice( @@ -643,8 +643,7 @@ mac_address_change_not_supported_.end(); } -std::string NetworkDeviceHandlerImpl::FindPrimaryEnabledUsbEthernetDevicePath() - const { +void NetworkDeviceHandlerImpl::UpdatePrimaryEnabledUsbEthernetDevice() { NetworkStateHandler::DeviceStateList device_state_list; network_state_handler_->GetDeviceListByType(NetworkTypePattern::Ethernet(), &device_state_list); @@ -657,21 +656,62 @@ for (const auto* device_state : device_state_list) { if (device_state && device_state->link_up() && device_state->device_bus_type() == shill::kDeviceBusTypePci) { - return ""; + primary_enabled_usb_ethernet_device_path_ = ""; + return; } } } + // Nothing change, primary USB Ethernet device still enabled. if (IsUsbEnabledDevice(network_state_handler_->GetDeviceState( primary_enabled_usb_ethernet_device_path_))) { - return primary_enabled_usb_ethernet_device_path_; + return; + } + + // Reset primary enabled USB Ethernet device since it isn't enabled anymore. + primary_enabled_usb_ethernet_device_path_ = ""; + + // Give the priority to USB Ethernet device which already has the required MAC + // address source property. It can happen after Chrome crashes, when shill + // devices have some properties and Chrome does not know which device was + // the primary USB Ethernet before the crash. + for (const auto* device_state : device_state_list) { + if (IsUsbEnabledDevice(device_state) && device_state && + device_state->mac_address_source() == + usb_ethernet_mac_address_source_) { + primary_enabled_usb_ethernet_device_path_ = device_state->path(); + return; + } } for (const auto* device_state : device_state_list) { - if (IsUsbEnabledDevice(device_state)) - return device_state->path(); + if (IsUsbEnabledDevice(device_state)) { + primary_enabled_usb_ethernet_device_path_ = device_state->path(); + return; + } } - return ""; +} + +void NetworkDeviceHandlerImpl:: + ResetMacAddressSourceForSecondaryUsbEthernetDevices() const { + NetworkStateHandler::DeviceStateList device_state_list; + network_state_handler_->GetDeviceListByType(NetworkTypePattern::Ethernet(), + &device_state_list); + + for (const auto* device_state : device_state_list) { + if (!device_state || + device_state->path() == primary_enabled_usb_ethernet_device_path_ || + device_state->mac_address_source().empty() || + device_state->mac_address_source() == + shill::kUsbEthernetMacAddressSourceUsbAdapterMac) { + continue; + } + ShillDeviceClient::Get()->SetUsbEthernetMacAddressSource( + dbus::ObjectPath(device_state->path()), + shill::kUsbEthernetMacAddressSourceUsbAdapterMac, base::DoNothing(), + base::Bind(&HandleShillCallFailure, device_state->path(), + network_handler::ErrorCallback())); + } } void NetworkDeviceHandlerImpl::HandleMACAddressRandomization(
diff --git a/chromeos/network/network_device_handler_impl.h b/chromeos/network/network_device_handler_impl.h index 8e1191c3..465ad4e 100644 --- a/chromeos/network/network_device_handler_impl.h +++ b/chromeos/network/network_device_handler_impl.h
@@ -166,8 +166,11 @@ // Checks whether Device is enabled USB Ethernet adapter. bool IsUsbEnabledDevice(const DeviceState* device_state) const; - // Returns path for primary enabled USB Ethernet device. - std::string FindPrimaryEnabledUsbEthernetDevicePath() const; + // Updates the primary enabled USB Ethernet device path. + void UpdatePrimaryEnabledUsbEthernetDevice(); + + // Resets MAC address source property for secondary USB Ethernet devices. + void ResetMacAddressSourceForSecondaryUsbEthernetDevices() const; // Sets the value of |mac_addr_randomization_supported_| based on // whether shill thinks it is supported on the wifi device. If it is
diff --git a/chromeos/network/network_device_handler_unittest.cc b/chromeos/network/network_device_handler_unittest.cc index 07d503b..52da2df 100644 --- a/chromeos/network/network_device_handler_unittest.cc +++ b/chromeos/network/network_device_handler_unittest.cc
@@ -109,6 +109,16 @@ ASSERT_EQ(expected_result, result_); } + void ExpectDeviceProperty(const std::string& device_path, + const std::string& property_name, + const std::string& expected_value) { + GetDeviceProperties(device_path, kResultSuccess); + std::string value; + ASSERT_TRUE( + properties_->GetStringWithoutPathExpansion(property_name, &value)); + ASSERT_EQ(value, expected_value); + } + protected: base::test::SingleThreadTaskEnvironment task_environment_; std::string result_; @@ -223,6 +233,66 @@ EXPECT_FALSE(allow_roaming); } +TEST_F(NetworkDeviceHandlerTest, + ResetUsbEthernetMacAddressSourceForSecondaryUsbDevices) { + ShillDeviceClient::TestInterface* device_test = + fake_device_client_->GetTestInterface(); + + constexpr char kSource[] = "some_source1"; + + constexpr char kUsbEthernetDevicePath1[] = "usb_ethernet_device1"; + device_test->AddDevice(kUsbEthernetDevicePath1, shill::kTypeEthernet, "eth1"); + device_test->SetDeviceProperty( + kUsbEthernetDevicePath1, shill::kDeviceBusTypeProperty, + base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath1, + shill::kLinkUpProperty, base::Value(true), + /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath1, + shill::kUsbEthernetMacAddressSourceProperty, + base::Value("source_to_override1"), + /*notify_changed=*/true); + constexpr char kUsbEthernetDevicePath2[] = "usb_ethernet_device2"; + device_test->AddDevice(kUsbEthernetDevicePath2, shill::kTypeEthernet, "eth2"); + device_test->SetDeviceProperty( + kUsbEthernetDevicePath2, shill::kDeviceBusTypeProperty, + base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath2, + shill::kLinkUpProperty, base::Value(true), + /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath2, + shill::kUsbEthernetMacAddressSourceProperty, + base::Value(kSource), + /*notify_changed=*/true); + constexpr char kUsbEthernetDevicePath3[] = "usb_ethernet_device3"; + device_test->AddDevice(kUsbEthernetDevicePath3, shill::kTypeEthernet, "eth3"); + device_test->SetDeviceProperty( + kUsbEthernetDevicePath3, shill::kDeviceBusTypeProperty, + base::Value(shill::kDeviceBusTypeUsb), /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath3, + shill::kLinkUpProperty, base::Value(true), + /*notify_changed=*/true); + device_test->SetDeviceProperty(kUsbEthernetDevicePath3, + shill::kUsbEthernetMacAddressSourceProperty, + base::Value("source_to_override2"), + /*notify_changed=*/true); + + network_device_handler_->SetUsbEthernetMacAddressSource(kSource); + base::RunLoop().RunUntilIdle(); + + // Expect to reset source property for eth1 and eth3 since eth2 already has + // needed source value. + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath1, shill::kUsbEthernetMacAddressSourceProperty, + "usb_adapter_mac")); + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath2, shill::kUsbEthernetMacAddressSourceProperty, + kSource)); + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath3, shill::kUsbEthernetMacAddressSourceProperty, + "usb_adapter_mac")); +} + TEST_F(NetworkDeviceHandlerTest, UsbEthernetMacAddressSource) { ShillDeviceClient::TestInterface* device_test = fake_device_client_->GetTestInterface(); @@ -246,7 +316,7 @@ shill::kLinkUpProperty, base::Value(true), /*notify_changed=*/true); device_test->SetUsbEthernetMacAddressSourceError(kUsbEthernetDevicePath2, - "not_supported"); + "not-supported"); constexpr char kUsbEthernetDevicePath3[] = "usb_ethernet_device3"; device_test->AddDevice(kUsbEthernetDevicePath3, shill::kTypeEthernet, "eth3"); @@ -275,43 +345,31 @@ constexpr char kSource1[] = "some_source1"; network_device_handler_->SetUsbEthernetMacAddressSource(kSource1); base::RunLoop().RunUntilIdle(); - network_device_handler_->GetDeviceProperties( - kUsbEthernetDevicePath3, properties_success_callback_, error_callback_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kResultSuccess, result_); - std::string usb_ethernet_mac_address_source; - EXPECT_TRUE(properties_->GetStringWithoutPathExpansion( - shill::kUsbEthernetMacAddressSourceProperty, - &usb_ethernet_mac_address_source)); - EXPECT_EQ(usb_ethernet_mac_address_source, kSource1); + + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath3, shill::kUsbEthernetMacAddressSourceProperty, + kSource1)); // Expect property change on eth3, because device is connected to the // internet. const char* kSource2 = shill::kUsbEthernetMacAddressSourceBuiltinAdapterMac; network_device_handler_->SetUsbEthernetMacAddressSource(kSource2); base::RunLoop().RunUntilIdle(); - network_device_handler_->GetDeviceProperties( - kUsbEthernetDevicePath3, properties_success_callback_, error_callback_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kResultSuccess, result_); - EXPECT_TRUE(properties_->GetStringWithoutPathExpansion( - shill::kUsbEthernetMacAddressSourceProperty, - &usb_ethernet_mac_address_source)); - EXPECT_EQ(usb_ethernet_mac_address_source, kSource2); + + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath3, shill::kUsbEthernetMacAddressSourceProperty, + kSource2)); // Expect property change back to "usb_adapter_mac" on eth3, because device // is not connected to the internet. device_test->SetDeviceProperty(kUsbEthernetDevicePath3, shill::kLinkUpProperty, base::Value(false), /*notify_changed=*/true); - network_device_handler_->GetDeviceProperties( - kUsbEthernetDevicePath3, properties_success_callback_, error_callback_); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kResultSuccess, result_); - EXPECT_TRUE(properties_->GetStringWithoutPathExpansion( - shill::kUsbEthernetMacAddressSourceProperty, - &usb_ethernet_mac_address_source)); - EXPECT_EQ(usb_ethernet_mac_address_source, "usb_adapter_mac"); + + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath3, shill::kUsbEthernetMacAddressSourceProperty, + "usb_adapter_mac")); // Expect property change back to "usb_adapter_mac" on eth1, because both // builtin PCI eth4 and eth1 have the same MAC address and connected to the @@ -322,28 +380,21 @@ device_test->SetDeviceProperty(kPciEthernetDevicePath, shill::kLinkUpProperty, base::Value(true), /*notify_changed=*/true); - network_device_handler_->GetDeviceProperties( - kUsbEthernetDevicePath1, properties_success_callback_, error_callback_); base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kResultSuccess, result_); - EXPECT_TRUE(properties_->GetStringWithoutPathExpansion( - shill::kUsbEthernetMacAddressSourceProperty, - &usb_ethernet_mac_address_source)); - EXPECT_EQ(usb_ethernet_mac_address_source, "usb_adapter_mac"); - // Expect property change on eth1, because device is connected to the internet - // and builtin PCI eth4 and eth1 have different MAC addresses. + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath1, shill::kUsbEthernetMacAddressSourceProperty, + "usb_adapter_mac")); + + // Expect property change on eth1, because device is connected to the + // internet and builtin PCI eth4 and eth1 have different MAC addresses. constexpr char kSource3[] = "some_source3"; network_device_handler_->SetUsbEthernetMacAddressSource(kSource3); base::RunLoop().RunUntilIdle(); - network_device_handler_->GetDeviceProperties( - kUsbEthernetDevicePath1, properties_success_callback_, error_callback_); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(kResultSuccess, result_); - EXPECT_TRUE(properties_->GetStringWithoutPathExpansion( - shill::kUsbEthernetMacAddressSourceProperty, - &usb_ethernet_mac_address_source)); - EXPECT_EQ(usb_ethernet_mac_address_source, kSource3); + + ASSERT_NO_FATAL_FAILURE(ExpectDeviceProperty( + kUsbEthernetDevicePath1, shill::kUsbEthernetMacAddressSourceProperty, + kSource3)); } TEST_F(NetworkDeviceHandlerTest, SetWifiTDLSEnabled) {
diff --git a/chromeos/services/assistant/platform/volume_control_impl.cc b/chromeos/services/assistant/platform/volume_control_impl.cc index 778fed4..ab9a7855 100644 --- a/chromeos/services/assistant/platform/volume_control_impl.cc +++ b/chromeos/services/assistant/platform/volume_control_impl.cc
@@ -6,8 +6,12 @@ #include <utility> +#include "ash/public/mojom/assistant_volume_control.mojom.h" #include "ash/public/mojom/constants.mojom.h" #include "chromeos/services/assistant/media_session/assistant_media_session.h" +#include "mojo/public/cpp/bindings/pending_remote.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" namespace chromeos { namespace assistant { @@ -15,14 +19,13 @@ VolumeControlImpl::VolumeControlImpl(mojom::Client* client, AssistantMediaSession* media_session) : media_session_(media_session), - binding_(this), main_task_runner_(base::SequencedTaskRunnerHandle::Get()), weak_factory_(this) { client->RequestAssistantVolumeControl( - mojo::MakeRequest(&volume_control_ptr_)); - ash::mojom::VolumeObserverPtr observer; - binding_.Bind(mojo::MakeRequest(&observer)); - volume_control_ptr_->AddVolumeObserver(std::move(observer)); + volume_control_.BindNewPipeAndPassReceiver()); + mojo::PendingRemote<ash::mojom::VolumeObserver> observer; + receiver_.Bind(observer.InitWithNewPipeAndPassReceiver()); + volume_control_->AddVolumeObserver(std::move(observer)); } VolumeControlImpl::~VolumeControlImpl() = default; @@ -97,12 +100,12 @@ void VolumeControlImpl::SetSystemVolumeOnMainThread(float new_volume, bool user_initiated) { DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - volume_control_ptr_->SetVolume(new_volume * 100.0, user_initiated); + volume_control_->SetVolume(new_volume * 100.0, user_initiated); } void VolumeControlImpl::SetSystemMutedOnMainThread(bool muted) { DCHECK(main_task_runner_->RunsTasksInCurrentSequence()); - volume_control_ptr_->SetMuted(muted); + volume_control_->SetMuted(muted); } } // namespace assistant
diff --git a/chromeos/services/assistant/platform/volume_control_impl.h b/chromeos/services/assistant/platform/volume_control_impl.h index cc207bd..f2bfa394b 100644 --- a/chromeos/services/assistant/platform/volume_control_impl.h +++ b/chromeos/services/assistant/platform/volume_control_impl.h
@@ -9,7 +9,8 @@ #include "base/macros.h" #include "chromeos/services/assistant/public/mojom/assistant.mojom.h" #include "libassistant/shared/public/platform_audio_output.h" -#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/receiver.h" +#include "mojo/public/cpp/bindings/remote.h" namespace chromeos { namespace assistant { @@ -44,8 +45,8 @@ void SetSystemMutedOnMainThread(bool muted); AssistantMediaSession* media_session_; - ash::mojom::AssistantVolumeControlPtr volume_control_ptr_; - mojo::Binding<ash::mojom::VolumeObserver> binding_; + mojo::Remote<ash::mojom::AssistantVolumeControl> volume_control_; + mojo::Receiver<ash::mojom::VolumeObserver> receiver_{this}; scoped_refptr<base::SequencedTaskRunner> main_task_runner_; int volume_ = 100;
diff --git a/chromeos/services/ime/public/mojom/input_engine.mojom b/chromeos/services/ime/public/mojom/input_engine.mojom index 680eeacb..c6573cb 100644 --- a/chromeos/services/ime/public/mojom/input_engine.mojom +++ b/chromeos/services/ime/public/mojom/input_engine.mojom
@@ -44,7 +44,6 @@ // Information about a specific keypress. struct KeypressInfoForRulebased { - // Keypress Type (Eg; "keydown", "keyup", etc). string type; @@ -55,8 +54,8 @@ bool shift; bool altgr; bool caps; - bool ctrl; - bool alt; + bool ctrl = false; // DEPRECATED + bool alt = false; // DEPRECATED }; // Manages access to a set of IME engines, implemented by the IME service
diff --git a/components/arc/arc_util.cc b/components/arc/arc_util.cc index e439b13..7aad9ce 100644 --- a/components/arc/arc_util.cc +++ b/components/arc/arc_util.cc
@@ -15,7 +15,7 @@ #include "chromeos/constants/chromeos_switches.h" #include "chromeos/dbus/concierge_client.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/session_manager/session_manager_client.h" #include "components/arc/arc_features.h" #include "components/exo/shell_surface_util.h"
diff --git a/components/arc/session/arc_data_remover.cc b/components/arc/session/arc_data_remover.cc index 89d7672..40ae810b 100644 --- a/components/arc/session/arc_data_remover.cc +++ b/components/arc/session/arc_data_remover.cc
@@ -10,7 +10,7 @@ #include "base/callback_helpers.h" #include "base/logging.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/dbus/upstart/upstart_client.h" #include "components/arc/arc_prefs.h" #include "components/arc/arc_util.h"
diff --git a/components/autofill/core/browser/form_structure.cc b/components/autofill/core/browser/form_structure.cc index 5eb8e5a..85be7732 100644 --- a/components/autofill/core/browser/form_structure.cc +++ b/components/autofill/core/browser/form_structure.cc
@@ -412,13 +412,6 @@ upload->set_password_has_lowercase_letter( password_attributes_vote.second); break; - case PasswordAttribute::kHasUppercaseLetter: - upload->set_password_has_uppercase_letter( - password_attributes_vote.second); - break; - case PasswordAttribute::kHasNumeric: - upload->set_password_has_numeric(password_attributes_vote.second); - break; case PasswordAttribute::kHasSpecialSymbol: upload->set_password_has_special_symbol(password_attributes_vote.second); if (password_attributes_vote.second)
diff --git a/components/autofill/core/browser/form_structure.h b/components/autofill/core/browser/form_structure.h index 4ec71b57..d65bc8e 100644 --- a/components/autofill/core/browser/form_structure.h +++ b/components/autofill/core/browser/form_structure.h
@@ -44,8 +44,6 @@ // Password attributes (whether a password has special symbols, numeric, etc.) enum class PasswordAttribute { kHasLowercaseLetter, - kHasUppercaseLetter, - kHasNumeric, kHasSpecialSymbol, kPasswordAttributesCount };
diff --git a/components/autofill/core/browser/form_structure_unittest.cc b/components/autofill/core/browser/form_structure_unittest.cc index 7ebf1c7..68a41e1 100644 --- a/components/autofill/core/browser/form_structure_unittest.cc +++ b/components/autofill/core/browser/form_structure_unittest.cc
@@ -2592,7 +2592,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); @@ -2623,7 +2623,7 @@ upload.set_autofill_used(false); upload.set_data_present("144200030e"); upload.set_passwords_revealed(false); - upload.set_password_has_numeric(true); + upload.set_password_has_lowercase_letter(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); upload.set_submission_event( @@ -2685,7 +2685,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); @@ -2787,7 +2787,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); @@ -2818,7 +2818,7 @@ upload.set_autofill_used(false); upload.set_data_present("144200030e"); upload.set_passwords_revealed(false); - upload.set_password_has_numeric(true); + upload.set_password_has_lowercase_letter(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); @@ -2918,7 +2918,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); ASSERT_EQ(form_structure->field_count(), possible_field_types.size()); @@ -2949,7 +2949,7 @@ upload.set_autofill_used(false); upload.set_data_present("144200030e"); upload.set_passwords_revealed(false); - upload.set_password_has_numeric(true); + upload.set_password_has_lowercase_letter(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); upload.set_submission_event( @@ -3044,7 +3044,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); form_structure->set_submission_event( SubmissionIndicatorEvent::HTML_FORM_SUBMISSION); @@ -3078,7 +3078,7 @@ upload.set_autofill_used(false); upload.set_data_present("144200030e"); upload.set_passwords_revealed(false); - upload.set_password_has_numeric(true); + upload.set_password_has_lowercase_letter(true); upload.set_password_length(10u); upload.set_action_signature(15724779818122431245U); upload.set_has_form_tag(true); @@ -3130,7 +3130,7 @@ form_structure = std::make_unique<FormStructure>(form); form_structure->set_password_attributes_vote( - std::make_pair(PasswordAttribute::kHasNumeric, true)); + std::make_pair(PasswordAttribute::kHasLowercaseLetter, true)); form_structure->set_password_length_vote(10u); form_structure->set_submission_event( SubmissionIndicatorEvent::HTML_FORM_SUBMISSION);
diff --git a/components/autofill/core/browser/proto/server.proto b/components/autofill/core/browser/proto/server.proto index 67002a1..72e0e4f6 100644 --- a/components/autofill/core/browser/proto/server.proto +++ b/components/autofill/core/browser/proto/server.proto
@@ -337,11 +337,11 @@ // Whether the password has any lowercase letter. optional bool password_has_lowercase_letter = 25; - // Whether the password has any uppercase letter. - optional bool password_has_uppercase_letter = 26; + // Deprecated since M80: Whether the password has any uppercase letter. + optional bool password_has_uppercase_letter = 26 [deprecated = true]; - // Whether the password has any digit. - optional bool password_has_numeric = 27; + // Deprecated since M80: Whether the password has any digit. + optional bool password_has_numeric = 27 [deprecated = true]; // Whether the password has any special symbol. optional bool password_has_special_symbol = 28;
diff --git a/components/autofill/core/common/save_password_progress_logger.cc b/components/autofill/core/common/save_password_progress_logger.cc index b26b6c6..1aadf99 100644 --- a/components/autofill/core/common/save_password_progress_logger.cc +++ b/components/autofill/core/common/save_password_progress_logger.cc
@@ -440,12 +440,6 @@ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE: return "Uploading password requirements vote for using lowercase letters"; case SavePasswordProgressLogger:: - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE: - return "Uploading password requirements vote for using lowercase letters"; - case SavePasswordProgressLogger:: - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS: - return "Uploading password requirements vote for using numbers"; - case SavePasswordProgressLogger:: STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL: return "Uploading password requirements vote for using special symbols"; case SavePasswordProgressLogger::
diff --git a/components/autofill/core/common/save_password_progress_logger.h b/components/autofill/core/common/save_password_progress_logger.h index 28ad6d90..1ff14586 100644 --- a/components/autofill/core/common/save_password_progress_logger.h +++ b/components/autofill/core/common/save_password_progress_logger.h
@@ -155,8 +155,6 @@ STRING_LEAK_DETECTION_TOKEN_REQUEST_ERROR, STRING_LEAK_DETECTION_INVALID_SERVER_RESPONSE_ERROR, STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE, - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE, - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS, STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL, STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIFIC_SPECIAL_SYMBOL, STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_PASSWORD_LENGTH,
diff --git a/components/autofill_assistant/browser/controller_observer.cc b/components/autofill_assistant/browser/controller_observer.cc index 15fd369..f951da6e 100644 --- a/components/autofill_assistant/browser/controller_observer.cc +++ b/components/autofill_assistant/browser/controller_observer.cc
@@ -11,31 +11,4 @@ ControllerObserver::ControllerObserver() = default; ControllerObserver::~ControllerObserver() = default; - -void ControllerObserver::OnStateChanged(AutofillAssistantState new_state) {} -void ControllerObserver::OnStatusMessageChanged(const std::string& message) {} -void ControllerObserver::OnBubbleMessageChanged(const std::string& message) {} -void ControllerObserver::CloseCustomTab() {} -void ControllerObserver::OnUserActionsChanged( - const std::vector<UserAction>& user_actions) {} -void ControllerObserver::OnCollectUserDataOptionsChanged( - const CollectUserDataOptions* options) {} -void ControllerObserver::OnUserDataChanged(const UserData* state) {} -void ControllerObserver::OnDetailsChanged(const Details* details) {} -void ControllerObserver::OnInfoBoxChanged(const InfoBox* info_box) {} -void ControllerObserver::OnProgressChanged(int progress) {} -void ControllerObserver::OnProgressVisibilityChanged(bool visible) {} -void ControllerObserver::OnTouchableAreaChanged( - const RectF& visual_viewport, - const std::vector<RectF>& touchable_areas, - const std::vector<RectF>& restricted_areas) {} -void ControllerObserver::OnViewportModeChanged(ViewportMode mode) {} -void ControllerObserver::OnPeekModeChanged( - ConfigureBottomSheetProto::PeekMode peek_mode) {} -void ControllerObserver::OnOverlayColorsChanged( - const UiDelegate::OverlayColors& colors) {} -void ControllerObserver::OnFormChanged(const FormProto* form) {} -void ControllerObserver::OnClientSettingsChanged( - const ClientSettings& settings) {} - } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/controller_observer.h b/components/autofill_assistant/browser/controller_observer.h index 2c576277..82b93a1 100644 --- a/components/autofill_assistant/browser/controller_observer.h +++ b/components/autofill_assistant/browser/controller_observer.h
@@ -31,44 +31,44 @@ ~ControllerObserver() override; // Called when the controller has entered a new state. - virtual void OnStateChanged(AutofillAssistantState new_state); + virtual void OnStateChanged(AutofillAssistantState new_state) = 0; // Report that the status message has changed. - virtual void OnStatusMessageChanged(const std::string& message); + virtual void OnStatusMessageChanged(const std::string& message) = 0; // Report that the bubble / tooltip message has changed. - virtual void OnBubbleMessageChanged(const std::string& message); + virtual void OnBubbleMessageChanged(const std::string& message) = 0; // If the current chrome activity is a custom tab activity, close it. // Otherwise, do nothing. - virtual void CloseCustomTab(); + virtual void CloseCustomTab() = 0; // Report that the set of user actions has changed. virtual void OnUserActionsChanged( - const std::vector<UserAction>& user_actions); + const std::vector<UserAction>& user_actions) = 0; // Report that the options configuring a CollectUserDataAction have changed. virtual void OnCollectUserDataOptionsChanged( - const CollectUserDataOptions* options); + const CollectUserDataOptions* options) = 0; // Updates the currently selected user data (e.g., contact information). - virtual void OnUserDataChanged(const UserData* state); + virtual void OnUserDataChanged(const UserData* state) = 0; // Called when details have changed. Details will be null if they have been // cleared. - virtual void OnDetailsChanged(const Details* details); + virtual void OnDetailsChanged(const Details* details) = 0; // Called when info box has changed. |info_box| will be null if it has been // cleared. - virtual void OnInfoBoxChanged(const InfoBox* info_box); + virtual void OnInfoBoxChanged(const InfoBox* info_box) = 0; // Called when the current progress has changed. Progress, is expressed as a // percentage. - virtual void OnProgressChanged(int progress); + virtual void OnProgressChanged(int progress) = 0; // Called when the current progress bar visibility has changed. If |visible| // is true, then the bar is now shown. - virtual void OnProgressVisibilityChanged(bool visible); + virtual void OnProgressVisibilityChanged(bool visible) = 0; // Updates the area of the visible viewport that is accessible when the // overlay state is OverlayState::PARTIAL. @@ -88,22 +88,24 @@ virtual void OnTouchableAreaChanged( const RectF& visual_viewport, const std::vector<RectF>& touchable_areas, - const std::vector<RectF>& restricted_areas); + const std::vector<RectF>& restricted_areas) = 0; // Called when the viewport mode has changed. - virtual void OnViewportModeChanged(ViewportMode mode); + virtual void OnViewportModeChanged(ViewportMode mode) = 0; // Called when the peek mode has changed. - virtual void OnPeekModeChanged(ConfigureBottomSheetProto::PeekMode peek_mode); + virtual void OnPeekModeChanged( + ConfigureBottomSheetProto::PeekMode peek_mode) = 0; // Called when the overlay colors have changed. - virtual void OnOverlayColorsChanged(const UiDelegate::OverlayColors& colors); + virtual void OnOverlayColorsChanged( + const UiDelegate::OverlayColors& colors) = 0; // Called when the form has changed. - virtual void OnFormChanged(const FormProto* form); + virtual void OnFormChanged(const FormProto* form) = 0; // Called when client settings have changed. - virtual void OnClientSettingsChanged(const ClientSettings& settings); + virtual void OnClientSettingsChanged(const ClientSettings& settings) = 0; }; } // namespace autofill_assistant #endif // COMPONENTS_AUTOFILL_ASSISTANT_BROWSER_CONTROLLER_OBSERVER_H_
diff --git a/components/autofill_assistant/browser/controller_unittest.cc b/components/autofill_assistant/browser/controller_unittest.cc index 50227cb..a97f886 100644 --- a/components/autofill_assistant/browser/controller_unittest.cc +++ b/components/autofill_assistant/browser/controller_unittest.cc
@@ -521,6 +521,28 @@ EXPECT_TRUE(controller_->PerformUserAction(0)); } +TEST_F(ControllerTest, CloseCustomTab) { + SupportsScriptResponseProto script_response; + AddRunnableScript(&script_response, "stop"); + SetNextScriptResponse(script_response); + + ActionsResponseProto actions_response; + actions_response.add_actions()->mutable_stop()->set_close_cct(true); + std::string actions_response_str; + actions_response.SerializeToString(&actions_response_str); + EXPECT_CALL(*mock_service_, OnGetActions(StrEq("stop"), _, _, _, _, _)) + .WillOnce(RunOnceCallback<5>(true, actions_response_str)); + + Start(); + ASSERT_THAT(controller_->GetUserActions(), SizeIs(1)); + EXPECT_CALL(mock_observer_, CloseCustomTab()).Times(1); + + testing::InSequence seq; + EXPECT_CALL(fake_client_, + Shutdown(Metrics::DropOutReason::CUSTOM_TAB_CLOSED)); + EXPECT_TRUE(controller_->PerformUserAction(0)); +} + TEST_F(ControllerTest, Reset) { // 1. Fetch scripts for URL, which in contains a single "reset" script. SupportsScriptResponseProto script_response; @@ -1574,4 +1596,31 @@ Eq(0)); } +TEST_F(ControllerTest, SetOverlayColors) { + EXPECT_CALL( + mock_observer_, + OnOverlayColorsChanged(AllOf( + Field(&Controller::OverlayColors::background, StrEq("#FF000000")), + Field(&Controller::OverlayColors::highlight_border, + StrEq("#FFFFFFFF"))))); + + std::map<std::string, std::string> parameters; + parameters["OVERLAY_COLORS"] = "#FF000000:#FFFFFFFF"; + auto context = TriggerContext::Create(parameters, "exps"); + + GURL url("http://a.example.com/path"); + controller_->Start(url, std::move(context)); +} + +TEST_F(ControllerTest, ChangeClientSettings) { + SupportsScriptResponseProto response; + response.mutable_client_settings()->set_periodic_script_check_interval_ms(1); + SetupScripts(response); + EXPECT_CALL(mock_observer_, + OnClientSettingsChanged( + Field(&ClientSettings::periodic_script_check_interval, + base::TimeDelta::FromMilliseconds(1)))); + Start(); +} + } // namespace autofill_assistant
diff --git a/components/autofill_assistant/browser/mock_controller_observer.h b/components/autofill_assistant/browser/mock_controller_observer.h index 151bdc1..995f662 100644 --- a/components/autofill_assistant/browser/mock_controller_observer.h +++ b/components/autofill_assistant/browser/mock_controller_observer.h
@@ -13,6 +13,7 @@ #include "components/autofill_assistant/browser/controller_observer.h" #include "components/autofill_assistant/browser/metrics.h" #include "components/autofill_assistant/browser/script.h" +#include "components/autofill_assistant/browser/ui_delegate.h" #include "testing/gmock/include/gmock/gmock.h" namespace autofill_assistant { @@ -24,6 +25,7 @@ MOCK_METHOD1(OnStatusMessageChanged, void(const std::string& message)); MOCK_METHOD1(OnBubbleMessageChanged, void(const std::string& message)); + MOCK_METHOD0(CloseCustomTab, void()); MOCK_METHOD1(OnStateChanged, void(AutofillAssistantState)); MOCK_METHOD1(OnUserActionsChanged, void(const std::vector<UserAction>& user_actions)); @@ -43,9 +45,10 @@ MOCK_METHOD1(OnViewportModeChanged, void(ViewportMode mode)); MOCK_METHOD1(OnPeekModeChanged, void(ConfigureBottomSheetProto::PeekMode peek_mode)); + MOCK_METHOD1(OnOverlayColorsChanged, + void(const UiDelegate::OverlayColors& colors)); MOCK_METHOD1(OnFormChanged, void(const FormProto* form)); - - // TODO(b/141163294): add missing methods and unit tests. + MOCK_METHOD1(OnClientSettingsChanged, void(const ClientSettings& settings)); }; } // namespace autofill_assistant
diff --git a/components/dom_distiller/core/dom_distiller_service.cc b/components/dom_distiller/core/dom_distiller_service.cc index 8ed1cee..10d6afff 100644 --- a/components/dom_distiller/core/dom_distiller_service.cc +++ b/components/dom_distiller/core/dom_distiller_service.cc
@@ -32,14 +32,6 @@ return skeleton; } -void RunArticleAvailableCallback( - const DomDistillerService::ArticleAvailableCallback& article_cb, - const ArticleEntry& entry, - const DistilledArticleProto* article_proto, - bool distillation_succeeded) { - article_cb.Run(distillation_succeeded); -} - } // namespace DomDistillerService::DomDistillerService( @@ -67,47 +59,6 @@ std::move(handle)); } -const std::string DomDistillerService::AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) { - ArticleEntry entry; - const bool is_already_added = store_ && store_->GetEntryByUrl(url, &entry); - - TaskTracker* task_tracker = nullptr; - if (is_already_added) { - task_tracker = GetTaskTrackerForEntry(entry); - if (task_tracker == nullptr) { - // Entry is in the store but there is no task tracker. This could - // happen when distillation has already completed. For now just return - // true. - // TODO(shashishekhar): Change this to check if article is available, - // An article may not be available for a variety of reasons, e.g. - // distillation failure or blobs not available locally. - base::ThreadTaskRunnerHandle::Get()->PostTask( - FROM_HERE, base::BindOnce(article_cb, true)); - return entry.entry_id(); - } - } else { - GetOrCreateTaskTrackerForUrl(url, &task_tracker); - } - - if (!article_cb.is_null()) { - task_tracker->AddSaveCallback( - base::Bind(&RunArticleAvailableCallback, article_cb)); - } - - if (!is_already_added) { - task_tracker->AddSaveCallback(base::Bind( - &DomDistillerService::AddDistilledPageToList, base::Unretained(this))); - task_tracker->StartDistiller(distiller_factory_.get(), - std::move(distiller_page)); - task_tracker->StartBlobFetcher(); - } - - return task_tracker->GetEntryId(); -} - bool DomDistillerService::HasEntry(const std::string& entry_id) { return store_ && store_->GetEntryById(entry_id, nullptr); } @@ -120,32 +71,6 @@ return ""; } -std::vector<ArticleEntry> DomDistillerService::GetEntries() const { - if (!store_) { - return std::vector<ArticleEntry>(); - } - return store_->GetEntries(); -} - -std::unique_ptr<ArticleEntry> DomDistillerService::RemoveEntry( - const std::string& entry_id) { - std::unique_ptr<ArticleEntry> entry(new ArticleEntry); - entry->set_entry_id(entry_id); - TaskTracker* task_tracker = GetTaskTrackerForEntry(*entry); - if (task_tracker != nullptr) { - task_tracker->CancelSaveCallbacks(); - } - - if (!store_ || !store_->GetEntryById(entry_id, entry.get())) { - return std::unique_ptr<ArticleEntry>(); - } - - if (store_->RemoveEntry(*entry)) { - return entry; - } - return std::unique_ptr<ArticleEntry>(); -} - std::unique_ptr<ViewerHandle> DomDistillerService::ViewEntry( ViewRequestDelegate* delegate, std::unique_ptr<DistillerPage> distiller_page, @@ -259,19 +184,6 @@ } } -void DomDistillerService::AddDistilledPageToList( - const ArticleEntry& entry, - const DistilledArticleProto* article_proto, - bool distillation_succeeded) { - DCHECK(IsEntryValid(entry)); - if (store_ && distillation_succeeded) { - DCHECK(article_proto); - DCHECK_GT(article_proto->pages_size(), 0); - store_->AddEntry(entry); - DCHECK_EQ(article_proto->pages_size(), entry.pages_size()); - } -} - DistilledPagePrefs* DomDistillerService::GetDistilledPagePrefs() { return distilled_page_prefs_.get(); }
diff --git a/components/dom_distiller/core/dom_distiller_service.h b/components/dom_distiller/core/dom_distiller_service.h index 59d8e51..8532d8a 100644 --- a/components/dom_distiller/core/dom_distiller_service.h +++ b/components/dom_distiller/core/dom_distiller_service.h
@@ -11,7 +11,6 @@ #include "base/callback.h" #include "base/macros.h" -#include "base/memory/weak_ptr.h" #include "components/dom_distiller/core/article_entry.h" #include "components/dom_distiller/core/distilled_page_prefs.h" #include "components/dom_distiller/core/distiller_page.h" @@ -20,7 +19,6 @@ namespace dom_distiller { -class DistilledArticleProto; class DistilledContentStore; class DistillerFactory; class DistillerPageFactory; @@ -37,17 +35,6 @@ typedef base::Callback<void(bool)> ArticleAvailableCallback; virtual ~DomDistillerServiceInterface() {} - // Distill the article at |url| and add the resulting entry to the DOM - // distiller list. |article_cb| is always invoked, and the bool argument to it - // represents whether the article is available offline. - // Use CreateDefaultDistillerPage() to create a default |distiller_page|. - // The provided |distiller_page| is only used if there is not already a - // distillation task in progress for the given |url|. - virtual const std::string AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) = 0; - // Returns whether an article stored has the given entry id. virtual bool HasEntry(const std::string& entry_id) = 0; @@ -56,13 +43,6 @@ // empty string if there is no entry associated with the given entry ID. virtual std::string GetUrlForEntry(const std::string& entry_id) = 0; - // Gets the full list of entries. - virtual std::vector<ArticleEntry> GetEntries() const = 0; - - // Removes the specified entry from the dom distiller store. - virtual std::unique_ptr<ArticleEntry> RemoveEntry( - const std::string& entry_id) = 0; - // Request to view an article by entry id. Returns a null pointer if no entry // with |entry_id| exists. The ViewerHandle should be destroyed before the // ViewRequestDelegate. The request will be cancelled when the handle is @@ -113,15 +93,8 @@ ~DomDistillerService() override; // DomDistillerServiceInterface implementation. - const std::string AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) override; bool HasEntry(const std::string& entry_id) override; std::string GetUrlForEntry(const std::string& entry_id) override; - std::vector<ArticleEntry> GetEntries() const override; - std::unique_ptr<ArticleEntry> RemoveEntry( - const std::string& entry_id) override; std::unique_ptr<ViewerHandle> ViewEntry( ViewRequestDelegate* delegate, std::unique_ptr<DistillerPage> distiller_page, @@ -138,9 +111,6 @@ private: void CancelTask(TaskTracker* task); - void AddDistilledPageToList(const ArticleEntry& entry, - const DistilledArticleProto* article_proto, - bool distillation_succeeded); TaskTracker* CreateTaskTracker(const ArticleEntry& entry);
diff --git a/components/dom_distiller/core/dom_distiller_service_unittest.cc b/components/dom_distiller/core/dom_distiller_service_unittest.cc index d2590e3..c88a344 100644 --- a/components/dom_distiller/core/dom_distiller_service_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_service_unittest.cc
@@ -33,6 +33,8 @@ namespace { +const char kTestEntryId[] = "id0"; + class FakeViewRequestDelegate : public ViewRequestDelegate { public: ~FakeViewRequestDelegate() override {} @@ -46,12 +48,6 @@ MOCK_METHOD1(DistillationCompleted, void(bool)); }; -DomDistillerService::ArticleAvailableCallback ArticleCallback( - MockArticleAvailableCallback* callback) { - return base::Bind(&MockArticleAvailableCallback::DistillationCompleted, - base::Unretained(callback)); -} - void RunDistillerCallback(FakeDistiller* distiller, std::unique_ptr<DistilledArticleProto> proto) { distiller->RunDistillerCallback(std::move(proto)); @@ -75,9 +71,13 @@ class DomDistillerServiceTest : public testing::Test { public: void SetUp() override { + // Create a test entry in the DB. + ArticleEntry entry; + entry.set_entry_id(kTestEntryId); + entry.add_pages()->set_url("http://www.example.com/p1"); + db_model_[kTestEntryId] = entry; FakeDB<ArticleEntry>* fake_db = new FakeDB<ArticleEntry>(&db_model_); - FakeDB<ArticleEntry>::EntryMap store_model; - store_ = test::util::CreateStoreWithFakeDB(fake_db, store_model); + store_ = test::util::CreateStoreWithFakeDB(fake_db, db_model_); distiller_factory_ = new MockDistillerFactory(); distiller_page_factory_ = new MockDistillerPageFactory(); service_.reset(new DomDistillerService( @@ -111,18 +111,10 @@ EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) .WillOnce(Return(distiller)); - GURL url("http://www.example.com/p1"); - std::string entry_id("id0"); - ArticleEntry entry; - entry.set_entry_id(entry_id); - entry.add_pages()->set_url(url.spec()); - - store_->AddEntry(entry); - FakeViewRequestDelegate viewer_delegate; std::unique_ptr<ViewerHandle> handle = service_->ViewEntry( &viewer_delegate, service_->CreateDefaultDistillerPage(gfx::Size()), - entry_id); + kTestEntryId); ASSERT_FALSE(distiller->GetArticleCallback().is_null()); @@ -213,304 +205,5 @@ EXPECT_TRUE(distiller_destroyed); } -TEST_F(DomDistillerServiceTest, TestViewUrlDoesNotAddEntry) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - FakeViewRequestDelegate viewer_delegate; - GURL url("http://www.example.com/p1"); - std::unique_ptr<ViewerHandle> handle = service_->ViewUrl( - &viewer_delegate, service_->CreateDefaultDistillerPage(gfx::Size()), url); - - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(url.spec()); - EXPECT_CALL(viewer_delegate, OnArticleReady(proto.get())); - - RunDistillerCallback(distiller, std::move(proto)); - base::RunLoop().RunUntilIdle(); - // The entry should not be added to the store. - EXPECT_EQ(0u, store_->GetEntries().size()); -} - -TEST_F(DomDistillerServiceTest, TestAddAndRemoveEntry) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - GURL url("http://www.example.com/p1"); - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(true)); - - std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - ASSERT_FALSE(distiller->GetArticleCallback().is_null()); - EXPECT_EQ(url, distiller->GetUrl()); - - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(url.spec()); - RunDistillerCallback(distiller, std::move(proto)); - - ArticleEntry entry; - EXPECT_TRUE(store_->GetEntryByUrl(url, &entry)); - EXPECT_EQ(entry.entry_id(), entry_id); - EXPECT_EQ(1u, store_->GetEntries().size()); - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, store_->GetEntries().size()); -} - -TEST_F(DomDistillerServiceTest, TestCancellation) { - FakeDistiller* distiller = new FakeDistiller(false); - - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(false)); - - GURL url("http://www.example.com/p1"); - std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - // Remove entry will cause the |article_cb| to be called with false value. - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(DomDistillerServiceTest, TestMultipleCallbacks) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - const int kClientsCount = 5; - MockArticleAvailableCallback article_cb[kClientsCount]; - // Adding a URL and then distilling calls all clients. - GURL url("http://www.example.com/p1"); - const std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb[0])); - EXPECT_CALL(article_cb[0], DistillationCompleted(true)); - - for (int i = 1; i < kClientsCount; ++i) { - EXPECT_EQ(entry_id, - service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb[i]))); - EXPECT_CALL(article_cb[i], DistillationCompleted(true)); - } - - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(url.spec()); - RunDistillerCallback(distiller, std::move(proto)); - - // Add the same url again, all callbacks should be called with true. - for (int i = 0; i < kClientsCount; ++i) { - EXPECT_CALL(article_cb[i], DistillationCompleted(true)); - EXPECT_EQ(entry_id, - service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb[i]))); - } - - base::RunLoop().RunUntilIdle(); -} - -TEST_F(DomDistillerServiceTest, TestMultipleCallbacksOnRemove) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - const int kClientsCount = 5; - MockArticleAvailableCallback article_cb[kClientsCount]; - // Adding a URL and remove the entry before distillation. Callback should be - // called with false. - GURL url("http://www.example.com/p1"); - const std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb[0])); - - EXPECT_CALL(article_cb[0], DistillationCompleted(false)); - for (int i = 1; i < kClientsCount; ++i) { - EXPECT_EQ(entry_id, - service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb[i]))); - EXPECT_CALL(article_cb[i], DistillationCompleted(false)); - } - - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); -} - -TEST_F(DomDistillerServiceTest, TestMultiplePageArticle) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - const int kPageCount = 8; - - std::string base_url("http://www.example.com/p"); - GURL pages_url[kPageCount]; - for (int page_num = 0; page_num < kPageCount; ++page_num) { - pages_url[page_num] = GURL(base_url + base::NumberToString(page_num)); - } - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(true)); - - std::string entry_id = service_->AddToList( - pages_url[0], service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - ArticleEntry entry; - ASSERT_FALSE(distiller->GetArticleCallback().is_null()); - EXPECT_EQ(pages_url[0], distiller->GetUrl()); - - // Create the article with pages to pass to the distiller. - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(pages_url[0].spec()); - for (int page_num = 1; page_num < kPageCount; ++page_num) { - DistilledPageProto* distilled_page = proto->add_pages(); - distilled_page->set_url(pages_url[page_num].spec()); - } - - RunDistillerCallback(distiller, std::move(proto)); - EXPECT_TRUE(store_->GetEntryByUrl(pages_url[0], &entry)); - - EXPECT_EQ(kPageCount, entry.pages_size()); - // An article should have just one entry. - EXPECT_EQ(1u, store_->GetEntries().size()); - - // All pages should have correct urls. - for (int page_num = 0; page_num < kPageCount; ++page_num) { - EXPECT_EQ(pages_url[page_num].spec(), entry.pages(page_num).url()); - } - - // Should be able to query article using any of the pages url. - for (int page_num = 0; page_num < kPageCount; ++page_num) { - EXPECT_TRUE(store_->GetEntryByUrl(pages_url[page_num], &entry)); - } - - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, store_->GetEntries().size()); -} - -TEST_F(DomDistillerServiceTest, TestHasEntry) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - GURL url("http://www.example.com/p1"); - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(true)); - - std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - ASSERT_FALSE(distiller->GetArticleCallback().is_null()); - EXPECT_EQ(url, distiller->GetUrl()); - - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(url.spec()); - RunDistillerCallback(distiller, std::move(proto)); - - // Check that HasEntry returns true for the article just added. - EXPECT_TRUE(service_->HasEntry(entry_id)); - - // Remove article and check that there is no longer an entry for the given - // entry id. - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, store_->GetEntries().size()); - EXPECT_FALSE(service_->HasEntry(entry_id)); -} - -TEST_F(DomDistillerServiceTest, TestGetUrlForOnePageEntry) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - GURL url("http://www.example.com/p1"); - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(true)); - - std::string entry_id = service_->AddToList( - url, service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - ASSERT_FALSE(distiller->GetArticleCallback().is_null()); - EXPECT_EQ(url, distiller->GetUrl()); - - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(url.spec()); - RunDistillerCallback(distiller, std::move(proto)); - - // Check if retrieved URL is same as given URL. - GURL retrieved_url(service_->GetUrlForEntry(entry_id)); - EXPECT_EQ(url, retrieved_url); - - // Remove article and check that there is no longer an entry for the given - // entry id. - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, store_->GetEntries().size()); - EXPECT_EQ("", service_->GetUrlForEntry(entry_id)); -} - -TEST_F(DomDistillerServiceTest, TestGetUrlForMultiPageEntry) { - FakeDistiller* distiller = new FakeDistiller(false); - EXPECT_CALL(*distiller_factory_, CreateDistillerImpl()) - .WillOnce(Return(distiller)); - - const int kPageCount = 8; - - std::string base_url("http://www.example.com/p"); - GURL pages_url[kPageCount]; - for (int page_num = 0; page_num < kPageCount; ++page_num) { - pages_url[page_num] = GURL(base_url + base::NumberToString(page_num)); - } - - MockArticleAvailableCallback article_cb; - EXPECT_CALL(article_cb, DistillationCompleted(true)); - - std::string entry_id = service_->AddToList( - pages_url[0], service_->CreateDefaultDistillerPage(gfx::Size()), - ArticleCallback(&article_cb)); - - ArticleEntry entry; - ASSERT_FALSE(distiller->GetArticleCallback().is_null()); - EXPECT_EQ(pages_url[0], distiller->GetUrl()); - - // Create the article with pages to pass to the distiller. - std::unique_ptr<DistilledArticleProto> proto = - CreateArticleWithURL(pages_url[0].spec()); - for (int page_num = 1; page_num < kPageCount; ++page_num) { - DistilledPageProto* distilled_page = proto->add_pages(); - distilled_page->set_url(pages_url[page_num].spec()); - } - - RunDistillerCallback(distiller, std::move(proto)); - EXPECT_TRUE(store_->GetEntryByUrl(pages_url[0], &entry)); - - // Check if retrieved URL is same as given URL for the first page. - GURL retrieved_url(service_->GetUrlForEntry(entry_id)); - EXPECT_EQ(pages_url[0], retrieved_url); - - // Remove the article and check that no URL can be retrieved for the entry. - service_->RemoveEntry(entry_id); - base::RunLoop().RunUntilIdle(); - EXPECT_EQ(0u, store_->GetEntries().size()); - EXPECT_EQ("", service_->GetUrlForEntry(entry_id)); -} - } // namespace test } // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_store.cc b/components/dom_distiller/core/dom_distiller_store.cc index 826ee22..d187df2b 100644 --- a/components/dom_distiller/core/dom_distiller_store.cc +++ b/components/dom_distiller/core/dom_distiller_store.cc
@@ -49,67 +49,10 @@ return model_.GetEntryByUrl(url, entry); } -bool DomDistillerStore::AddEntry(const ArticleEntry& entry) { - return ChangeEntry(entry, SyncChange::ACTION_ADD); -} - -bool DomDistillerStore::UpdateEntry(const ArticleEntry& entry) { - return ChangeEntry(entry, SyncChange::ACTION_UPDATE); -} - -bool DomDistillerStore::RemoveEntry(const ArticleEntry& entry) { - return ChangeEntry(entry, SyncChange::ACTION_DELETE); -} - -bool DomDistillerStore::ChangeEntry(const ArticleEntry& entry, - SyncChange::SyncChangeType changeType) { - if (!database_loaded_) { - return false; - } - - bool hasEntry = model_.GetEntryById(entry.entry_id(), nullptr); - if (hasEntry) { - if (changeType == SyncChange::ACTION_ADD) { - DVLOG(1) << "Already have entry with id " << entry.entry_id() << "."; - return false; - } - } else if (changeType != SyncChange::ACTION_ADD) { - DVLOG(1) << "No entry with id " << entry.entry_id() << " found."; - return false; - } - - SyncChangeList changes_to_apply; - changes_to_apply.push_back( - SyncChange(FROM_HERE, changeType, CreateLocalData(entry))); - - SyncChangeList changes_applied; - SyncChangeList changes_missing; - - ApplyChangesToModel(changes_to_apply, &changes_applied, &changes_missing); - - if (changeType == SyncChange::ACTION_UPDATE && changes_applied.size() != 1) { - DVLOG(1) << "Failed to update entry with id " << entry.entry_id() << "."; - return false; - } - - DCHECK_EQ(size_t(0), changes_missing.size()); - DCHECK_EQ(size_t(1), changes_applied.size()); - - ApplyChangesToDatabase(changes_applied); - - return true; -} - std::vector<ArticleEntry> DomDistillerStore::GetEntries() const { return model_.GetEntries(); } -void DomDistillerStore::ApplyChangesToModel(const SyncChangeList& changes, - SyncChangeList* changes_applied, - SyncChangeList* changes_missing) { - model_.ApplyChangesToModel(changes, changes_applied, changes_missing); -} - void DomDistillerStore::OnDatabaseInit( leveldb_proto::Enums::InitStatus status) { if (status != leveldb_proto::Enums::InitStatus::kOK) { @@ -188,7 +131,8 @@ SyncChangeList changes_to_apply; model_.CalculateChangesForMerge(data, &changes_to_apply, changes_missing); - ApplyChangesToModel(changes_to_apply, changes_applied, changes_missing); + model_.ApplyChangesToModel(changes_to_apply, changes_applied, + changes_missing); } } // namespace dom_distiller
diff --git a/components/dom_distiller/core/dom_distiller_store.h b/components/dom_distiller/core/dom_distiller_store.h index 1153ee9b..1c6cab8 100644 --- a/components/dom_distiller/core/dom_distiller_store.h +++ b/components/dom_distiller/core/dom_distiller_store.h
@@ -24,11 +24,6 @@ public: virtual ~DomDistillerStoreInterface() {} - virtual bool AddEntry(const ArticleEntry& entry) = 0; - // Returns false if |entry| is not present or |entry| was not updated. - virtual bool UpdateEntry(const ArticleEntry& entry) = 0; - virtual bool RemoveEntry(const ArticleEntry& entry) = 0; - // Lookup an ArticleEntry by ID or URL. Returns whether a corresponding entry // was found. On success, if |entry| is not null, it will contain the entry. virtual bool GetEntryById(const std::string& entry_id, @@ -70,10 +65,6 @@ ~DomDistillerStore() override; - bool AddEntry(const ArticleEntry& entry) override; - bool UpdateEntry(const ArticleEntry& entry) override; - bool RemoveEntry(const ArticleEntry& entry) override; - bool GetEntryById(const std::string& entry_id, ArticleEntry* entry) override; bool GetEntryByUrl(const GURL& url, ArticleEntry* entry) override; std::vector<ArticleEntry> GetEntries() const override; @@ -83,22 +74,12 @@ void OnDatabaseLoad(bool success, std::unique_ptr<EntryVector> entries); void OnDatabaseSave(bool success); - // Returns true if the change is successfully applied. - bool ChangeEntry(const ArticleEntry& entry, - syncer::SyncChange::SyncChangeType changeType); - void MergeDataWithModel(const syncer::SyncDataList& data, syncer::SyncChangeList* changes_applied, syncer::SyncChangeList* changes_missing); bool ApplyChangesToDatabase(const syncer::SyncChangeList& change_list); - // Applies the changes to |model_|. If the model returns an error, disables - // syncing and database changes and returns false. - void ApplyChangesToModel(const syncer::SyncChangeList& change_list, - syncer::SyncChangeList* changes_applied, - syncer::SyncChangeList* changes_missing); - std::unique_ptr<leveldb_proto::ProtoDatabase<ArticleEntry>> database_; bool database_loaded_;
diff --git a/components/dom_distiller/core/dom_distiller_store_unittest.cc b/components/dom_distiller/core/dom_distiller_store_unittest.cc index ad601489..1733891 100644 --- a/components/dom_distiller/core/dom_distiller_store_unittest.cc +++ b/components/dom_distiller/core/dom_distiller_store_unittest.cc
@@ -173,59 +173,4 @@ EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model)); } -TEST_F(DomDistillerStoreTest, TestAddAndRemoveEntry) { - CreateStore(); - fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); - fake_db_->LoadCallback(true); - - EXPECT_TRUE(store_->GetEntries().empty()); - EXPECT_TRUE(db_model_.empty()); - - store_->AddEntry(GetSampleEntry(0)); - - EntryMap expected_model; - AddEntry(GetSampleEntry(0), &expected_model); - - EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model)); - EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model)); - - store_->RemoveEntry(GetSampleEntry(0)); - expected_model.clear(); - - EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model)); - EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model)); -} - -TEST_F(DomDistillerStoreTest, TestAddAndUpdateEntry) { - CreateStore(); - fake_db_->InitStatusCallback(leveldb_proto::Enums::InitStatus::kOK); - fake_db_->LoadCallback(true); - - EXPECT_TRUE(store_->GetEntries().empty()); - EXPECT_TRUE(db_model_.empty()); - - store_->AddEntry(GetSampleEntry(0)); - - EntryMap expected_model; - AddEntry(GetSampleEntry(0), &expected_model); - - EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model)); - EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model)); - - EXPECT_FALSE(store_->UpdateEntry(GetSampleEntry(0))); - - ArticleEntry updated_entry(GetSampleEntry(0)); - updated_entry.set_title("updated title."); - EXPECT_TRUE(store_->UpdateEntry(updated_entry)); - expected_model.clear(); - AddEntry(updated_entry, &expected_model); - - EXPECT_TRUE(AreEntriesEqual(store_->GetEntries(), expected_model)); - EXPECT_TRUE(AreEntryMapsEqual(db_model_, expected_model)); - - store_->RemoveEntry(updated_entry); - EXPECT_FALSE(store_->UpdateEntry(updated_entry)); - EXPECT_FALSE(store_->UpdateEntry(GetSampleEntry(0))); -} - } // namespace dom_distiller
diff --git a/components/dom_distiller/core/viewer_unittest.cc b/components/dom_distiller/core/viewer_unittest.cc index 2283843..cf1c9cd6 100644 --- a/components/dom_distiller/core/viewer_unittest.cc +++ b/components/dom_distiller/core/viewer_unittest.cc
@@ -41,19 +41,8 @@ TestDomDistillerService() {} ~TestDomDistillerService() override {} - MOCK_METHOD3(AddToList, - const std::string(const GURL&, - DistillerPage*, - const ArticleAvailableCallback&)); - const std::string AddToList( - const GURL& url, - std::unique_ptr<DistillerPage> distiller_page, - const ArticleAvailableCallback& article_cb) override { - return AddToList(url, distiller_page.get(), article_cb); - } MOCK_METHOD1(HasEntry, bool(const std::string&)); MOCK_METHOD1(GetUrlForEntry, std::string(const std::string&)); - MOCK_CONST_METHOD0(GetEntries, std::vector<ArticleEntry>()); MOCK_METHOD0(ViewUrlImpl, ViewerHandle*()); std::unique_ptr<ViewerHandle> ViewUrl( ViewRequestDelegate*, @@ -68,10 +57,6 @@ const std::string&) override { return std::unique_ptr<ViewerHandle>(ViewEntryImpl()); } - MOCK_METHOD0(RemoveEntryImpl, ArticleEntry*()); - std::unique_ptr<ArticleEntry> RemoveEntry(const std::string&) override { - return std::unique_ptr<ArticleEntry>(RemoveEntryImpl()); - } std::unique_ptr<DistillerPage> CreateDefaultDistillerPage( const gfx::Size& render_view_size) override { return std::unique_ptr<DistillerPage>();
diff --git a/components/keyed_service/core/keyed_service.h b/components/keyed_service/core/keyed_service.h index ff98c9bba..f9fd7ab 100644 --- a/components/keyed_service/core/keyed_service.h +++ b/components/keyed_service/core/keyed_service.h
@@ -13,7 +13,10 @@ // Two-phase shutdown allows keyed services to have a first pass shutdown phase // where they drop references. Not all services will need this, so there's a // default implementation. Only once every service has been given a chance to -// drop references are services deleted. +// drop references are services deleted. In a service's destructor the service +// should *not* request other services from their factories via the relevant +// Context object (e.g., Profile), as the association between that Context +// object and its keyed services is dropped after the shutdown phase. class KEYED_SERVICE_EXPORT KeyedService { public: KeyedService();
diff --git a/components/password_manager/core/browser/browser_save_password_progress_logger.cc b/components/password_manager/core/browser/browser_save_password_progress_logger.cc index 27ee2f2..211ed83 100644 --- a/components/password_manager/core/browser/browser_save_password_progress_logger.cc +++ b/components/password_manager/core/browser/browser_save_password_progress_logger.cc
@@ -33,8 +33,9 @@ // Replaces all non-digits in |str| by spaces. std::string ScrubNonDigit(std::string str) { - std::replace_if(str.begin(), str.end(), - [](char c) { return !base::IsAsciiDigit(c); }, ' '); + std::replace_if( + str.begin(), str.end(), [](char c) { return !base::IsAsciiDigit(c); }, + ' '); return str; } @@ -146,16 +147,6 @@ STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_LOWERCASE, attribute_value); break; - case PasswordAttribute::kHasUppercaseLetter: - message += BinaryPasswordAttributeLogString( - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_UPPERCASE, attribute_value); - break; - - case PasswordAttribute::kHasNumeric: - message += BinaryPasswordAttributeLogString( - STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_NUMERICS, attribute_value); - break; - case PasswordAttribute::kHasSpecialSymbol: message += BinaryPasswordAttributeLogString( STRING_PASSWORD_REQUIREMENTS_VOTE_FOR_SPECIAL_SYMBOL,
diff --git a/components/password_manager/core/browser/leak_detection_delegate.cc b/components/password_manager/core/browser/leak_detection_delegate.cc index 7cb4a0cf..36de9f6 100644 --- a/components/password_manager/core/browser/leak_detection_delegate.cc +++ b/components/password_manager/core/browser/leak_detection_delegate.cc
@@ -11,9 +11,11 @@ #include "components/password_manager/core/browser/leak_detection/leak_detection_check_factory_impl.h" #include "components/password_manager/core/browser/leak_detection_delegate_helper.h" #include "components/password_manager/core/browser/leak_detection_dialog_utils.h" +#include "components/password_manager/core/browser/leaked_credentials_table.h" #include "components/password_manager/core/browser/password_feature_manager.h" #include "components/password_manager/core/browser/password_manager_client.h" #include "components/password_manager/core/browser/password_manager_util.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_service.h" #include "services/network/public/cpp/shared_url_loader_factory.h" @@ -58,10 +60,24 @@ BrowserSavePasswordProgressLogger logger(client_->GetLogManager()); logger.LogBoolean(Logger::STRING_LEAK_DETECTION_FINISHED, is_leaked); } + + password_manager::PasswordStore* password_store = + client_->GetProfilePasswordStore(); + if (base::FeatureList::IsEnabled(password_manager::features::kLeakHistory)) { + if (is_leaked) { + password_store->AddLeakedCredentials( + LeakedCredentials(url, username, base::Time::Now())); + } else { + // If the credentials are not saved as leaked in the database, this call + // will just get ignored. + password_store->RemoveLeakedCredentials(url, username); + } + } + if (is_leaked) { if (!client_->GetPasswordFeatureManager() ->ShouldCheckReuseOnLeakDetection()) { - // If we should not check leaked password reuse, then the + // If leaked password reuse should not be checked, then the // |CredentialLeakType| needed to show the correct notification is already // determined. OnShowLeakDetectionNotification( @@ -73,9 +89,8 @@ helper_ = std::make_unique<LeakDetectionDelegateHelper>(base::BindOnce( &LeakDetectionDelegate::OnShowLeakDetectionNotification, base::Unretained(this))); - helper_->GetCredentialLeakType(client_->GetProfilePasswordStore(), - std::move(url), std::move(username), - std::move(password)); + helper_->GetCredentialLeakType(password_store, std::move(url), + std::move(username), std::move(password)); } } }
diff --git a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc index 274df3d..fd47b138 100644 --- a/components/password_manager/core/browser/leak_detection_delegate_unittest.cc +++ b/components/password_manager/core/browser/leak_detection_delegate_unittest.cc
@@ -8,8 +8,12 @@ #include "base/strings/utf_string_conversions.h" #include "base/test/metrics/histogram_tester.h" +#include "base/test/scoped_feature_list.h" +#include "base/test/task_environment.h" #include "components/password_manager/core/browser/leak_detection/leak_detection_check.h" +#include "components/password_manager/core/browser/mock_password_store.h" #include "components/password_manager/core/browser/stub_password_manager_client.h" +#include "components/password_manager/core/common/password_manager_features.h" #include "components/password_manager/core/common/password_manager_pref_names.h" #include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_service.h" @@ -45,6 +49,7 @@ MOCK_CONST_METHOD0(GetPrefs, PrefService*()); MOCK_METHOD2(NotifyUserCredentialsWereLeaked, void(password_manager::CredentialLeakType, const GURL&)); + MOCK_CONST_METHOD0(GetProfilePasswordStore, PasswordStore*()); }; class MockLeakDetectionCheck : public LeakDetectionCheck { @@ -65,29 +70,37 @@ class LeakDetectionDelegateTest : public testing::Test { public: - LeakDetectionDelegateTest() : delegate_(&client_) { + LeakDetectionDelegateTest() { + mock_store_->Init(syncer::SyncableService::StartSyncFlare(), nullptr); auto mock_factory = std::make_unique<testing::StrictMock<MockLeakDetectionCheckFactory>>(); mock_factory_ = mock_factory.get(); delegate_.set_leak_factory(std::move(mock_factory)); - prefs_ = std::make_unique<TestingPrefServiceSimple>(); - prefs_->registry()->RegisterBooleanPref( + pref_service_->registry()->RegisterBooleanPref( password_manager::prefs::kPasswordLeakDetectionEnabled, true); - ON_CALL(client_, GetPrefs()).WillByDefault(Return(prefs_.get())); + ON_CALL(client_, GetPrefs()).WillByDefault(Return(pref_service())); } - ~LeakDetectionDelegateTest() override = default; + + ~LeakDetectionDelegateTest() override { mock_store_->ShutdownOnUIThread(); } MockPasswordManagerClient& client() { return client_; } MockLeakDetectionCheckFactory& factory() { return *mock_factory_; } LeakDetectionDelegate& delegate() { return delegate_; } + MockPasswordStore* store() { return mock_store_.get(); } + PrefService* pref_service() { return pref_service_.get(); } - protected: - std::unique_ptr<TestingPrefServiceSimple> prefs_; + void WaitForPasswordStore() { task_environment_.RunUntilIdle(); } private: + base::test::TaskEnvironment task_environment_{ + base::test::TaskEnvironment::TimeSource::MOCK_TIME}; testing::NiceMock<MockPasswordManagerClient> client_; MockLeakDetectionCheckFactory* mock_factory_ = nullptr; - LeakDetectionDelegate delegate_; + scoped_refptr<MockPasswordStore> mock_store_ = + base::MakeRefCounted<testing::StrictMock<MockPasswordStore>>(); + LeakDetectionDelegate delegate_{&client_}; + std::unique_ptr<TestingPrefServiceSimple> pref_service_ = + std::make_unique<TestingPrefServiceSimple>(); }; TEST_F(LeakDetectionDelegateTest, InIncognito) { @@ -101,8 +114,8 @@ TEST_F(LeakDetectionDelegateTest, PrefIsFalse) { const autofill::PasswordForm form = CreateTestForm(); - prefs_->SetBoolean(password_manager::prefs::kPasswordLeakDetectionEnabled, - false); + pref_service()->SetBoolean( + password_manager::prefs::kPasswordLeakDetectionEnabled, false); EXPECT_CALL(factory(), TryCreateLeakCheck).Times(0); delegate().StartLeakCheck(form); @@ -133,7 +146,7 @@ EXPECT_TRUE(delegate().leak_check()); } -TEST_F(LeakDetectionDelegateTest, LeakDetectionDone) { +TEST_F(LeakDetectionDelegateTest, LeakDetectionDoneWithFalseResult) { base::HistogramTester histogram_tester; LeakDetectionDelegateInterface* delegate_interface = &delegate(); const autofill::PasswordForm form = CreateTestForm(); @@ -144,9 +157,20 @@ EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked).Times(0); delegate_interface->OnLeakDetectionDone( - false, form.origin, form.username_value, form.password_value); + /*is_leaked=*/false, form.origin, form.username_value, + form.password_value); histogram_tester.ExpectTotalCount( "PasswordManager.LeakDetection.NotifyIsLeakedTime", 0); +} + +TEST_F(LeakDetectionDelegateTest, LeakDetectionDoneWithTrueResult) { + base::HistogramTester histogram_tester; + LeakDetectionDelegateInterface* delegate_interface = &delegate(); + const autofill::PasswordForm form = CreateTestForm(); + + EXPECT_CALL(factory(), TryCreateLeakCheck) + .WillOnce(Return(ByMove(std::make_unique<MockLeakDetectionCheck>()))); + delegate().StartLeakCheck(form); EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked( @@ -154,9 +178,55 @@ IsSaved(false), IsReused(false), IsSyncing(false)), form.origin)); delegate_interface->OnLeakDetectionDone( - true, form.origin, form.username_value, form.password_value); + /*is_leaked=*/true, form.origin, form.username_value, + form.password_value); histogram_tester.ExpectTotalCount( "PasswordManager.LeakDetection.NotifyIsLeakedTime", 1); } +TEST_F(LeakDetectionDelegateTest, LeakHistoryRemoveCredentials) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kLeakHistory); + LeakDetectionDelegateInterface* delegate_interface = &delegate(); + const autofill::PasswordForm form = CreateTestForm(); + + EXPECT_CALL(client(), GetProfilePasswordStore()) + .WillRepeatedly(testing::Return(store())); + EXPECT_CALL(factory(), TryCreateLeakCheck) + .WillOnce(Return(ByMove(std::make_unique<MockLeakDetectionCheck>()))); + delegate().StartLeakCheck(form); + + EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked).Times(0); + delegate_interface->OnLeakDetectionDone( + /*is_leaked=*/false, form.origin, form.username_value, + form.password_value); + + EXPECT_CALL(*store(), + RemoveLeakedCredentialsImpl(form.origin, form.username_value)); + WaitForPasswordStore(); +} + +TEST_F(LeakDetectionDelegateTest, LeakHistoryAddCredentials) { + base::test::ScopedFeatureList scoped_feature_list; + scoped_feature_list.InitAndEnableFeature(features::kLeakHistory); + LeakDetectionDelegateInterface* delegate_interface = &delegate(); + const autofill::PasswordForm form = CreateTestForm(); + + EXPECT_CALL(client(), GetProfilePasswordStore()) + .WillRepeatedly(testing::Return(store())); + EXPECT_CALL(factory(), TryCreateLeakCheck) + .WillOnce(Return(ByMove(std::make_unique<MockLeakDetectionCheck>()))); + delegate().StartLeakCheck(form); + + EXPECT_CALL(client(), NotifyUserCredentialsWereLeaked(_, form.origin)); + delegate_interface->OnLeakDetectionDone( + /*is_leaked=*/true, form.origin, form.username_value, + form.password_value); + + const LeakedCredentials leaked_credentials(form.origin, form.username_value, + base::Time::Now()); + EXPECT_CALL(*store(), AddLeakedCredentialsImpl(leaked_credentials)); + WaitForPasswordStore(); +} + } // namespace password_manager
diff --git a/components/password_manager/core/browser/leaked_credentials_table.cc b/components/password_manager/core/browser/leaked_credentials_table.cc index f16a94e..0506fbf9 100644 --- a/components/password_manager/core/browser/leaked_credentials_table.cc +++ b/components/password_manager/core/browser/leaked_credentials_table.cc
@@ -41,14 +41,15 @@ std::vector<LeakedCredentials> StatementToLeakedCredentials(sql::Statement* s) { std::vector<LeakedCredentials> results; while (s->Step()) { - results.push_back(LeakedCredentials()); - results.back().url = GURL( + GURL url( s->ColumnString(GetColumnNumber(LeakedCredentialsTableColumn::kUrl))); - results.back().username = s->ColumnString16( + base::string16 username = s->ColumnString16( GetColumnNumber(LeakedCredentialsTableColumn::kUsername)); - results.back().create_time = base::Time::FromDeltaSinceWindowsEpoch( + base::Time create_time = base::Time::FromDeltaSinceWindowsEpoch( (base::TimeDelta::FromMicroseconds(s->ColumnInt64( GetColumnNumber(LeakedCredentialsTableColumn::kCreateTime))))); + results.push_back( + LeakedCredentials(std::move(url), std::move(username), create_time)); } return results; }
diff --git a/components/password_manager/core/browser/leaked_credentials_table.h b/components/password_manager/core/browser/leaked_credentials_table.h index b476ad77..1e6cc81 100644 --- a/components/password_manager/core/browser/leaked_credentials_table.h +++ b/components/password_manager/core/browser/leaked_credentials_table.h
@@ -16,9 +16,12 @@ namespace password_manager { // Represents information about the particular credentials leak. -// TODO(crbug.com/1005746): Discuss the design whether we should have additional -// |update_time| field or store multiple records with different |create_time|. struct LeakedCredentials { + LeakedCredentials(GURL url, base::string16 username, base::Time create_time) + : url(std::move(url)), + username(std::move(username)), + create_time(create_time) {} + // The url of the website of the leak. GURL url; // The value of the leaked username.
diff --git a/components/password_manager/core/browser/leaked_credentials_table_unittest.cc b/components/password_manager/core/browser/leaked_credentials_table_unittest.cc index acfb4a2..65ecb9b 100644 --- a/components/password_manager/core/browser/leaked_credentials_table_unittest.cc +++ b/components/password_manager/core/browser/leaked_credentials_table_unittest.cc
@@ -26,10 +26,6 @@ void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); ReloadDatabase(); - - test_data_.url = GURL(kTestDomain); - test_data_.username = base::ASCIIToUTF16(kUsername); - test_data_.create_time = base::Time::FromTimeT(1); } void ReloadDatabase() { @@ -49,7 +45,8 @@ base::ScopedTempDir temp_dir_; std::unique_ptr<sql::Database> connection_; std::unique_ptr<LeakedCredentialsTable> db_; - LeakedCredentials test_data_; + LeakedCredentials test_data_{GURL(kTestDomain), base::ASCIIToUTF16(kUsername), + base::Time::FromTimeT(1)}; }; TEST_F(LeakedCredentialsTableTest, Sanity) {
diff --git a/components/password_manager/core/browser/password_store_unittest.cc b/components/password_manager/core/browser/password_store_unittest.cc index dbfe3d331..26807ac 100644 --- a/components/password_manager/core/browser/password_store_unittest.cc +++ b/components/password_manager/core/browser/password_store_unittest.cc
@@ -1248,15 +1248,12 @@ } TEST_F(PasswordStoreTest, GetAllLeakedCredentials) { - LeakedCredentials leaked_credentials; - leaked_credentials.url = GURL("https://example.com"); - leaked_credentials.username = base::ASCIIToUTF16("username"); - leaked_credentials.create_time = base::Time::FromTimeT(1); - - LeakedCredentials leaked_credentials2; - leaked_credentials2.url = GURL("https://example2.com"); - leaked_credentials2.username = base::ASCIIToUTF16("username2"); - leaked_credentials2.create_time = base::Time::FromTimeT(2); + LeakedCredentials leaked_credentials(GURL("https://example.com"), + base::ASCIIToUTF16("username"), + base::Time::FromTimeT(1)); + LeakedCredentials leaked_credentials2(GURL("https://example2.com"), + base::ASCIIToUTF16("username2"), + base::Time::FromTimeT(2)); scoped_refptr<PasswordStoreDefault> store = CreatePasswordStore(); store->Init(syncer::SyncableService::StartSyncFlare(), nullptr);
diff --git a/components/password_manager/core/browser/votes_uploader.cc b/components/password_manager/core/browser/votes_uploader.cc index dbc89a6..7f7158fb 100644 --- a/components/password_manager/core/browser/votes_uploader.cc +++ b/components/password_manager/core/browser/votes_uploader.cc
@@ -102,8 +102,9 @@ } auto vote_type_iter = vote_types.find(field->name); - if (vote_type_iter != vote_types.end()) + if (vote_type_iter != vote_types.end()) { field->set_vote_type(vote_type_iter->second); + } DCHECK(type != autofill::USERNAME || field->vote_type() != AutofillUploadContents::Field::NO_INFORMATION); @@ -182,8 +183,9 @@ const std::map<base::string16, const PasswordForm*>& best_matches, PasswordForm* pending_credentials) { if (pending_credentials->times_used == 1 || - IsAddingUsernameToExistingMatch(*pending_credentials, best_matches)) + IsAddingUsernameToExistingMatch(*pending_credentials, best_matches)) { UploadFirstLoginVotes(best_matches, *pending_credentials, submitted_form); + } // Upload credentials the first time they are saved. This data is used // by password generation to help determine account creation sites. @@ -534,8 +536,9 @@ return false; for (const PasswordForm* match : matches) { if ((match->password_value == password) && - FindUsernameInOtherPossibleUsernames(*match, username)) + FindUsernameInOtherPossibleUsernames(*match, username)) { return true; + } } return false; } @@ -544,30 +547,25 @@ const base::string16& password_value, FormStructure* form_structure) { // Don't crowdsource password attributes for non-ascii passwords. - for (const auto& e : password_value) + for (const auto& e : password_value) { if (!(IsUppercaseLetter(e) || IsLowercaseLetter(e) || IsNumeric(e) || - IsSpecialSymbol(e))) + IsSpecialSymbol(e))) { return; + } + } - // Select a character class attribute to upload. - int bucket = base::RandGenerator(9); + // Select a character class attribute to upload. Upload special symbols more + // often (8 in 9 cases) as most issues are due to missing or wrong special + // symbols. Don't upload info about uppercase and numeric characters as all + // sites that allow lowercase letters also uppercase letters, and all sites + // allow numeric symbols in passwords. + autofill::PasswordAttribute character_class_attribute; bool (*predicate)(int c) = nullptr; - autofill::PasswordAttribute character_class_attribute = - autofill::PasswordAttribute::kHasSpecialSymbol; - if (bucket == 0) { + if (base::RandGenerator(9) == 0) { predicate = &IsLowercaseLetter; character_class_attribute = autofill::PasswordAttribute::kHasLowercaseLetter; - } else if (bucket == 1) { - predicate = &IsUppercaseLetter; - character_class_attribute = - autofill::PasswordAttribute::kHasUppercaseLetter; - } else if (bucket == 2) { - predicate = &IsNumeric; - character_class_attribute = autofill::PasswordAttribute::kHasNumeric; - } else { // 3 <= bucket < 9 - // Upload symbols more often as 2/3rd of issues are because of missing - // special symbols. + } else { predicate = &IsSpecialSymbol; character_class_attribute = autofill::PasswordAttribute::kHasSpecialSymbol; } @@ -601,9 +599,10 @@ void VotesUploader::StoreInitialFieldValues( const autofill::FormData& observed_form) { for (const auto& field : observed_form.fields) { - if (!field.value.empty()) + if (!field.value.empty()) { initial_values_.insert( std::make_pair(field.unique_renderer_id, field.value)); + } } }
diff --git a/components/password_manager/core/browser/votes_uploader_unittest.cc b/components/password_manager/core/browser/votes_uploader_unittest.cc index ed3742d..bfb3b03 100644 --- a/components/password_manager/core/browser/votes_uploader_unittest.cc +++ b/components/password_manager/core/browser/votes_uploader_unittest.cc
@@ -220,9 +220,9 @@ TEST_F(VotesUploaderTest, GeneratePasswordAttributesVote) { VotesUploader votes_uploader(&client_, true); // Checks that randomization distorts information about present and missed - // character classess, but a true value is still restorable with aggregation + // character classes, but a true value is still restorable with aggregation // of many distorted reports. - const char* kPasswordSnippets[] = {"abc", "XYZ", "123", "*-_"}; + const char* kPasswordSnippets[kNumberOfPasswordAttributes] = {"abc", "*-_"}; for (int test_case = 0; test_case < 10; ++test_case) { bool has_password_attribute[kNumberOfPasswordAttributes]; base::string16 password_value; @@ -236,8 +236,8 @@ FormData form; FormStructure form_structure(form); - int reported_false[kNumberOfPasswordAttributes] = {0, 0, 0, 0}; - int reported_true[kNumberOfPasswordAttributes] = {0, 0, 0, 0}; + int reported_false[kNumberOfPasswordAttributes] = {0, 0}; + int reported_true[kNumberOfPasswordAttributes] = {0, 0}; int reported_actual_length = 0; int reported_wrong_length = 0; @@ -290,7 +290,8 @@ const base::string16 password_value = ASCIIToUTF16("password-withsymbols!"); const int kNumberOfRuns = 2000; - const int kSpecialSymbolsAttribute = 3; + const int kSpecialSymbolsAttribute = + static_cast<int>(PasswordAttribute::kHasSpecialSymbol); FormData form;
diff --git a/components/policy/core/common/cloud/enterprise_metrics.cc b/components/policy/core/common/cloud/enterprise_metrics.cc index 83e1f1c..0bf4caee 100644 --- a/components/policy/core/common/cloud/enterprise_metrics.cc +++ b/components/policy/core/common/cloud/enterprise_metrics.cc
@@ -6,11 +6,11 @@ namespace policy { -const char kMetricUserPolicyRefresh[] = "Enterprise.PolicyRefresh"; +const char kMetricUserPolicyRefresh[] = "Enterprise.PolicyRefresh2"; const char kMetricUserPolicyRefreshFcm[] = - "Enterprise.FCMInvalidationService.PolicyRefresh"; + "Enterprise.FCMInvalidationService.PolicyRefresh2"; const char kMetricUserPolicyRefreshTicl[] = - "Enterprise.TiclInvalidationService.PolicyRefresh"; + "Enterprise.TiclInvalidationService.PolicyRefresh2"; const char kMetricUserPolicyInvalidations[] = "Enterprise.PolicyInvalidations"; const char kMetricUserPolicyInvalidationsFcm[] = @@ -21,11 +21,11 @@ const char kMetricUserPolicyChromeOSSessionAbort[] = "Enterprise.UserPolicyChromeOS.SessionAbort"; -const char kMetricDevicePolicyRefresh[] = "Enterprise.DevicePolicyRefresh"; +const char kMetricDevicePolicyRefresh[] = "Enterprise.DevicePolicyRefresh2"; const char kMetricDevicePolicyRefreshFcm[] = - "Enterprise.FCMInvalidationService.DevicePolicyRefresh"; + "Enterprise.FCMInvalidationService.DevicePolicyRefresh2"; const char kMetricDevicePolicyRefreshTicl[] = - "Enterprise.TiclInvalidationService.DevicePolicyRefresh"; + "Enterprise.TiclInvalidationService.DevicePolicyRefresh2"; const char kMetricDevicePolicyInvalidations[] = "Enterprise.DevicePolicyInvalidations";
diff --git a/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc b/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc index 53a449685..f388596b 100644 --- a/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc +++ b/components/safe_browsing/triggers/ad_popup_trigger_unittest.cc
@@ -8,6 +8,7 @@ #include "base/test/metrics/histogram_tester.h" #include "base/test/scoped_feature_list.h" #include "base/test/test_simple_task_runner.h" +#include "build/build_config.h" #include "components/prefs/testing_pref_service.h" #include "components/safe_browsing/features.h" #include "components/safe_browsing/triggers/mock_trigger_manager.h" @@ -138,7 +139,14 @@ 1); } -TEST_F(AdPopupTriggerTest, ReportRejectedByTriggerManager) { +// TODO(https://crbug.com/1009917): Fix flakes on Windows bots. +#if defined(OS_WIN) +#define MAYBE_ReportRejectedByTriggerManager \ + DISABLED_ReportRejectedByTriggerManager +#else +#define MAYBE_ReportRejectedByTriggerManager ReportRejectedByTriggerManager +#endif +TEST_F(AdPopupTriggerTest, MAYBE_ReportRejectedByTriggerManager) { // If the trigger manager rejects the report, we don't try to finish/send the // report. CreateTrigger();
diff --git a/components/signin/core/browser/account_reconcilor.cc b/components/signin/core/browser/account_reconcilor.cc index 638d3e07..ad4c5b3 100644 --- a/components/signin/core/browser/account_reconcilor.cc +++ b/components/signin/core/browser/account_reconcilor.cc
@@ -713,14 +713,14 @@ std::vector<CoreAccountId> chrome_account_ids; - // Remove any accounts that have an error. There is no point in trying to - // reconcile them, since it won't work anyway. If the list ends up being + // Remove any accounts that have an error. There is no point in trying to + // reconcile them, since it won't work anyway. If the list ends up being // empty then don't reconcile any accounts. for (const auto& chrome_account_with_refresh_tokens : chrome_accounts_with_refresh_tokens) { if (identity_manager_->HasAccountWithRefreshTokenInPersistentErrorState( chrome_account_with_refresh_tokens.account_id)) { - VLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: " + VLOG(1) << "AccountReconcilor::LoadValidAccountsFromTokenService: " << chrome_account_with_refresh_tokens.account_id << " has error, don't reconcile"; continue; @@ -728,7 +728,7 @@ chrome_account_ids.push_back(chrome_account_with_refresh_tokens.account_id); } - VLOG(1) << "AccountReconcilor::ValidateAccountsFromTokenService: " + VLOG(1) << "AccountReconcilor::LoadValidAccountsFromTokenService: " << "Chrome " << chrome_account_ids.size() << " accounts"; return chrome_account_ids;
diff --git a/components/signin/internal/identity_manager/account_fetcher_service.cc b/components/signin/internal/identity_manager/account_fetcher_service.cc index 97889b9..f4e6679 100644 --- a/components/signin/internal/identity_manager/account_fetcher_service.cc +++ b/components/signin/internal/identity_manager/account_fetcher_service.cc
@@ -50,7 +50,7 @@ const char AccountFetcherService::kLastUpdatePref[] = "account_tracker_service_last_update"; -const int AccountFetcherService::kAccountImageDownloadSize = 64; +const int AccountFetcherService::kAccountImageDownloadSize = 256; // AccountFetcherService implementation AccountFetcherService::AccountFetcherService() = default;
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn index 0d8f76fa..9cb304c 100644 --- a/content/browser/BUILD.gn +++ b/content/browser/BUILD.gn
@@ -1853,6 +1853,8 @@ "web_contents/web_drag_utils_win.h", "web_package/bundled_exchanges_handle.cc", "web_package/bundled_exchanges_handle.h", + "web_package/bundled_exchanges_handle_tracker.cc", + "web_package/bundled_exchanges_handle_tracker.h", "web_package/bundled_exchanges_reader.cc", "web_package/bundled_exchanges_reader.h", "web_package/bundled_exchanges_source.cc",
diff --git a/content/browser/frame_host/navigation_request.cc b/content/browser/frame_host/navigation_request.cc index 9267e74..c405994 100644 --- a/content/browser/frame_host/navigation_request.cc +++ b/content/browser/frame_host/navigation_request.cc
@@ -49,6 +49,7 @@ #include "content/browser/service_worker/service_worker_context_wrapper.h" #include "content/browser/service_worker/service_worker_navigation_handle.h" #include "content/browser/site_instance_impl.h" +#include "content/browser/web_package/bundled_exchanges_handle_tracker.h" #include "content/browser/web_package/bundled_exchanges_source.h" #include "content/browser/web_package/bundled_exchanges_utils.h" #include "content/browser/web_package/prefetched_signed_exchange_cache.h" @@ -688,7 +689,9 @@ mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client, mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache) { + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker) { // Only normal navigations to a different document or reloads are expected. // - Renderer-initiated same document navigations never start in the browser. // - Restore-navigations are always browser-initiated. @@ -750,6 +753,8 @@ std::move(blob_url_loader_factory); navigation_request->prefetched_signed_exchange_cache_ = std::move(prefetched_signed_exchange_cache); + navigation_request->bundled_exchanges_handle_tracker_ = + std::move(bundled_exchanges_handle_tracker); return navigation_request; } @@ -1984,19 +1989,29 @@ } // Initialize the BundledExchangesHandle. - if (bundled_exchanges_utils::CanLoadAsTrustableBundledExchangesFile( - common_params_->url)) { - auto source = BundledExchangesSource::MaybeCreateFromTrustedFileUrl( - common_params_->url); - // MaybeCreateFromTrustedFileUrl() returns null when the url contains an - // invalid character. - if (source) { - bundled_exchanges_handle_ = - BundledExchangesHandle::CreateForTrustableFile(std::move(source)); + if (bundled_exchanges_handle_tracker_) { + DCHECK(base::FeatureList::IsEnabled(features::kBundledHTTPExchanges) || + base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kTrustableBundledExchangesFileUrl)); + bundled_exchanges_handle_ = + bundled_exchanges_handle_tracker_->MaybeCreateBundledExchangesHandle( + common_params_->url); + } + if (!bundled_exchanges_handle_) { + if (bundled_exchanges_utils::CanLoadAsTrustableBundledExchangesFile( + common_params_->url)) { + auto source = BundledExchangesSource::MaybeCreateFromTrustedFileUrl( + common_params_->url); + // MaybeCreateFromTrustedFileUrl() returns null when the url contains an + // invalid character. + if (source) { + bundled_exchanges_handle_ = + BundledExchangesHandle::CreateForTrustableFile(std::move(source)); + } + } else if (bundled_exchanges_utils::CanLoadAsBundledExchangesFile( + common_params_->url)) { + bundled_exchanges_handle_ = BundledExchangesHandle::CreateForFile(); } - } else if (bundled_exchanges_utils::CanLoadAsBundledExchangesFile( - common_params_->url)) { - bundled_exchanges_handle_ = BundledExchangesHandle::CreateForFile(); } // Mark the fetch_start (Navigation Timing API).
diff --git a/content/browser/frame_host/navigation_request.h b/content/browser/frame_host/navigation_request.h index 36f80c02..9acef58 100644 --- a/content/browser/frame_host/navigation_request.h +++ b/content/browser/frame_host/navigation_request.h
@@ -54,6 +54,7 @@ namespace content { class AppCacheNavigationHandle; +class BundledExchangesHandleTracker; class FrameNavigationEntry; class FrameTreeNode; class NavigationHandleImpl; @@ -164,7 +165,9 @@ mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache); + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker); // Creates a request at commit time. This should only be used for // renderer-initiated same-document navigations, and navigations whose @@ -992,6 +995,12 @@ scoped_refptr<PrefetchedSignedExchangeCache> prefetched_signed_exchange_cache_; + // Tracks navigations within bundled exchanges file. Used when + // BundledHTTPExchanges feature is enabled or + // TrustableBundledExchangesFileUrl switch is set. + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker_; + // The time this navigation was ready to commit. base::TimeTicks ready_to_commit_time_;
diff --git a/content/browser/frame_host/navigator.cc b/content/browser/frame_host/navigator.cc index d16c21b..a2805dc 100644 --- a/content/browser/frame_host/navigator.cc +++ b/content/browser/frame_host/navigator.cc
@@ -5,6 +5,7 @@ #include "content/browser/frame_host/navigator.h" #include "base/time/time.h" +#include "content/browser/web_package/bundled_exchanges_handle_tracker.h" #include "content/browser/web_package/prefetched_signed_exchange_cache.h" namespace content { @@ -35,6 +36,8 @@ mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client, mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache) {} + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker) {} } // namespace content
diff --git a/content/browser/frame_host/navigator.h b/content/browser/frame_host/navigator.h index 73c75d2..ac97c76 100644 --- a/content/browser/frame_host/navigator.h +++ b/content/browser/frame_host/navigator.h
@@ -31,6 +31,7 @@ namespace content { +class BundledExchangesHandleTracker; class FrameNavigationEntry; class FrameTreeNode; class PrefetchedSignedExchangeCache; @@ -156,7 +157,9 @@ mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache); + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker); // Used to restart a navigation that was thought to be same-document in // cross-document mode.
diff --git a/content/browser/frame_host/navigator_impl.cc b/content/browser/frame_host/navigator_impl.cc index b8ff600c..10f4611 100644 --- a/content/browser/frame_host/navigator_impl.cc +++ b/content/browser/frame_host/navigator_impl.cc
@@ -23,6 +23,7 @@ #include "content/browser/frame_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_impl.h" #include "content/browser/site_instance_impl.h" +#include "content/browser/web_package/bundled_exchanges_handle_tracker.h" #include "content/browser/web_package/prefetched_signed_exchange_cache.h" #include "content/browser/webui/web_ui_controller_factory_registry.h" #include "content/browser/webui/web_ui_impl.h" @@ -620,7 +621,9 @@ mojo::PendingAssociatedRemote<mojom::NavigationClient> navigation_client, mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache) { + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker) { // TODO(clamy): the url sent by the renderer should be validated with // FilterURL. // This is a renderer-initiated navigation. @@ -683,7 +686,8 @@ controller_->GetEntryCount(), override_user_agent, std::move(blob_url_loader_factory), std::move(navigation_client), std::move(navigation_initiator), - std::move(prefetched_signed_exchange_cache))); + std::move(prefetched_signed_exchange_cache), + std::move(bundled_exchanges_handle_tracker))); NavigationRequest* navigation_request = frame_tree_node->navigation_request(); // This frame has already run beforeunload before it sent this IPC. See if
diff --git a/content/browser/frame_host/navigator_impl.h b/content/browser/frame_host/navigator_impl.h index d95b4af..697bb98 100644 --- a/content/browser/frame_host/navigator_impl.h +++ b/content/browser/frame_host/navigator_impl.h
@@ -102,7 +102,9 @@ mojo::PendingRemote<blink::mojom::NavigationInitiator> navigation_initiator, scoped_refptr<PrefetchedSignedExchangeCache> - prefetched_signed_exchange_cache) override; + prefetched_signed_exchange_cache, + std::unique_ptr<BundledExchangesHandleTracker> + bundled_exchanges_handle_tracker) override; void RestartNavigationAsCrossDocument( std::unique_ptr<NavigationRequest> navigation_request) override; void OnAbortNavigation(FrameTreeNode* frame_tree_node) override;
diff --git a/content/browser/frame_host/render_frame_host_impl.cc b/content/browser/frame_host/render_frame_host_impl.cc index 9d13a8e3..fec2898 100644 --- a/content/browser/frame_host/render_frame_host_impl.cc +++ b/content/browser/frame_host/render_frame_host_impl.cc
@@ -104,6 +104,7 @@ #include "content/browser/speech/speech_synthesis_impl.h" #include "content/browser/storage_partition_impl.h" #include "content/browser/web_package/bundled_exchanges_handle.h" +#include "content/browser/web_package/bundled_exchanges_handle_tracker.h" #include "content/browser/web_package/prefetched_signed_exchange_cache.h" #include "content/browser/webauth/authenticator_environment_impl.h" #include "content/browser/webauth/authenticator_impl.h" @@ -2029,7 +2030,10 @@ std::move(pending_navigate_->blob_url_loader_factory), std::move(pending_navigate_->navigation_client), std::move(pending_navigate_->navigation_initiator), - EnsurePrefetchedSignedExchangeCache()); + EnsurePrefetchedSignedExchangeCache(), + bundled_exchanges_handle_ + ? bundled_exchanges_handle_->MaybeCreateTracker() + : nullptr); pending_navigate_.reset(); } } @@ -4287,7 +4291,10 @@ frame_tree_node()->navigator()->OnBeginNavigation( frame_tree_node(), std::move(validated_params), std::move(begin_params), std::move(blob_url_loader_factory), std::move(navigation_client), - std::move(navigation_initiator), EnsurePrefetchedSignedExchangeCache()); + std::move(navigation_initiator), EnsurePrefetchedSignedExchangeCache(), + bundled_exchanges_handle_ + ? bundled_exchanges_handle_->MaybeCreateTracker() + : nullptr); } void RenderFrameHostImpl::SubresourceResponseStarted(
diff --git a/content/browser/loader/navigation_loader_interceptor.cc b/content/browser/loader/navigation_loader_interceptor.cc index d2a4b810..b3ab463 100644 --- a/content/browser/loader/navigation_loader_interceptor.cc +++ b/content/browser/loader/navigation_loader_interceptor.cc
@@ -25,4 +25,8 @@ return false; } +bool NavigationLoaderInterceptor::ShouldBypassRedirectChecks() { + return false; +} + } // namespace content
diff --git a/content/browser/loader/navigation_loader_interceptor.h b/content/browser/loader/navigation_loader_interceptor.h index 5796a05..ad204af6 100644 --- a/content/browser/loader/navigation_loader_interceptor.h +++ b/content/browser/loader/navigation_loader_interceptor.h
@@ -120,6 +120,11 @@ ThrottlingURLLoader* url_loader, bool* skip_other_interceptors, bool* will_return_unsafe_redirect); + + // Called when MaybeCreateLoader() has called the LoaderCallback with a valid + // RequestHandler. Returns true when this interceptor will return an unsafe + // redirect response and will handle the redirected request. + virtual bool ShouldBypassRedirectChecks(); }; } // namespace content
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc index e40a0b3..1623add 100644 --- a/content/browser/loader/navigation_url_loader_impl.cc +++ b/content/browser/loader/navigation_url_loader_impl.cc
@@ -564,7 +564,8 @@ subresource_loader_params_ = interceptor->MaybeCreateSubresourceLoaderParams(); - + if (interceptor->ShouldBypassRedirectChecks()) + bypass_redirect_checks_ = true; return; }
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc index 1c3113a..af11627 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc +++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.cc
@@ -504,14 +504,18 @@ base::SequencedTaskRunnerHandle::Get(), std::move(callback)); } -void DWriteFontProxyImpl::FallbackFamilyNameForCodepoint( +void DWriteFontProxyImpl::FallbackFamilyAndStyleForCodepoint( const std::string& base_family_name, const std::string& locale_name, uint32_t codepoint, - FallbackFamilyNameForCodepointCallback callback) { + FallbackFamilyAndStyleForCodepointCallback callback) { InitializeDirectWrite(); - callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun(std::move(callback), - std::string()); + callback = mojo::WrapCallbackWithDefaultInvokeIfNotRun( + std::move(callback), + blink::mojom::FallbackFamilyAndStyle::New("", + /* weight */ 0, + /* width */ 0, + /* slant */ 0)); if (!codepoint) return; @@ -532,7 +536,13 @@ SkString family_name; typeface->getFamilyName(&family_name); - std::move(callback).Run(family_name.c_str()); + + SkFontStyle font_style = typeface->fontStyle(); + + auto result_fallback_and_style = blink::mojom::FallbackFamilyAndStyle::New( + family_name.c_str(), font_style.weight(), font_style.width(), + font_style.slant()); + std::move(callback).Run(std::move(result_fallback_and_style)); } void DWriteFontProxyImpl::InitializeDirectWrite() {
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win.h b/content/browser/renderer_host/dwrite_font_proxy_impl_win.h index 5fb48d4f..09e4491 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_impl_win.h +++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win.h
@@ -66,11 +66,11 @@ void GetUniqueNameLookupTable( GetUniqueNameLookupTableCallback callback) override; - void FallbackFamilyNameForCodepoint( + void FallbackFamilyAndStyleForCodepoint( const std::string& base_family_name, const std::string& locale_name, uint32_t codepoint, - FallbackFamilyNameForCodepointCallback callback) override; + FallbackFamilyAndStyleForCodepointCallback callback) override; void InitializeDirectWrite();
diff --git a/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc b/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc index 07454c06..fa5c3fb 100644 --- a/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc +++ b/content/browser/renderer_host/dwrite_font_proxy_impl_win_unittest.cc
@@ -269,24 +269,31 @@ if (fallback_request.is_win10 && !on_win10) continue; - std::string family_name; + blink::mojom::FallbackFamilyAndStylePtr fallback_family_and_style; UChar32 codepoint; U16_GET(fallback_request.text.c_str(), 0, 0, fallback_request.text.size(), codepoint); - dwrite_font_proxy().FallbackFamilyNameForCodepoint( + dwrite_font_proxy().FallbackFamilyAndStyleForCodepoint( "Times New Roman", fallback_request.language_tag, codepoint, - &family_name); + &fallback_family_and_style); auto find_result_it = std::find(fallback_request.fallback_fonts.begin(), - fallback_request.fallback_fonts.end(), family_name); + fallback_request.fallback_fonts.end(), + fallback_family_and_style->fallback_family_name); EXPECT_TRUE(find_result_it != fallback_request.fallback_fonts.end()) << "Did not find expected fallback font for language: " << fallback_request.language_tag << ", codepoint U+" << std::hex - << codepoint << " DWrite returned font name: \"" << family_name << "\"" + << codepoint << " DWrite returned font name: \"" + << fallback_family_and_style->fallback_family_name << "\"" << ", expected: " << base::JoinString(fallback_request.fallback_fonts, ", "); + EXPECT_EQ(fallback_family_and_style->weight, 400u); + EXPECT_EQ(fallback_family_and_style->width, + 5u); // SkFontStyle::Width::kNormal_Width + EXPECT_EQ(fallback_family_and_style->slant, + 0u); // SkFontStyle::Slant::kUpright_Slant } }
diff --git a/content/browser/renderer_host/render_process_host_browsertest.cc b/content/browser/renderer_host/render_process_host_browsertest.cc index 446db60..dd04f65 100644 --- a/content/browser/renderer_host/render_process_host_browsertest.cc +++ b/content/browser/renderer_host/render_process_host_browsertest.cc
@@ -59,9 +59,13 @@ } std::unique_ptr<net::test_server::HttpResponse> HandleHungBeacon( + const base::RepeatingClosure& on_called, const net::test_server::HttpRequest& request) { if (request.relative_url != "/beacon") return nullptr; + if (on_called) { + on_called.Run(); + } return std::make_unique<net::test_server::HungResponse>(); } @@ -987,6 +991,35 @@ rph->RemoveObserver(this); } +IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, + KeepAliveRendererProcessWithServiceWorker) { + base::RunLoop run_loop; + embedded_test_server()->RegisterRequestHandler( + base::BindRepeating(HandleHungBeacon, run_loop.QuitClosure())); + ASSERT_TRUE(embedded_test_server()->Start()); + + EXPECT_TRUE(NavigateToURL( + shell(), + embedded_test_server()->GetURL("/workers/service_worker_setup.html"))); + EXPECT_EQ("ok", EvalJs(shell(), "setup();")); + + RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>( + shell()->web_contents()->GetMainFrame()->GetProcess()); + // 1 for the service worker. + EXPECT_EQ(rph->keep_alive_ref_count(), 1u); + + // We use /workers/send-beacon.html, not send-beacon.html, due to the + // service worker scope rule. + EXPECT_TRUE(NavigateToURL( + shell(), embedded_test_server()->GetURL("/workers/send-beacon.html"))); + + run_loop.Run(); + // We are still using the same process. + ASSERT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(), rph); + // 1 for the service worker, 1 for the keepalive fetch. + EXPECT_EQ(rph->keep_alive_ref_count(), 2u); +} + // Test is flaky on Android builders: https://crbug.com/875179 #if defined(OS_ANDROID) #define MAYBE_KeepAliveRendererProcess_Hung \ @@ -997,7 +1030,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, MAYBE_KeepAliveRendererProcess_Hung) { embedded_test_server()->RegisterRequestHandler( - base::BindRepeating(HandleHungBeacon)); + base::BindRepeating(HandleHungBeacon, base::RepeatingClosure())); ASSERT_TRUE(embedded_test_server()->Start()); EXPECT_TRUE(NavigateToURL( @@ -1034,7 +1067,7 @@ IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, MAYBE_FetchKeepAliveRendererProcess_Hung) { embedded_test_server()->RegisterRequestHandler( - base::BindRepeating(HandleHungBeacon)); + base::BindRepeating(HandleHungBeacon, base::RepeatingClosure())); ASSERT_TRUE(embedded_test_server()->Start()); EXPECT_TRUE(NavigateToURL(
diff --git a/content/browser/renderer_host/render_process_host_impl.h b/content/browser/renderer_host/render_process_host_impl.h index e58f6a8..6bc459b 100644 --- a/content/browser/renderer_host/render_process_host_impl.h +++ b/content/browser/renderer_host/render_process_host_impl.h
@@ -546,6 +546,8 @@ ipc_send_watcher_for_testing_ = std::move(watcher); } + size_t keep_alive_ref_count() const { return keep_alive_ref_count_; } + protected: // A proxy for our IPC::Channel that lives on the IO thread. std::unique_ptr<IPC::ChannelProxy> channel_;
diff --git a/content/browser/service_worker/service_worker_context_core.cc b/content/browser/service_worker/service_worker_context_core.cc index f0897fd..881dade 100644 --- a/content/browser/service_worker/service_worker_context_core.cc +++ b/content/browser/service_worker/service_worker_context_core.cc
@@ -661,6 +661,10 @@ void ServiceWorkerContextCore::DeleteAndStartOver(StatusCallback callback) { job_coordinator_->AbortAll(); + + observer_list_->Notify( + FROM_HERE, &ServiceWorkerContextCoreObserver::OnDeleteAndStartOver); + storage_->DeleteAndStartOver(std::move(callback)); } @@ -743,6 +747,9 @@ void ServiceWorkerContextCore::OnRunningStateChanged( ServiceWorkerVersion* version) { + if (!version->context()) + return; + observer_list_->Notify( FROM_HERE, &ServiceWorkerContextCoreObserver::OnRunningStateChanged, version->version_id(), version->running_status());
diff --git a/content/browser/service_worker/service_worker_context_core_observer.h b/content/browser/service_worker/service_worker_context_core_observer.h index 12d194da..50edd986 100644 --- a/content/browser/service_worker/service_worker_context_core_observer.h +++ b/content/browser/service_worker/service_worker_context_core_observer.h
@@ -48,6 +48,11 @@ virtual void OnNewLiveVersion(const ServiceWorkerVersionInfo& version_info) {} virtual void OnRunningStateChanged(int64_t version_id, EmbeddedWorkerStatus running_status) {} + // Called when the context core is about to be deleted. After this is called, + // method calls on this observer will be for a new context core, possibly + // reusing version/registration IDs previously seen. So this method gives the + // observer a chance to discard any state it has. + virtual void OnDeleteAndStartOver() {} virtual void OnVersionStateChanged(int64_t version_id, const GURL& scope, ServiceWorkerVersion::Status status) {}
diff --git a/content/browser/service_worker/service_worker_context_wrapper.cc b/content/browser/service_worker/service_worker_context_wrapper.cc index 2278bb9..a77719c5 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.cc +++ b/content/browser/service_worker/service_worker_context_wrapper.cc
@@ -369,6 +369,8 @@ void ServiceWorkerContextWrapper::OnRunningStateChanged( int64_t version_id, EmbeddedWorkerStatus running_status) { + DCHECK_CURRENTLY_ON(BrowserThread::UI); + // When |running_status| is RUNNING/STOPPING, the service // worker is doing some actual tasks, so we consider the service worker is // in a running status. @@ -383,7 +385,8 @@ // process of the service worker is allocated/released, instead of using the // running status of the embedded worker. if (running_status == EmbeddedWorkerStatus::RUNNING) { - running_service_workers_.emplace(version_id); + bool inserted = running_service_workers_.emplace(version_id).second; + DCHECK(inserted); for (auto& observer : observer_list_) { observer.OnVersionRunningStatusChanged(this, version_id, true /* is_running */); @@ -394,7 +397,8 @@ if (running_service_workers_.find(version_id) != running_service_workers_.end() && running_status == EmbeddedWorkerStatus::STOPPED) { - running_service_workers_.erase(version_id); + size_t removed = running_service_workers_.erase(version_id); + DCHECK_EQ(removed, 1u); for (auto& observer : observer_list_) { observer.OnVersionRunningStatusChanged(this, version_id, false /* is_running */); @@ -402,6 +406,16 @@ } } +void ServiceWorkerContextWrapper::OnDeleteAndStartOver() { + for (int version_id : running_service_workers_) { + for (auto& observer : observer_list_) { + observer.OnVersionRunningStatusChanged(this, version_id, + false /* is_running */); + } + } + running_service_workers_.clear(); +} + void ServiceWorkerContextWrapper::OnVersionStateChanged( int64_t version_id, const GURL& scope,
diff --git a/content/browser/service_worker/service_worker_context_wrapper.h b/content/browser/service_worker/service_worker_context_wrapper.h index f41db5c1..cfa6143 100644 --- a/content/browser/service_worker/service_worker_context_wrapper.h +++ b/content/browser/service_worker/service_worker_context_wrapper.h
@@ -123,6 +123,7 @@ void OnNoControllees(int64_t version_id, const GURL& scope) override; void OnRunningStateChanged(int64_t version_id, EmbeddedWorkerStatus running_status) override; + void OnDeleteAndStartOver() override; void OnVersionStateChanged(int64_t version_id, const GURL& scope, ServiceWorkerVersion::Status status) override;
diff --git a/content/browser/tracing/cros_tracing_agent.cc b/content/browser/tracing/cros_tracing_agent.cc index ed2b988..7455961 100644 --- a/content/browser/tracing/cros_tracing_agent.cc +++ b/content/browser/tracing/cros_tracing_agent.cc
@@ -16,7 +16,7 @@ #include "base/task/post_task.h" #include "base/trace_event/trace_config.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "content/public/browser/browser_task_traits.h" #include "services/service_manager/public/cpp/connector.h" #include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
diff --git a/content/browser/tracing/tracing_controller_impl.cc b/content/browser/tracing/tracing_controller_impl.cc index a1a4c59..9b0bdcb9 100644 --- a/content/browser/tracing/tracing_controller_impl.cc +++ b/content/browser/tracing/tracing_controller_impl.cc
@@ -47,7 +47,7 @@ #if defined(OS_CHROMEOS) #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/system/statistics_provider.h" #include "content/browser/tracing/cros_tracing_agent.h" #endif
diff --git a/content/browser/web_package/bundled_exchanges_browsertest.cc b/content/browser/web_package/bundled_exchanges_browsertest.cc index aff6c09f..407975c 100644 --- a/content/browser/web_package/bundled_exchanges_browsertest.cc +++ b/content/browser/web_package/bundled_exchanges_browsertest.cc
@@ -9,11 +9,13 @@ #include "base/run_loop.h" #include "base/strings/string_piece.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" #include "base/system/sys_info.h" #include "base/test/scoped_feature_list.h" #include "base/threading/thread_restrictions.h" #include "build/build_config.h" +#include "content/browser/web_package/bundled_exchanges_utils.h" #include "content/public/browser/content_browser_client.h" #include "content/public/browser/navigation_handle.h" #include "content/public/common/content_features.h" @@ -31,7 +33,13 @@ namespace { // "%2F" is treated as an invalid character for file URLs. -static constexpr char kInvalidFileUrl[] = "file:///tmp/test%2F/a.wbn"; +constexpr char kInvalidFileUrl[] = "file:///tmp/test%2F/a.wbn"; + +constexpr char kTestPageUrl[] = "https://test.example.org/"; +constexpr char kTestPage1Url[] = "https://test.example.org/page1.html"; +constexpr char kTestPage2Url[] = "https://test.example.org/page2.html"; +constexpr char kTestPageForHashUrl[] = + "https://test.example.org/hash.html#hello"; base::FilePath GetTestDataPath(base::StringPiece file) { base::FilePath test_data_dir; @@ -60,6 +68,42 @@ } #endif // OS_ANDROID +class BundledExchangesBrowserTestBase : public ContentBrowserTest { + protected: + BundledExchangesBrowserTestBase() = default; + ~BundledExchangesBrowserTestBase() override = default; + + void NavigateToBundleAndWaitForReady(const GURL& test_data_url, + const GURL& expected_commit_url) { + base::string16 expected_title = base::ASCIIToUTF16("Ready"); + TitleWatcher title_watcher(shell()->web_contents(), expected_title); + EXPECT_TRUE(NavigateToURL(shell()->web_contents(), test_data_url, + expected_commit_url)); + EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); + } + + void RunTestScript(const std::string& script) { + EXPECT_TRUE(ExecuteScript(shell()->web_contents(), + "loadScript('" + script + "');")); + base::string16 ok = base::ASCIIToUTF16("OK"); + TitleWatcher title_watcher(shell()->web_contents(), ok); + title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); + EXPECT_EQ(ok, title_watcher.WaitAndGetTitle()); + } + + void NavigateToURLAndWaitForTitle(const GURL& url, const std::string& title) { + base::string16 title16 = base::ASCIIToUTF16(title); + TitleWatcher title_watcher(shell()->web_contents(), title16); + EXPECT_TRUE(ExecuteScript( + shell()->web_contents(), + base::StringPrintf("location.href = '%s';", url.spec().c_str()))); + EXPECT_EQ(title16, title_watcher.WaitAndGetTitle()); + } + + private: + DISALLOW_COPY_AND_ASSIGN(BundledExchangesBrowserTestBase); +}; + class TestBrowserClient : public ContentBrowserClient { public: TestBrowserClient() = default; @@ -152,17 +196,16 @@ EXPECT_EQ(net::ERR_INVALID_URL, *finish_navigation_observer.error_code()); } -class BundledExchangesTrustableFileBrowserTestBase : public ContentBrowserTest { +class BundledExchangesTrustableFileBrowserTestBase + : public BundledExchangesBrowserTestBase { protected: BundledExchangesTrustableFileBrowserTestBase() = default; ~BundledExchangesTrustableFileBrowserTestBase() override = default; - void SetUp() override { - ContentBrowserTest::SetUp(); - } + void SetUp() override { BundledExchangesBrowserTestBase::SetUp(); } void SetUpOnMainThread() override { - ContentBrowserTest::SetUpOnMainThread(); + BundledExchangesBrowserTestBase::SetUpOnMainThread(); original_client_ = MaybeSetBrowserClientForTesting(&browser_client_); } @@ -172,29 +215,11 @@ } void TearDownOnMainThread() override { - ContentBrowserTest::TearDownOnMainThread(); + BundledExchangesBrowserTestBase::TearDownOnMainThread(); if (original_client_) SetBrowserClientForTesting(original_client_); } - void NavigateToBundleAndWaitForReady() { - base::string16 expected_title = base::ASCIIToUTF16("Ready"); - TitleWatcher title_watcher(shell()->web_contents(), expected_title); - EXPECT_TRUE(NavigateToURL(shell()->web_contents(), test_data_url(), - GURL("https://test.example.org/"))); - EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); - } - - void RunTestScript(const std::string& script) { - EXPECT_TRUE(ExecuteScript(shell()->web_contents(), - "loadScript('" + script + "');")); - - base::string16 ok = base::ASCIIToUTF16("OK"); - TitleWatcher title_watcher(shell()->web_contents(), ok); - title_watcher.AlsoWaitForTitle(base::ASCIIToUTF16("FAIL")); - EXPECT_EQ(ok, title_watcher.WaitAndGetTitle()); - } - const GURL& test_data_url() const { return test_data_url_; } ContentBrowserClient* original_client_ = nullptr; @@ -241,7 +266,7 @@ // on Android Kitkat or older systems. if (!original_client_) return; - NavigateToBundleAndWaitForReady(); + NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl)); } IN_PROC_BROWSER_TEST_P(BundledExchangesTrustableFileBrowserTest, RangeRequest) { @@ -250,10 +275,35 @@ if (!original_client_) return; - NavigateToBundleAndWaitForReady(); + NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl)); RunTestScript("test-range-request.js"); } +IN_PROC_BROWSER_TEST_P(BundledExchangesTrustableFileBrowserTest, Navigation) { + // Don't run the test if we couldn't override BrowserClient. It happens only + // on Android Kitkat or older systems. + if (!original_client_) + return; + + NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl)); + NavigateToURLAndWaitForTitle(GURL(kTestPage1Url), "Page 1"); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), + GURL(kTestPage1Url)); + NavigateToURLAndWaitForTitle(GURL(kTestPage2Url), "Page 2"); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), + GURL(kTestPage2Url)); +} + +IN_PROC_BROWSER_TEST_P(BundledExchangesTrustableFileBrowserTest, + NavigationWithHash) { + // Don't run the test if we couldn't override BrowserClient. It happens only + // on Android Kitkat or older systems. + if (!original_client_) + return; + NavigateToBundleAndWaitForReady(test_data_url(), GURL(kTestPageUrl)); + NavigateToURLAndWaitForTitle(GURL(kTestPageForHashUrl), "#hello"); +} + INSTANTIATE_TEST_SUITE_P(BundledExchangesTrustableFileBrowserTests, BundledExchangesTrustableFileBrowserTest, testing::Values(TestFilePathMode::kNormalFilePath @@ -285,8 +335,7 @@ base::RunLoop run_loop; FinishNavigationObserver finish_navigation_observer(shell()->web_contents(), run_loop.QuitClosure()); - EXPECT_FALSE(NavigateToURL(shell()->web_contents(), test_data_url(), - GURL("https://test.example.org/"))); + EXPECT_FALSE(NavigateToURL(shell()->web_contents(), test_data_url())); run_loop.Run(); ASSERT_TRUE(finish_navigation_observer.error_code()); EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES, @@ -295,14 +344,14 @@ class BundledExchangesFileBrowserTest : public testing::WithParamInterface<TestFilePathMode>, - public ContentBrowserTest { + public BundledExchangesBrowserTestBase { protected: BundledExchangesFileBrowserTest() = default; ~BundledExchangesFileBrowserTest() override = default; void SetUp() override { feature_list_.InitWithFeatures({features::kBundledHTTPExchanges}, {}); - ContentBrowserTest::SetUp(); + BundledExchangesBrowserTestBase::SetUp(); } GURL GetTestUrlForFile(base::FilePath file_path) const { @@ -325,12 +374,40 @@ IN_PROC_BROWSER_TEST_P(BundledExchangesFileBrowserTest, BasicNavigation) { const GURL test_data_url = GetTestUrlForFile(GetTestDataPath("bundled_exchanges_browsertest.wbn")); - base::string16 expected_title = base::ASCIIToUTF16("Ready"); - TitleWatcher title_watcher(shell()->web_contents(), expected_title); - EXPECT_TRUE( - NavigateToURL(shell()->web_contents(), test_data_url, - GURL(test_data_url.spec() + "?https://test.example.org/"))); - EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); + NavigateToBundleAndWaitForReady( + test_data_url, + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPageUrl))); +} + +IN_PROC_BROWSER_TEST_P(BundledExchangesFileBrowserTest, Navigations) { + const GURL test_data_url = + GetTestUrlForFile(GetTestDataPath("bundled_exchanges_browsertest.wbn")); + NavigateToBundleAndWaitForReady( + test_data_url, + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPageUrl))); + NavigateToURLAndWaitForTitle(GURL(kTestPage1Url), "Page 1"); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPage1Url))); + NavigateToURLAndWaitForTitle(GURL(kTestPage2Url), "Page 2"); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPage2Url))); +} + +IN_PROC_BROWSER_TEST_P(BundledExchangesFileBrowserTest, NavigationWithHash) { + const GURL test_data_url = + GetTestUrlForFile(GetTestDataPath("bundled_exchanges_browsertest.wbn")); + NavigateToBundleAndWaitForReady( + test_data_url, + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPageUrl))); + NavigateToURLAndWaitForTitle(GURL(kTestPageForHashUrl), "#hello"); + EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + test_data_url, GURL(kTestPageForHashUrl))); } IN_PROC_BROWSER_TEST_P(BundledExchangesFileBrowserTest, @@ -341,8 +418,7 @@ base::RunLoop run_loop; FinishNavigationObserver finish_navigation_observer(shell()->web_contents(), run_loop.QuitClosure()); - EXPECT_FALSE(NavigateToURL(shell()->web_contents(), test_data_url, - GURL("https://test.example.org/"))); + EXPECT_FALSE(NavigateToURL(shell()->web_contents(), test_data_url)); run_loop.Run(); ASSERT_TRUE(finish_navigation_observer.error_code()); EXPECT_EQ(net::ERR_INVALID_BUNDLED_EXCHANGES,
diff --git a/content/browser/web_package/bundled_exchanges_handle.cc b/content/browser/web_package/bundled_exchanges_handle.cc index 5fbd7219..8c4418c 100644 --- a/content/browser/web_package/bundled_exchanges_handle.cc +++ b/content/browser/web_package/bundled_exchanges_handle.cc
@@ -10,6 +10,7 @@ #include "base/strings/stringprintf.h" #include "base/task/post_task.h" #include "content/browser/loader/navigation_loader_interceptor.h" +#include "content/browser/web_package/bundled_exchanges_handle_tracker.h" #include "content/browser/web_package/bundled_exchanges_reader.h" #include "content/browser/web_package/bundled_exchanges_source.h" #include "content/browser/web_package/bundled_exchanges_url_loader_factory.h" @@ -30,6 +31,10 @@ namespace { +using DoneCallback = base::OnceCallback<void( + const GURL& base_url_override, + std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory)>; + const net::NetworkTrafficAnnotationTag kTrafficAnnotation = net::DefineNetworkTrafficAnnotation("bundled_exchanges_start_url_loader", R"( @@ -123,10 +128,6 @@ // StartResponse() to create the loader for the main resource. class InterceptorForFile final : public NavigationLoaderInterceptor { public: - using DoneCallback = base::OnceCallback<void( - const GURL& base_url_override, - std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory)>; - explicit InterceptorForFile(DoneCallback done_callback) : done_callback_(std::move(done_callback)) {} ~InterceptorForFile() override { @@ -173,7 +174,7 @@ BundledExchangesSource::MaybeCreateFromFileUrl(request.url); if (!source) return false; - reader_ = std::make_unique<BundledExchangesReader>(*source); + reader_ = base::MakeRefCounted<BundledExchangesReader>(std::move(source)); reader_->ReadMetadata(base::BindOnce(&InterceptorForFile::OnMetadataReady, weak_factory_.GetWeakPtr(), request)); *client_request = forwarding_client_.BindNewPipeAndPassReceiver(); @@ -218,7 +219,7 @@ } DoneCallback done_callback_; - std::unique_ptr<BundledExchangesReader> reader_; + scoped_refptr<BundledExchangesReader> reader_; GURL primary_url_; std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory_; @@ -249,14 +250,10 @@ // CreateURLLoader() to create the loader for the main resource. class InterceptorForTrustableFile final : public NavigationLoaderInterceptor { public: - using DoneCallback = base::OnceCallback<void( - const GURL& base_url_override, - std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory)>; - InterceptorForTrustableFile(std::unique_ptr<BundledExchangesSource> source, DoneCallback done_callback) : source_(std::move(source)), - reader_(std::make_unique<BundledExchangesReader>(*source_)), + reader_(base::MakeRefCounted<BundledExchangesReader>(source_->Clone())), done_callback_(std::move(done_callback)) { reader_->ReadMetadata( base::BindOnce(&InterceptorForTrustableFile::OnMetadataReady, @@ -340,7 +337,7 @@ } std::unique_ptr<BundledExchangesSource> source_; - std::unique_ptr<BundledExchangesReader> reader_; + scoped_refptr<BundledExchangesReader> reader_; DoneCallback done_callback_; network::ResourceRequest pending_resource_request_; @@ -359,6 +356,153 @@ DISALLOW_COPY_AND_ASSIGN(InterceptorForTrustableFile); }; +// A class to inherit NavigationLoaderInterceptor for the navigation within a +// trustable BundledExchanges file. +// For example: +// A user opened "file:///tmp/a.wbn", and InterceptorForTrustableFile +// redirected to "https://example.com/a.html" and "a.html" in "a.wbn" was +// loaded. And the user clicked a link to "https://example.com/b.html" from +// "a.html". +// In this case, this interceptor intecepts the navigation request to "b.html", +// and creates a URLLoader using the BundledExchangesURLLoaderFactory to load +// the response of "b.html" in "a.wbn". +class InterceptorForTrackedNavigationFromTrustableFile final + : public NavigationLoaderInterceptor { + public: + InterceptorForTrackedNavigationFromTrustableFile( + scoped_refptr<BundledExchangesReader> reader, + DoneCallback done_callback) + : url_loader_factory_(std::make_unique<BundledExchangesURLLoaderFactory>( + std::move(reader))), + done_callback_(std::move(done_callback)) {} + ~InterceptorForTrackedNavigationFromTrustableFile() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + } + + private: + // NavigationLoaderInterceptor implementation + void MaybeCreateLoader(const network::ResourceRequest& resource_request, + BrowserContext* browser_context, + LoaderCallback callback, + FallbackCallback fallback_callback) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + DCHECK(url_loader_factory_->reader()->HasEntry(resource_request.url)); + std::move(callback).Run(base::BindOnce( + &InterceptorForTrackedNavigationFromTrustableFile::CreateURLLoader, + weak_factory_.GetWeakPtr())); + } + + void CreateURLLoader(const network::ResourceRequest& resource_request, + network::mojom::URLLoaderRequest request, + network::mojom::URLLoaderClientPtr client) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + url_loader_factory_->CreateLoaderAndStart( + std::move(request), /*routing_id=*/0, /*request_id=*/0, /*options=*/0, + resource_request, std::move(client), + net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation)); + std::move(done_callback_) + .Run( + /*base_url_override=*/GURL(), std::move(url_loader_factory_)); + } + + std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory_; + DoneCallback done_callback_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<InterceptorForTrackedNavigationFromTrustableFile> + weak_factory_{this}; + + DISALLOW_COPY_AND_ASSIGN(InterceptorForTrackedNavigationFromTrustableFile); +}; + +// A class to inherit NavigationLoaderInterceptor for the navigation within a +// BundledExchanges file. +// For example: +// A user opened "file:///tmp/a.wbn", and InterceptorForFile redirected to +// "file:///tmp/a.wbn?https://example.com/a.html" and "a.html" in "a.wbn" was +// loaded. And the user clicked a link to "https://example.com/b.html" from +// "a.html". +// In this case, this interceptor intecepts the navigation request to "b.html", +// and redirect the navigation request to +// "file:///tmp/a.wbn?https://example.com/b.html" and creates a URLLoader using +// the BundledExchangesURLLoaderFactory to load the response of "b.html" in +// "a.wbn". +class InterceptorForTrackedNavigationFromFile final + : public NavigationLoaderInterceptor { + public: + InterceptorForTrackedNavigationFromFile( + scoped_refptr<BundledExchangesReader> reader, + DoneCallback done_callback) + : url_loader_factory_(std::make_unique<BundledExchangesURLLoaderFactory>( + std::move(reader))), + done_callback_(std::move(done_callback)) {} + ~InterceptorForTrackedNavigationFromFile() override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + } + + private: + // NavigationLoaderInterceptor implementation + void MaybeCreateLoader(const network::ResourceRequest& resource_request, + BrowserContext* browser_context, + LoaderCallback callback, + FallbackCallback fallback_callback) override { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + std::move(callback).Run(base::BindOnce( + &InterceptorForTrackedNavigationFromFile::CreateURLLoader, + weak_factory_.GetWeakPtr())); + } + + bool ShouldBypassRedirectChecks() override { return true; } + + void CreateURLLoader(const network::ResourceRequest& resource_request, + network::mojom::URLLoaderRequest request, + network::mojom::URLLoaderClientPtr client) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + if (!is_redirected_) { + DCHECK(url_loader_factory_->reader()->HasEntry(resource_request.url)); + is_redirected_ = true; + original_request_url_ = resource_request.url; + + GURL bundled_exchanges_url = + url_loader_factory_->reader()->source().url(); + const GURL new_url = + bundled_exchanges_utils::GetSynthesizedUrlForBundledExchanges( + bundled_exchanges_url, original_request_url_); + auto redirect_loader = + std::make_unique<PrimaryURLRedirectLoader>(client.PassInterface()); + redirect_loader->OnReadyToRedirect(resource_request, new_url); + mojo::MakeSelfOwnedReceiver( + std::move(redirect_loader), + mojo::PendingReceiver<network::mojom::URLLoader>(std::move(request))); + return; + } + network::ResourceRequest new_resource_request = resource_request; + new_resource_request.url = original_request_url_; + url_loader_factory_->CreateLoaderAndStart( + std::move(request), /*routing_id=*/0, /*request_id=*/0, /*options=*/0, + new_resource_request, std::move(client), + net::MutableNetworkTrafficAnnotationTag(kTrafficAnnotation)); + std::move(done_callback_) + .Run( + /*base_url_override=*/original_request_url_, + std::move(url_loader_factory_)); + } + + std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory_; + DoneCallback done_callback_; + + bool is_redirected_ = false; + GURL original_request_url_; + + SEQUENCE_CHECKER(sequence_checker_); + + base::WeakPtrFactory<InterceptorForTrackedNavigationFromFile> weak_factory_{ + this}; + + DISALLOW_COPY_AND_ASSIGN(InterceptorForTrackedNavigationFromFile); +}; + } // namespace // static @@ -384,6 +528,29 @@ return handle; } +// static +std::unique_ptr<BundledExchangesHandle> +BundledExchangesHandle::CreateForTrackedNavigation( + scoped_refptr<BundledExchangesReader> reader) { + auto handle = base::WrapUnique(new BundledExchangesHandle()); + if (reader->source().is_trusted()) { + handle->SetInterceptor( + std::make_unique<InterceptorForTrackedNavigationFromTrustableFile>( + std::move(reader), + base::BindOnce( + &BundledExchangesHandle::OnBundledExchangesFileLoaded, + handle->weak_factory_.GetWeakPtr()))); + } else { + handle->SetInterceptor( + std::make_unique<InterceptorForTrackedNavigationFromFile>( + std::move(reader), + base::BindOnce( + &BundledExchangesHandle::OnBundledExchangesFileLoaded, + handle->weak_factory_.GetWeakPtr()))); + } + return handle; +} + BundledExchangesHandle::BundledExchangesHandle() = default; BundledExchangesHandle::~BundledExchangesHandle() = default; @@ -404,6 +571,14 @@ url_loader_factory_->Clone(std::move(receiver)); } +std::unique_ptr<BundledExchangesHandleTracker> +BundledExchangesHandle::MaybeCreateTracker() { + if (!url_loader_factory_) + return nullptr; + return std::make_unique<BundledExchangesHandleTracker>( + url_loader_factory_->reader()); +} + bool BundledExchangesHandle::IsReadyForLoading() { return !!url_loader_factory_; }
diff --git a/content/browser/web_package/bundled_exchanges_handle.h b/content/browser/web_package/bundled_exchanges_handle.h index efe932f..1080443b 100644 --- a/content/browser/web_package/bundled_exchanges_handle.h +++ b/content/browser/web_package/bundled_exchanges_handle.h
@@ -18,6 +18,8 @@ class BundledExchangesSource; class BundledExchangesURLLoaderFactory; +class BundledExchangesHandleTracker; +class BundledExchangesReader; class NavigationLoaderInterceptor; // A class to provide interfaces to communicate with a BundledExchanges for @@ -27,6 +29,8 @@ static std::unique_ptr<BundledExchangesHandle> CreateForFile(); static std::unique_ptr<BundledExchangesHandle> CreateForTrustableFile( std::unique_ptr<BundledExchangesSource> source); + static std::unique_ptr<BundledExchangesHandle> CreateForTrackedNavigation( + scoped_refptr<BundledExchangesReader> reader); ~BundledExchangesHandle(); @@ -40,6 +44,11 @@ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver, mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory); + // Creates a BundledExchangesHandleTracker to track navigations within the + // bundled exchanges file. Returns null if not yet succeeded to load the + // exchanges file. + std::unique_ptr<BundledExchangesHandleTracker> MaybeCreateTracker(); + // Checks if a valid BundledExchanges is attached, opened, and ready for use. bool IsReadyForLoading(); @@ -60,6 +69,7 @@ std::unique_ptr<NavigationLoaderInterceptor> interceptor_; GURL base_url_override_; + scoped_refptr<BundledExchangesReader> reader_; std::unique_ptr<BundledExchangesURLLoaderFactory> url_loader_factory_; base::WeakPtrFactory<BundledExchangesHandle> weak_factory_{this};
diff --git a/content/browser/web_package/bundled_exchanges_handle_tracker.cc b/content/browser/web_package/bundled_exchanges_handle_tracker.cc new file mode 100644 index 0000000..3b49ad54 --- /dev/null +++ b/content/browser/web_package/bundled_exchanges_handle_tracker.cc
@@ -0,0 +1,29 @@ +// Copyright 2019 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 "content/browser/web_package/bundled_exchanges_handle_tracker.h" + +#include "content/browser/web_package/bundled_exchanges_handle.h" +#include "content/browser/web_package/bundled_exchanges_reader.h" +#include "url/gurl.h" + +namespace content { + +BundledExchangesHandleTracker::BundledExchangesHandleTracker( + scoped_refptr<BundledExchangesReader> reader) + : reader_(std::move(reader)) { + DCHECK(reader_); +} + +BundledExchangesHandleTracker::~BundledExchangesHandleTracker() = default; + +std::unique_ptr<BundledExchangesHandle> +BundledExchangesHandleTracker::MaybeCreateBundledExchangesHandle( + const GURL& url) { + if (!reader_->HasEntry(url)) + return nullptr; + return BundledExchangesHandle::CreateForTrackedNavigation(reader_); +} + +} // namespace content
diff --git a/content/browser/web_package/bundled_exchanges_handle_tracker.h b/content/browser/web_package/bundled_exchanges_handle_tracker.h new file mode 100644 index 0000000..30913a3 --- /dev/null +++ b/content/browser/web_package/bundled_exchanges_handle_tracker.h
@@ -0,0 +1,39 @@ +// Copyright 2019 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 CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_HANDLE_TRACKER_H_ +#define CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_HANDLE_TRACKER_H_ + +#include "base/memory/scoped_refptr.h" +#include "content/browser/web_package/bundled_exchanges_reader.h" + +class GURL; + +namespace content { + +class BundledExchangesHandle; +class BundledExchangesReader; + +// This class is used to track navigations within the bundled exchanges file. +class BundledExchangesHandleTracker { + public: + explicit BundledExchangesHandleTracker( + scoped_refptr<BundledExchangesReader> reader); + ~BundledExchangesHandleTracker(); + + // Returns a BundledExchangesHandle to handle the navigation request to |url| + // if the bundled exchanges file contains the matching response. Otherwise + // returns null. + std::unique_ptr<BundledExchangesHandle> MaybeCreateBundledExchangesHandle( + const GURL& url); + + private: + scoped_refptr<BundledExchangesReader> reader_; + + DISALLOW_COPY_AND_ASSIGN(BundledExchangesHandleTracker); +}; + +} // namespace content + +#endif // CONTENT_BROWSER_WEB_PACKAGE_BUNDLED_EXCHANGES_HANDLE_TRACKER_H_
diff --git a/content/browser/web_package/bundled_exchanges_reader.cc b/content/browser/web_package/bundled_exchanges_reader.cc index 2ba23cce..d7dddf6 100644 --- a/content/browser/web_package/bundled_exchanges_reader.cc +++ b/content/browser/web_package/bundled_exchanges_reader.cc
@@ -24,13 +24,13 @@ namespace content { BundledExchangesReader::SharedFile::SharedFile( - const BundledExchangesSource& source) { + std::unique_ptr<BundledExchangesSource> source) { base::PostTaskAndReplyWithResult( FROM_HERE, {base::ThreadPool(), base::MayBlock()}, base::BindOnce( [](std::unique_ptr<BundledExchangesSource> source) -> std::unique_ptr<base::File> { return source->OpenFile(); }, - source.Clone()), + std::move(source)), base::BindOnce(&SharedFile::SetFile, base::RetainedRef(this))); } @@ -136,11 +136,12 @@ }; BundledExchangesReader::BundledExchangesReader( - const BundledExchangesSource& source) - : parser_(ServiceManagerConnection::GetForProcess() + std::unique_ptr<BundledExchangesSource> source) + : source_(std::move(source)), + parser_(ServiceManagerConnection::GetForProcess() ? ServiceManagerConnection::GetForProcess()->GetConnector() : nullptr), - file_(base::MakeRefCounted<SharedFile>(source)) {} + file_(base::MakeRefCounted<SharedFile>(source_->Clone())) {} BundledExchangesReader::~BundledExchangesReader() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); @@ -151,8 +152,8 @@ DCHECK(!metadata_ready_); file_->DuplicateFile( - base::BindOnce(&BundledExchangesReader::ReadMetadataInternal, - weak_factory_.GetWeakPtr(), std::move(callback))); + base::BindOnce(&BundledExchangesReader::ReadMetadataInternal, this, + std::move(callback))); } void BundledExchangesReader::ReadResponse(const GURL& url, @@ -210,6 +211,11 @@ return primary_url_; } +const BundledExchangesSource& BundledExchangesReader::source() const { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + return *source_; +} + void BundledExchangesReader::SetBundledExchangesParserFactoryForTesting( mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> factory) { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/content/browser/web_package/bundled_exchanges_reader.h b/content/browser/web_package/bundled_exchanges_reader.h index 74f52ad5..b684b8ea 100644 --- a/content/browser/web_package/bundled_exchanges_reader.h +++ b/content/browser/web_package/bundled_exchanges_reader.h
@@ -30,11 +30,14 @@ // A class to handle a BundledExchanges that is specified by |source|. // It asks the utility process to parse metadata and response structures, and // provides body data based on parsed information. +// This class is typically owned by BundledExchangesURLLoaderFactory, and also +// could be co-owned by BundledExchangesHandleTracker during navigations. // Running on the UI thread. -class CONTENT_EXPORT BundledExchangesReader final { +class CONTENT_EXPORT BundledExchangesReader final + : public base::RefCounted<BundledExchangesReader> { public: - explicit BundledExchangesReader(const BundledExchangesSource& source); - ~BundledExchangesReader(); + explicit BundledExchangesReader( + std::unique_ptr<BundledExchangesSource> source); // Starts parsing, and runs |callback| when meta data gets to be available. // |error| is set only on failures. @@ -67,15 +70,20 @@ // Should be called after ReadMetadata finishes. const GURL& GetPrimaryURL() const; + // Returns the BundledExchangesSource. + const BundledExchangesSource& source() const; + void SetBundledExchangesParserFactoryForTesting( mojo::Remote<data_decoder::mojom::BundledExchangesParserFactory> factory); private: + friend class base::RefCounted<BundledExchangesReader>; + // A simple wrapper class to share a single base::File instance among multiple // SharedFileDataSource instances. class SharedFile final : public base::RefCountedThreadSafe<SharedFile> { public: - explicit SharedFile(const BundledExchangesSource& source); + explicit SharedFile(std::unique_ptr<BundledExchangesSource> source); void DuplicateFile(base::OnceCallback<void(base::File)> callback); base::File* operator->(); @@ -93,6 +101,8 @@ }; class SharedFileDataSource; + ~BundledExchangesReader(); + void ReadMetadataInternal(MetadataCallback callback, base::File file); void OnMetadataParsed(MetadataCallback callback, @@ -104,14 +114,14 @@ SEQUENCE_CHECKER(sequence_checker_); + const std::unique_ptr<BundledExchangesSource> source_; + data_decoder::SafeBundledExchangesParser parser_; scoped_refptr<SharedFile> file_; GURL primary_url_; base::flat_map<GURL, data_decoder::mojom::BundleIndexValuePtr> entries_; bool metadata_ready_ = false; - base::WeakPtrFactory<BundledExchangesReader> weak_factory_{this}; - DISALLOW_COPY_AND_ASSIGN(BundledExchangesReader); };
diff --git a/content/browser/web_package/bundled_exchanges_reader_unittest.cc b/content/browser/web_package/bundled_exchanges_reader_unittest.cc index 71f1344..3990246 100644 --- a/content/browser/web_package/bundled_exchanges_reader_unittest.cc +++ b/content/browser/web_package/bundled_exchanges_reader_unittest.cc
@@ -61,7 +61,7 @@ private: base::test::TaskEnvironment task_environment_; std::unique_ptr<MockBundledExchangesReaderFactory> reader_factory_; - std::unique_ptr<BundledExchangesReader> reader_; + scoped_refptr<BundledExchangesReader> reader_; const GURL primary_url_ = GURL("https://test.example.org/"); const std::string body_ = std::string("hello new open world."); };
diff --git a/content/browser/web_package/bundled_exchanges_url_loader_factory.cc b/content/browser/web_package/bundled_exchanges_url_loader_factory.cc index b9c9e866..1d1b43c 100644 --- a/content/browser/web_package/bundled_exchanges_url_loader_factory.cc +++ b/content/browser/web_package/bundled_exchanges_url_loader_factory.cc
@@ -84,7 +84,7 @@ } } - factory_->GetReader()->ReadResponse( + factory_->reader()->ReadResponse( resource_request.url, base::BindOnce(&EntryLoader::OnResponseReady, weak_factory_.GetWeakPtr())); } @@ -152,7 +152,7 @@ return; } - factory_->GetReader()->ReadResponseBody( + factory_->reader()->ReadResponseBody( std::move(response), std::move(producer_handle), base::BindOnce(&EntryLoader::FinishReadingBody, weak_factory_.GetWeakPtr())); @@ -178,7 +178,7 @@ }; BundledExchangesURLLoaderFactory::BundledExchangesURLLoaderFactory( - std::unique_ptr<BundledExchangesReader> reader) + scoped_refptr<BundledExchangesReader> reader) : reader_(std::move(reader)) {} BundledExchangesURLLoaderFactory::~BundledExchangesURLLoaderFactory() = default;
diff --git a/content/browser/web_package/bundled_exchanges_url_loader_factory.h b/content/browser/web_package/bundled_exchanges_url_loader_factory.h index b194b0d..ae6961a 100644 --- a/content/browser/web_package/bundled_exchanges_url_loader_factory.h +++ b/content/browser/web_package/bundled_exchanges_url_loader_factory.h
@@ -23,7 +23,7 @@ : public network::mojom::URLLoaderFactory { public: explicit BundledExchangesURLLoaderFactory( - std::unique_ptr<BundledExchangesReader> reader); + scoped_refptr<BundledExchangesReader> reader); ~BundledExchangesURLLoaderFactory() override; // Set a |network::mojom::URLLoaderFactory| remote interface used for requests @@ -43,14 +43,16 @@ traffic_annotation) override; void Clone(network::mojom::URLLoaderFactoryRequest request) override; + const scoped_refptr<BundledExchangesReader>& reader() const { + return reader_; + } + private: class EntryLoader; friend class EntryLoader; - BundledExchangesReader* GetReader() { return reader_.get(); } - mojo::BindingSet<network::mojom::URLLoaderFactory> bindings_; - std::unique_ptr<BundledExchangesReader> reader_; + scoped_refptr<BundledExchangesReader> reader_; mojo::Remote<network::mojom::URLLoaderFactory> fallback_factory_; base::WeakPtrFactory<BundledExchangesURLLoaderFactory> weak_factory_{this};
diff --git a/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc b/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc index 01f5c03..346d37e 100644 --- a/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc +++ b/content/browser/web_package/mock_bundled_exchanges_reader_factory.cc
@@ -149,7 +149,7 @@ : MockBundledExchangesReaderFactory() {} ~MockBundledExchangesReaderFactoryImpl() override = default; - std::unique_ptr<BundledExchangesReader> CreateReader( + scoped_refptr<BundledExchangesReader> CreateReader( const std::string& test_file_data) override { if (!temp_dir_.CreateUniqueTempDir() || !CreateTemporaryFileInDir(temp_dir_.GetPath(), &temp_file_path_) || @@ -159,9 +159,9 @@ return nullptr; } - auto source = BundledExchangesSource::MaybeCreateFromTrustedFileUrl( - net::FilePathToFileURL(temp_file_path_)); - auto reader = std::make_unique<BundledExchangesReader>(*source); + auto reader = base::MakeRefCounted<BundledExchangesReader>( + BundledExchangesSource::MaybeCreateFromTrustedFileUrl( + net::FilePathToFileURL(temp_file_path_))); std::unique_ptr<MockParserFactory> factory = std::make_unique<MockParserFactory>();
diff --git a/content/browser/web_package/mock_bundled_exchanges_reader_factory.h b/content/browser/web_package/mock_bundled_exchanges_reader_factory.h index ee82a17..1497d69 100644 --- a/content/browser/web_package/mock_bundled_exchanges_reader_factory.h +++ b/content/browser/web_package/mock_bundled_exchanges_reader_factory.h
@@ -25,7 +25,7 @@ // Creates BundledExchangesReader instance. A temporary file is created and // |test_file_data| is stored. This temporary file is used when // BundledExchangesReader::ReadResponseBody() is called. - virtual std::unique_ptr<BundledExchangesReader> CreateReader( + virtual scoped_refptr<BundledExchangesReader> CreateReader( const std::string& test_file_data) = 0; // Calls ReadMetadata with |callback| for |reader|, and simulates the call as
diff --git a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java index a04301e0..25189bada17 100644 --- a/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java +++ b/content/public/test/android/javatests/src/org/chromium/content_public/browser/test/util/DOMUtils.java
@@ -502,6 +502,30 @@ } /** + * Returns the value of a given attribute of type {@code valueType} as a {@code T}. + * @param attributeName The attribute to return the value from. + * @param webContents The WebContents in which the node lives. + * @param nodeId The id of the node. + * @param valueType The type of the value to read. + * @return the attributes' value. + */ + public static <T> T getNodeAttribute(String attributeName, final WebContents webContents, + String nodeId, Class<T> valueType) throws InterruptedException, TimeoutException { + StringBuilder sb = new StringBuilder(); + sb.append("(function() {"); + sb.append(" var node = document.getElementById('" + nodeId + "');"); + sb.append(" if (!node) return null;"); + sb.append(" return [ node.getAttribute('" + attributeName + "') ];"); + sb.append("})();"); + + String jsonText = + JavaScriptUtils.executeJavaScriptAndWaitForResult(webContents, sb.toString()); + Assert.assertFalse("Failed to retrieve contents for " + nodeId, + jsonText.trim().equalsIgnoreCase("null")); + return readValue(jsonText, valueType); + } + + /** * Returns the next value of type {@code valueType} as a {@code T}. * @param jsonText The unparsed json text. * @param valueType The type of the value to read.
diff --git a/content/renderer/loader/web_url_loader_impl.cc b/content/renderer/loader/web_url_loader_impl.cc index 2c6cf18..b2ecb349 100644 --- a/content/renderer/loader/web_url_loader_impl.cc +++ b/content/renderer/loader/web_url_loader_impl.cc
@@ -360,9 +360,12 @@ std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle) { DCHECK(task_runner_handle); DCHECK(resource_dispatcher_); - return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), - std::move(task_runner_handle), - loader_factory_); + // This default implementation does not support KeepAlive. + mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle = + mojo::NullRemote(); + return std::make_unique<WebURLLoaderImpl>( + resource_dispatcher_.get(), std::move(task_runner_handle), + loader_factory_, std::move(keep_alive_handle)); } // This inner class exists since the WebURLLoader may be deleted while inside a @@ -1010,15 +1013,6 @@ WebURLLoaderImpl::WebURLLoaderImpl( ResourceDispatcher* resource_dispatcher, std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory) - : WebURLLoaderImpl(resource_dispatcher, - std::move(task_runner_handle), - std::move(url_loader_factory), - mojo::NullRemote()) {} - -WebURLLoaderImpl::WebURLLoaderImpl( - ResourceDispatcher* resource_dispatcher, - std::unique_ptr<WebResourceLoadingTaskRunnerHandle> task_runner_handle, scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory, mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle) : context_(new Context(this,
diff --git a/content/renderer/loader/web_url_loader_impl.h b/content/renderer/loader/web_url_loader_impl.h index 6c28739..15cfcaba 100644 --- a/content/renderer/loader/web_url_loader_impl.h +++ b/content/renderer/loader/web_url_loader_impl.h
@@ -49,11 +49,6 @@ class CONTENT_EXPORT WebURLLoaderImpl : public blink::WebURLLoader { public: - WebURLLoaderImpl( - ResourceDispatcher* resource_dispatcher, - std::unique_ptr<blink::scheduler::WebResourceLoadingTaskRunnerHandle> - task_runner_handle, - scoped_refptr<network::SharedURLLoaderFactory> url_loader_factory); // When non-null |keep_alive_handle| is specified, this loader prolongs // this render process's lifetime. WebURLLoaderImpl(
diff --git a/content/renderer/loader/web_url_loader_impl_unittest.cc b/content/renderer/loader/web_url_loader_impl_unittest.cc index 96cfcc43..ddb3ab9a 100644 --- a/content/renderer/loader/web_url_loader_impl_unittest.cc +++ b/content/renderer/loader/web_url_loader_impl_unittest.cc
@@ -171,7 +171,8 @@ CreateUnprioritized( blink::scheduler::GetSingleThreadTaskRunnerForTesting()), base::MakeRefCounted<network::WeakWrapperSharedURLLoaderFactory>( - &fake_url_loader_factory_))), + &fake_url_loader_factory_), + /*keep_alive_handle=*/mojo::NullRemote())), delete_on_receive_redirect_(false), delete_on_receive_response_(false), delete_on_receive_data_(false),
diff --git a/content/renderer/loader/web_worker_fetch_context_impl.cc b/content/renderer/loader/web_worker_fetch_context_impl.cc index 235d3f8..4d1d40a 100644 --- a/content/renderer/loader/web_worker_fetch_context_impl.cc +++ b/content/renderer/loader/web_worker_fetch_context_impl.cc
@@ -85,17 +85,22 @@ task_runner_handle) override { DCHECK(task_runner_handle); DCHECK(resource_dispatcher_); + + // KeepAlive is not yet supported in web workers. + mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle = + mojo::NullRemote(); + if (CanCreateServiceWorkerURLLoader(request)) { // Create our own URLLoader to route the request to the controller service // worker. - return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), - std::move(task_runner_handle), - service_worker_loader_factory_); + return std::make_unique<WebURLLoaderImpl>( + resource_dispatcher_.get(), std::move(task_runner_handle), + service_worker_loader_factory_, std::move(keep_alive_handle)); } - return std::make_unique<WebURLLoaderImpl>(resource_dispatcher_.get(), - std::move(task_runner_handle), - loader_factory_); + return std::make_unique<WebURLLoaderImpl>( + resource_dispatcher_.get(), std::move(task_runner_handle), + loader_factory_, std::move(keep_alive_handle)); } void SetServiceWorkerURLLoaderFactory(
diff --git a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc index d6dec97..8306936a 100644 --- a/content/renderer/service_worker/service_worker_network_provider_for_frame.cc +++ b/content/renderer/service_worker/service_worker_network_provider_for_frame.cc
@@ -137,11 +137,22 @@ kServiceWorkerInterceptedRequestFromOriginDirtyStyleSheet); } + mojo::PendingRemote<mojom::KeepAliveHandle> keep_alive_handle; + if (request.GetKeepalive()) { + // This cast is safe because NewDocumentObserver is always created with a + // RenderFrameImpl. + auto* render_frame_impl = + static_cast<RenderFrameImpl*>(observer_->render_frame()); + render_frame_impl->GetFrameHost()->IssueKeepAliveHandle( + keep_alive_handle.InitWithNewPipeAndPassReceiver()); + } + // Create our own SubresourceLoader to route the request to the controller // ServiceWorker. return std::make_unique<WebURLLoaderImpl>( RenderThreadImpl::current()->resource_dispatcher(), - std::move(task_runner_handle), context()->GetSubresourceLoaderFactory()); + std::move(task_runner_handle), context()->GetSubresourceLoaderFactory(), + std::move(keep_alive_handle)); } blink::mojom::ControllerServiceWorkerMode
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest.wbn b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest.wbn index 774f509..59e5a80 100644 --- a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest.wbn +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest.wbn Binary files differ
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.html b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.html new file mode 100644 index 0000000..e3d10ac --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<script src="hash.js"></script>
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.js b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.js new file mode 100644 index 0000000..8a680fe8 --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/hash.js
@@ -0,0 +1,5 @@ +// Copyright 2019 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. + +document.title = location.hash;
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.html b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.html new file mode 100644 index 0000000..45116366 --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<script src="page1.js"></script>
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.js b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.js new file mode 100644 index 0000000..188bce1d --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page1.js
@@ -0,0 +1,5 @@ +// Copyright 2019 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. + +document.title = 'Page 1';
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.html b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.html new file mode 100644 index 0000000..b079bf0 --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.html
@@ -0,0 +1,2 @@ +<!DOCTYPE html> +<script src="page2.js"></script>
diff --git a/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.js b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.js new file mode 100644 index 0000000..4b5a76fd --- /dev/null +++ b/content/test/data/bundled_exchanges/bundled_exchanges_browsertest/page2.js
@@ -0,0 +1,5 @@ +// Copyright 2019 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. + +document.title = 'Page 2';
diff --git a/content/test/data/workers/send-beacon.html b/content/test/data/workers/send-beacon.html new file mode 100644 index 0000000..a8d5fab7 --- /dev/null +++ b/content/test/data/workers/send-beacon.html
@@ -0,0 +1,4 @@ +<!doctype html> +<script> +navigator.sendBeacon('/beacon', 'hello'); +</script>
diff --git a/content/test/dwrite_font_fake_sender_win.cc b/content/test/dwrite_font_fake_sender_win.cc index 8b1a43a..2145e13 100644 --- a/content/test/dwrite_font_fake_sender_win.cc +++ b/content/test/dwrite_font_fake_sender_win.cc
@@ -145,11 +145,11 @@ void FakeFontCollection::GetUniqueNameLookupTableIfAvailable( GetUniqueNameLookupTableIfAvailableCallback callback) {} -void FakeFontCollection::FallbackFamilyNameForCodepoint( +void FakeFontCollection::FallbackFamilyAndStyleForCodepoint( const std::string& base_family_name, const std::string& locale_name, uint32_t codepoint, - FallbackFamilyNameForCodepointCallback callback) {} + FallbackFamilyAndStyleForCodepointCallback callback) {} FakeFontCollection::~FakeFontCollection() = default;
diff --git a/content/test/dwrite_font_fake_sender_win.h b/content/test/dwrite_font_fake_sender_win.h index 04dd330..ad41cc3e 100644 --- a/content/test/dwrite_font_fake_sender_win.h +++ b/content/test/dwrite_font_fake_sender_win.h
@@ -129,11 +129,11 @@ GetUniqueNameLookupTableIfAvailableCallback callback) override; void GetUniqueNameLookupTable( GetUniqueNameLookupTableCallback callback) override; - void FallbackFamilyNameForCodepoint( + void FallbackFamilyAndStyleForCodepoint( const std::string& base_family_name, const std::string& locale_name, uint32_t codepoint, - FallbackFamilyNameForCodepointCallback callback) override; + FallbackFamilyAndStyleForCodepointCallback callback) override; private: std::vector<FakeFont> fonts_;
diff --git a/extensions/browser/api/diagnostics/diagnostics_api.cc b/extensions/browser/api/diagnostics/diagnostics_api.cc index 85401ec..4c569140 100644 --- a/extensions/browser/api/diagnostics/diagnostics_api.cc +++ b/extensions/browser/api/diagnostics/diagnostics_api.cc
@@ -10,7 +10,7 @@ #include "base/strings/string_number_conversions.h" #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" namespace extensions {
diff --git a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm index 898d6da..2e56688 100644 --- a/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/content_suggestions_egtest.mm
@@ -47,7 +47,14 @@ #error "This file requires ARC support." #endif -using namespace ntp_snippets; +using ntp_snippets::AdditionalSuggestionsHelper; +using ntp_snippets::Category; +using ntp_snippets::CategoryStatus; +using ntp_snippets::ContentSuggestion; +using ntp_snippets::ContentSuggestionsService; +using ntp_snippets::CreateChromeContentSuggestionsService; +using ntp_snippets::KnownCategories; +using ntp_snippets::MockContentSuggestionsProvider; using testing::_; using testing::Invoke; using testing::WithArg; @@ -198,11 +205,11 @@ // Add 3 suggestions, persisted accross page loads. std::vector<ContentSuggestion> suggestions; - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium1", GURL("http://chromium.org/1"))); - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium2", GURL("http://chromium.org/2"))); - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium3", GURL("http://chromium.org/3"))); self.provider->FireSuggestionsChanged(self.category, std::move(suggestions)); @@ -238,15 +245,15 @@ - (void)testReloadPage { // Add 2 suggestions. std::vector<ContentSuggestion> suggestions; - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium1", GURL("http://chromium.org/1"))); - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium2", GURL("http://chromium.org/2"))); self.provider->FireSuggestionsChanged(self.category, std::move(suggestions)); // Change the suggestions to have one the second one. std::vector<ContentSuggestion> suggestionsOnly; - suggestionsOnly.emplace_back( + suggestionsOnly.push_back( Suggestion(self.category, "chromium2", GURL("http://chromium.org/2"))); self.provider->FireSuggestionsChanged(self.category, std::move(suggestionsOnly)); @@ -276,11 +283,11 @@ // Add 3 suggestions, persisted accross page loads. std::vector<ContentSuggestion> suggestions; - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium1", GURL("http://chromium.org/1"))); - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium2", GURL("http://chromium.org/2"))); - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium3", GURL("http://chromium.org/3"))); self.provider->FireSuggestionsChanged(self.category, std::move(suggestions)); @@ -339,7 +346,7 @@ assertWithMatcher:grey_nil()]; std::vector<ContentSuggestion> suggestions; - suggestions.emplace_back( + suggestions.push_back( Suggestion(self.category, "chromium", GURL("http://chromium.org"))); self.provider->FireSuggestionsChanged(self.category, std::move(suggestions));
diff --git a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm index 2a0c7b8..8425e0d2 100644 --- a/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm +++ b/ios/chrome/browser/ui/content_suggestions/ntp_home_egtest.mm
@@ -51,9 +51,17 @@ #error "This file requires ARC support." #endif -using namespace content_suggestions; -using namespace ntp_home; -using namespace ntp_snippets; +using content_suggestions::searchFieldWidth; +using ntp_home::CollectionView; +using ntp_home::FakeOmnibox; +using ntp_home::OmniboxWidth; +using ntp_home::OmniboxWidthBetween; +using ntp_home::Suggestions; +using ntp_snippets::CategoryStatus; +using ntp_snippets::ContentSuggestionsService; +using ntp_snippets::CreateChromeContentSuggestionsService; +using ntp_snippets::KnownCategories; +using ntp_snippets::MockContentSuggestionsProvider; namespace { const char kPageLoadedString[] = "Page loaded!"; @@ -410,7 +418,7 @@ ReadingListModelFactory::GetForBrowserState(self.browserState) ->AddEntry(GURL("http://chromium.org/"), "title", reading_list::ADDED_VIA_CURRENT_APP); - self.provider->FireSuggestionsChanged(self.category, ntp_home::Suggestions()); + self.provider->FireSuggestionsChanged(self.category, Suggestions()); // Scroll to have a position to restored. [[EarlGrey selectElementWithMatcher:chrome_test_util:: @@ -418,7 +426,7 @@ performAction:grey_scrollInDirection(kGREYDirectionDown, 150)]; // Save the position before navigating. - UIView* omnibox = ntp_home::FakeOmnibox(); + UIView* omnibox = FakeOmnibox(); CGPoint previousPosition = omnibox.bounds.origin; // Navigate and come back. @@ -430,7 +438,7 @@ [ChromeEarlGrey goBack]; // Check that the new position is the same. - omnibox = ntp_home::FakeOmnibox(); + omnibox = FakeOmnibox(); GREYAssertEqual(previousPosition.y, omnibox.bounds.origin.y, @"Omnibox not at the same position"); } @@ -445,7 +453,7 @@ ReadingListModelFactory::GetForBrowserState(self.browserState) ->AddEntry(GURL("http://chromium.org/"), "title", reading_list::ADDED_VIA_CURRENT_APP); - self.provider->FireSuggestionsChanged(self.category, ntp_home::Suggestions()); + self.provider->FireSuggestionsChanged(self.category, Suggestions()); // Scroll to have a position to restored. [[EarlGrey selectElementWithMatcher:chrome_test_util:: @@ -453,7 +461,7 @@ performAction:grey_scrollInDirection(kGREYDirectionDown, 150)]; // Save the position before navigating. - UIView* omnibox = ntp_home::FakeOmnibox(); + UIView* omnibox = FakeOmnibox(); CGPoint previousPosition = omnibox.bounds.origin; // Tap the omnibox to focus it. @@ -468,7 +476,7 @@ [ChromeEarlGrey goBack]; // Check that the new position is the same. - omnibox = ntp_home::FakeOmnibox(); + omnibox = FakeOmnibox(); GREYAssertEqual(previousPosition.y, omnibox.bounds.origin.y, @"Omnibox not at the same position"); } @@ -527,7 +535,7 @@ // Tests that tapping the fake omnibox moves the collection. - (void)testTapFakeOmniboxScroll { // Get the collection and its layout. - UIView* collection = ntp_home::CollectionView(); + UIView* collection = CollectionView(); GREYAssertTrue([collection isKindOfClass:[UICollectionView class]], @"The collection has not been correctly selected."); UICollectionView* collectionView = (UICollectionView*)collection; @@ -556,7 +564,7 @@ [[EarlGrey selectElementWithMatcher:chrome_test_util::FakeOmnibox()] assertWithMatcher:grey_not(grey_sufficientlyVisible())]; - CGFloat top = ntp_home::CollectionView().safeAreaInsets.top; + CGFloat top = CollectionView().safeAreaInsets.top; GREYAssertTrue(offsetAfterTap.y >= origin.y + headerHeight - (60 + top), @"The collection has not moved."); @@ -578,7 +586,7 @@ // back to where it was. - (void)testTapFakeOmniboxScrollScrolled { // Get the collection and its layout. - UIView* collection = ntp_home::CollectionView(); + UIView* collection = CollectionView(); GREYAssertTrue([collection isKindOfClass:[UICollectionView class]], @"The collection has not been correctly selected."); UICollectionView* collectionView = (UICollectionView*)collection;
diff --git a/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util_unittest.mm b/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util_unittest.mm index ae1243b..5edca62b 100644 --- a/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util_unittest.mm +++ b/ios/chrome/browser/ui/dialogs/nsurl_protection_space_util_unittest.mm
@@ -16,7 +16,8 @@ #error "This file requires ARC support." #endif -using namespace nsurlprotectionspace_util; +using nsurlprotectionspace_util::CanShow; +using nsurlprotectionspace_util::MessageForHTTPAuth; namespace {
diff --git a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm index 39707e0..d20b2f8 100644 --- a/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm +++ b/ios/chrome/browser/ui/qr_scanner/qr_scanner_view_controller_egtest.mm
@@ -43,8 +43,7 @@ #error "This file requires ARC support." #endif -using namespace chrome_test_util; -using namespace scanner; +using scanner::CameraState; namespace { @@ -74,7 +73,7 @@ // Returns the GREYMatcher for the button that closes the QR Scanner. id<GREYMatcher> QrScannerCloseButton() { - return ButtonWithAccessibilityLabel( + return chrome_test_util::ButtonWithAccessibilityLabel( [[ChromeIcon closeIcon] accessibilityLabel]); } @@ -100,7 +99,7 @@ // Returns the GREYMatcher for the QR Scanner viewport caption. id<GREYMatcher> QrScannerViewportCaption() { - return StaticTextWithAccessibilityLabelId( + return chrome_test_util::StaticTextWithAccessibilityLabelId( IDS_IOS_QR_SCANNER_VIEWPORT_CAPTION); } @@ -134,13 +133,13 @@ // Appends the given |editText| to the |text| already in the omnibox and presses // the keyboard return key. void EditOmniboxTextAndTapKeyboardReturn(std::string text, NSString* editText) { - [[EarlGrey selectElementWithMatcher:OmniboxText(text)] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(text)] performAction:grey_typeText([editText stringByAppendingString:@"\n"])]; } // Presses the keyboard return key. void TapKeyboardReturnKeyInOmniboxWithText(std::string text) { - [[EarlGrey selectElementWithMatcher:OmniboxText(text)] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(text)] performAction:grey_typeText(@"\n")]; } @@ -284,7 +283,7 @@ // Checks that the omnibox is visible and contains |text|. - (void)assertOmniboxIsVisibleWithText:(std::string)text { - [[EarlGrey selectElementWithMatcher:OmniboxText(text)] + [[EarlGrey selectElementWithMatcher:chrome_test_util::OmniboxText(text)] assertWithMatcher:grey_notNil()]; } @@ -374,20 +373,20 @@ - (NSString*)dialogTitleForState:(CameraState)state { base::string16 appName = base::UTF8ToUTF16(version_info::GetProductName()); switch (state) { - case CAMERA_AVAILABLE: - case CAMERA_NOT_LOADED: + case scanner::CAMERA_AVAILABLE: + case scanner::CAMERA_NOT_LOADED: return nil; - case CAMERA_IN_USE_BY_ANOTHER_APPLICATION: + case scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION: return l10n_util::GetNSString( IDS_IOS_QR_SCANNER_CAMERA_IN_USE_ALERT_TITLE); - case CAMERA_PERMISSION_DENIED: + case scanner::CAMERA_PERMISSION_DENIED: return l10n_util::GetNSString( IDS_IOS_SCANNER_CAMERA_PERMISSIONS_HELP_TITLE_GO_TO_SETTINGS); - case CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: - case CAMERA_UNAVAILABLE: + case scanner::CAMERA_UNAVAILABLE_DUE_TO_SYSTEM_PRESSURE: + case scanner::CAMERA_UNAVAILABLE: return l10n_util::GetNSString( IDS_IOS_QR_SCANNER_CAMERA_UNAVAILABLE_ALERT_TITLE); - case MULTIPLE_FOREGROUND_APPS: + case scanner::MULTIPLE_FOREGROUND_APPS: return l10n_util::GetNSString( IDS_IOS_QR_SCANNER_MULTIPLE_FOREGROUND_APPS_ALERT_TITLE); } @@ -660,9 +659,10 @@ AVAuthorizationStatusAuthorized]; [self swizzleCameraController:cameraControllerMock]; - std::vector<CameraState> tests{MULTIPLE_FOREGROUND_APPS, CAMERA_UNAVAILABLE, - CAMERA_PERMISSION_DENIED, - CAMERA_IN_USE_BY_ANOTHER_APPLICATION}; + std::vector<CameraState> tests{scanner::MULTIPLE_FOREGROUND_APPS, + scanner::CAMERA_UNAVAILABLE, + scanner::CAMERA_PERMISSION_DENIED, + scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION}; for (const CameraState& state : tests) { [self showQRScannerAndCheckLayoutWithCameraMock:cameraControllerMock]; @@ -689,14 +689,15 @@ [self swizzleCameraController:cameraControllerMock]; // Change state to CAMERA_UNAVAILABLE. - CameraState currentState = CAMERA_UNAVAILABLE; + CameraState currentState = scanner::CAMERA_UNAVAILABLE; [self showQRScannerAndCheckLayoutWithCameraMock:cameraControllerMock]; [self callCameraStateChanged:currentState]; [self assertQRScannerIsPresentingADialogForState:currentState]; - std::vector<CameraState> tests{ - CAMERA_PERMISSION_DENIED, MULTIPLE_FOREGROUND_APPS, - CAMERA_IN_USE_BY_ANOTHER_APPLICATION, CAMERA_UNAVAILABLE}; + std::vector<CameraState> tests{scanner::CAMERA_PERMISSION_DENIED, + scanner::MULTIPLE_FOREGROUND_APPS, + scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION, + scanner::CAMERA_UNAVAILABLE}; for (const CameraState& state : tests) { [self callCameraStateChanged:state]; @@ -723,9 +724,10 @@ AVAuthorizationStatusAuthorized]; [self swizzleCameraController:cameraControllerMock]; - std::vector<CameraState> tests{CAMERA_IN_USE_BY_ANOTHER_APPLICATION, - CAMERA_UNAVAILABLE, MULTIPLE_FOREGROUND_APPS, - CAMERA_PERMISSION_DENIED}; + std::vector<CameraState> tests{scanner::CAMERA_IN_USE_BY_ANOTHER_APPLICATION, + scanner::CAMERA_UNAVAILABLE, + scanner::MULTIPLE_FOREGROUND_APPS, + scanner::CAMERA_PERMISSION_DENIED}; for (const CameraState& state : tests) { [self showQRScannerAndCheckLayoutWithCameraMock:cameraControllerMock]; @@ -733,7 +735,7 @@ [self assertQRScannerIsPresentingADialogForState:state]; // Change state to CAMERA_AVAILABLE. - [self callCameraStateChanged:CAMERA_AVAILABLE]; + [self callCameraStateChanged:scanner::CAMERA_AVAILABLE]; [self assertQRScannerIsNotPresentingADialogForState:state]; [self closeQRScannerWithCameraMock:cameraControllerMock]; }
diff --git a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm index 97161ac..2ceebd3 100644 --- a/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/privacy_table_view_controller.mm
@@ -67,7 +67,6 @@ std::unique_ptr<PrefObserverBridge> _prefObserverBridge; // Registrar for pref changes notifications. PrefChangeRegistrar _prefChangeRegistrar; - PrefChangeRegistrar _prefChangeRegistrarApplicationContext; // Updatable Items TableViewDetailIconItem* _handoffDetailItem; @@ -94,8 +93,6 @@ PrefService* prefService = _browserState->GetPrefs(); _prefChangeRegistrar.Init(prefService); - _prefChangeRegistrarApplicationContext.Init( - GetApplicationContext()->GetLocalState()); _prefObserverBridge.reset(new PrefObserverBridge(self)); // Register to observe any changes on Perf backed values displayed by the // screen.
diff --git a/ios/chrome/browser/ui/settings/sync/sync_create_passphrase_table_view_controller.mm b/ios/chrome/browser/ui/settings/sync/sync_create_passphrase_table_view_controller.mm index 55362f9..5623ed8 100644 --- a/ios/chrome/browser/ui/settings/sync/sync_create_passphrase_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync/sync_create_passphrase_table_view_controller.mm
@@ -18,7 +18,9 @@ #error "This file requires ARC support." #endif -using namespace sync_encryption_passphrase; +using sync_encryption_passphrase::ItemTypeConfirmPassphrase; +using sync_encryption_passphrase::ItemTypeEnterPassphrase; +using sync_encryption_passphrase::SectionIdentifierPassphrase; @interface SyncCreatePassphraseTableViewController () { UITextField* confirmPassphrase_;
diff --git a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.mm b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.mm index 1a0fedf..a49bf946 100644 --- a/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.mm +++ b/ios/chrome/browser/ui/settings/sync/sync_encryption_passphrase_table_view_controller.mm
@@ -42,7 +42,11 @@ #error "This file requires ARC support." #endif -using namespace sync_encryption_passphrase; +using sync_encryption_passphrase::ItemTypeEnterPassphrase; +using sync_encryption_passphrase::ItemTypeError; +using sync_encryption_passphrase::ItemTypeFooter; +using sync_encryption_passphrase::ItemTypeMessage; +using sync_encryption_passphrase::SectionIdentifierPassphrase; namespace {
diff --git a/ios/net/cookies/system_cookie_util.h b/ios/net/cookies/system_cookie_util.h index 5759956..f8234b5 100644 --- a/ios/net/cookies/system_cookie_util.h +++ b/ios/net/cookies/system_cookie_util.h
@@ -5,6 +5,7 @@ #ifndef IOS_NET_COOKIES_SYSTEM_COOKIE_UTIL_H_ #define IOS_NET_COOKIES_SYSTEM_COOKIE_UTIL_H_ +#import <Foundation/Foundation.h> #include <stddef.h> #include "net/cookies/canonical_cookie.h" @@ -26,6 +27,10 @@ NSHTTPCookie* SystemCookieFromCanonicalCookie( const net::CanonicalCookie& cookie); +// Converts net::CookieList to NSArray<NSHTTPCookie*>. +NSArray<NSHTTPCookie*>* SystemCookiesFromCanonicalCookieList( + const net::CookieList& cookie_list); + enum CookieEvent { COOKIES_READ, // Cookies have been read from disk. COOKIES_APPLICATION_FOREGROUNDED // The application has been foregrounded.
diff --git a/ios/net/cookies/system_cookie_util.mm b/ios/net/cookies/system_cookie_util.mm index cb4dcd1..a38d323 100644 --- a/ios/net/cookies/system_cookie_util.mm +++ b/ios/net/cookies/system_cookie_util.mm
@@ -149,6 +149,15 @@ return system_cookie; } +NSArray<NSHTTPCookie*>* SystemCookiesFromCanonicalCookieList( + const net::CookieList& cookie_list) { + NSMutableArray<NSHTTPCookie*>* cookies = [[NSMutableArray alloc] init]; + for (const net::CanonicalCookie& cookie : cookie_list) { + [cookies addObject:net::SystemCookieFromCanonicalCookie(cookie)]; + } + return [cookies copy]; +} + void CheckForCookieLoss(size_t cookie_count, CookieEvent event) { NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults]; BOOL check_cookie_loss = [defaults boolForKey:kCheckCookieLossKey];
diff --git a/ios/net/cookies/system_cookie_util_unittest.mm b/ios/net/cookies/system_cookie_util_unittest.mm index d0cb069..fa53a02 100644 --- a/ios/net/cookies/system_cookie_util_unittest.mm +++ b/ios/net/cookies/system_cookie_util_unittest.mm
@@ -178,4 +178,39 @@ EXPECT_TRUE(system_cookie == nil); } +TEST_F(CookieUtil, SystemCookiesFromCanonicalCookieList) { + base::Time expire_date = base::Time::Now() + base::TimeDelta::FromHours(2); + net::CookieList cookie_list = { + net::CanonicalCookie("name1", "value1", "domain1", "path1/", + base::Time(), // creation + expire_date, + base::Time(), // last_access + false, // secure + false, // httponly + net::CookieSameSite::UNSPECIFIED, + net::COOKIE_PRIORITY_DEFAULT), + net::CanonicalCookie("name2", "value2", "domain2", "path2/", + base::Time(), // creation + expire_date, + base::Time(), // last_access + false, // secure + false, // httponly + net::CookieSameSite::UNSPECIFIED, + net::COOKIE_PRIORITY_DEFAULT), + }; + + NSArray<NSHTTPCookie*>* system_cookies = + SystemCookiesFromCanonicalCookieList(cookie_list); + + ASSERT_EQ(2UL, system_cookies.count); + EXPECT_NSEQ(@"name1", system_cookies[0].name); + EXPECT_NSEQ(@"value1", system_cookies[0].value); + EXPECT_NSEQ(@"domain1", system_cookies[0].domain); + EXPECT_NSEQ(@"path1/", system_cookies[0].path); + EXPECT_NSEQ(@"name2", system_cookies[1].name); + EXPECT_NSEQ(@"value2", system_cookies[1].value); + EXPECT_NSEQ(@"domain2", system_cookies[1].domain); + EXPECT_NSEQ(@"path2/", system_cookies[1].path); +} + } // namespace net
diff --git a/ios/web/download/BUILD.gn b/ios/web/download/BUILD.gn index 06859959..314f0f0 100644 --- a/ios/web/download/BUILD.gn +++ b/ios/web/download/BUILD.gn
@@ -8,6 +8,7 @@ deps = [ ":download_cookies", "//base", + "//ios/net", "//ios/web/net/cookies", "//ios/web/public", "//ios/web/public/download",
diff --git a/ios/web/download/download_task_impl.h b/ios/web/download/download_task_impl.h index 821d7e29..c50afbe3 100644 --- a/ios/web/download/download_task_impl.h +++ b/ios/web/download/download_task_impl.h
@@ -16,6 +16,7 @@ namespace net { class URLFetcherResponseWriter; +class URLRequestContextGetter; } namespace web { @@ -88,6 +89,12 @@ // Must be called on UI thread. The callback will be invoked on the UI thread. void GetCookies(base::Callback<void(NSArray<NSHTTPCookie*>*)> callback); + // Asynchronously returns cookies for |context_getter|. Must + // be called on IO thread. The callback will be invoked on the UI thread. + static void GetCookiesFromContextGetter( + scoped_refptr<net::URLRequestContextGetter> context_getter, + base::Callback<void(NSArray<NSHTTPCookie*>*)> callback); + // Starts the download with given cookies. void StartWithCookies(NSArray<NSHTTPCookie*>* cookies);
diff --git a/ios/web/download/download_task_impl.mm b/ios/web/download/download_task_impl.mm index b33fe6c..9f5bdbfd 100644 --- a/ios/web/download/download_task_impl.mm +++ b/ios/web/download/download_task_impl.mm
@@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/strings/sys_string_conversions.h" #include "base/task/post_task.h" +#import "ios/net/cookies/system_cookie_util.h" #import "ios/web/net/cookies/wk_cookie_util.h" #include "ios/web/public/browser_state.h" #import "ios/web/public/download/download_task_observer.h" @@ -23,7 +24,10 @@ #include "net/base/io_buffer.h" #import "net/base/mac/url_conversions.h" #include "net/base/net_errors.h" +#include "net/cookies/cookie_store.h" #include "net/url_request/url_fetcher_response_writer.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" #include "url/url_constants.h" #if !defined(__has_feature) || !__has_feature(objc_arc) @@ -402,14 +406,30 @@ void DownloadTaskImpl::GetCookies( base::Callback<void(NSArray<NSHTTPCookie*>*)> callback) { - DCHECK_CURRENTLY_ON(web::WebThread::UI); - auto store = WKCookieStoreForBrowserState(web_state_->GetBrowserState()); - DCHECK(store); - [store getAllCookies:^(NSArray<NSHTTPCookie*>* cookies) { - // getAllCookies: callback is always called on UI thread. - DCHECK_CURRENTLY_ON(WebThread::UI); - callback.Run(cookies); - }]; + DCHECK_CURRENTLY_ON(WebThread::UI); + scoped_refptr<net::URLRequestContextGetter> context_getter( + web_state_->GetBrowserState()->GetRequestContext()); + + // net::URLRequestContextGetter must be used in the IO thread. + base::PostTask(FROM_HERE, {WebThread::IO}, + base::BindOnce(&DownloadTaskImpl::GetCookiesFromContextGetter, + context_getter, callback)); +} + +void DownloadTaskImpl::GetCookiesFromContextGetter( + scoped_refptr<net::URLRequestContextGetter> context_getter, + base::Callback<void(NSArray<NSHTTPCookie*>*)> callback) { + DCHECK_CURRENTLY_ON(WebThread::IO); + context_getter->GetURLRequestContext()->cookie_store()->GetAllCookiesAsync( + base::BindOnce( + [](base::Callback<void(NSArray<NSHTTPCookie*>*)> callback, + const net::CookieList& cookie_list) { + NSArray<NSHTTPCookie*>* cookies = + SystemCookiesFromCanonicalCookieList(cookie_list); + base::PostTask(FROM_HERE, {WebThread::UI}, + base::BindOnce(callback, cookies)); + }, + callback)); } void DownloadTaskImpl::StartWithCookies(NSArray<NSHTTPCookie*>* cookies) {
diff --git a/ios/web/download/download_task_impl_unittest.mm b/ios/web/download/download_task_impl_unittest.mm index e8a4a936..62dfb86 100644 --- a/ios/web/download/download_task_impl_unittest.mm +++ b/ios/web/download/download_task_impl_unittest.mm
@@ -18,11 +18,14 @@ #import "base/test/ios/wait_util.h" #import "ios/web/net/cookies/wk_cookie_util.h" #import "ios/web/public/download/download_task_observer.h" +#include "ios/web/public/test/fakes/fake_cookie_store.h" #import "ios/web/public/test/fakes/test_web_state.h" #include "ios/web/public/test/web_test.h" #import "ios/web/test/fakes/crw_fake_nsurl_session_task.h" #include "net/base/net_errors.h" #include "net/url_request/url_fetcher_response_writer.h" +#include "net/url_request/url_request_context.h" +#include "net/url_request/url_request_context_getter.h" #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest_mac.h" @@ -134,6 +137,9 @@ session_delegate_callbacks_queue_( dispatch_queue_create(nullptr, DISPATCH_QUEUE_SERIAL)) { browser_state_.SetOffTheRecord(true); + browser_state_.GetRequestContext() + ->GetURLRequestContext() + ->set_cookie_store(&cookie_store_); web_state_.SetBrowserState(&browser_state_); task_->AddObserver(&task_observer_); } @@ -164,20 +170,6 @@ return Start(std::make_unique<net::URLFetcherStringWriter>()); } - // Sets cookie for the test browser state. - bool SetCookie(NSHTTPCookie* cookie) WARN_UNUSED_RESULT - API_AVAILABLE(ios(11.0)) { - auto store = web::WKCookieStoreForBrowserState(&browser_state_); - __block bool cookie_was_set = false; - [store setCookie:cookie - completionHandler:^{ - cookie_was_set = true; - }]; - return WaitUntilConditionOrTimeout(kWaitForCookiesTimeout, ^{ - return cookie_was_set; - }); - } - // Session and session delegate injected into DownloadTaskImpl for testing. NSURLSession* session() { return task_delegate_.session(); } id<NSURLSessionDataDelegate> session_delegate() { @@ -222,6 +214,7 @@ web::WebTaskEnvironment task_environment_; TestBrowserState browser_state_; TestWebState web_state_; + FakeCookieStore cookie_store_; testing::StrictMock<FakeDownloadTaskImplDelegate> task_delegate_; std::unique_ptr<DownloadTaskImpl> task_; MockDownloadTaskObserver task_observer_; @@ -544,23 +537,28 @@ // Tests that CreateSession is called with the correct cookies from the cookie // store. TEST_F(DownloadTaskImplTest, Cookie) { - // Add a cookie to BrowserState. - NSURL* cookie_url = [NSURL URLWithString:@(kUrl)]; - NSHTTPCookie* cookie = [NSHTTPCookie cookieWithProperties:@{ - NSHTTPCookieName : @"name", - NSHTTPCookieValue : @"value", - NSHTTPCookiePath : cookie_url.path, - NSHTTPCookieDomain : cookie_url.host, - NSHTTPCookieVersion : @1, - }]; - ASSERT_TRUE(SetCookie(cookie)); + GURL cookie_url(kUrl); + base::Time now = base::Time::Now(); + net::CanonicalCookie expected_cookie( + "name", "value", cookie_url.host(), cookie_url.path(), + /*creation=*/now, + /*expire_date=*/now + base::TimeDelta::FromHours(2), + /*last_access=*/now, + /*secure=*/false, + /*httponly=*/false, net::CookieSameSite::UNSPECIFIED, + net::COOKIE_PRIORITY_DEFAULT); + cookie_store_.SetAllCookies({expected_cookie}); // Start the download and make sure that all cookie from BrowserState were // picked up. EXPECT_CALL(task_observer_, OnDownloadUpdated(task_.get())); ASSERT_TRUE(Start()); + EXPECT_EQ(1U, task_delegate_.cookies().count); - EXPECT_NSEQ(cookie, task_delegate_.cookies().firstObject); + NSHTTPCookie* actual_cookie = task_delegate_.cookies().firstObject; + EXPECT_NSEQ(@"name", actual_cookie.name); + EXPECT_NSEQ(@"value", actual_cookie.value); + EXPECT_CALL(task_delegate_, OnTaskDestroyed(task_.get())); }
diff --git a/ios/web/public/test/fakes/BUILD.gn b/ios/web/public/test/fakes/BUILD.gn index 0c9fd36..b886d04e 100644 --- a/ios/web/public/test/fakes/BUILD.gn +++ b/ios/web/public/test/fakes/BUILD.gn
@@ -22,6 +22,7 @@ "//ios/web/test:test_constants", "//ios/web/web_state/ui:crw_web_view_navigation_proxy", "//ios/web/webui:webui", + "//net", "//net:test_support", "//testing/gtest", "//ui/base", @@ -38,6 +39,8 @@ "crw_fake_web_state_policy_decider.mm", "crw_test_web_state_observer.h", "crw_test_web_state_observer.mm", + "fake_cookie_store.cc", + "fake_cookie_store.h", "fake_download_controller_delegate.h", "fake_download_controller_delegate.mm", "fake_download_task.h",
diff --git a/ios/web/public/test/fakes/fake_cookie_store.cc b/ios/web/public/test/fakes/fake_cookie_store.cc new file mode 100644 index 0000000..3944008 --- /dev/null +++ b/ios/web/public/test/fakes/fake_cookie_store.cc
@@ -0,0 +1,84 @@ +// Copyright 2019 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 "ios/web/public/test/fakes/fake_cookie_store.h" + +#include "base/task/post_task.h" +#include "ios/web/public/thread/web_task_traits.h" +#include "ios/web/public/thread/web_thread.h" + +namespace web { + +FakeCookieStore::FakeCookieStore() {} + +FakeCookieStore::~FakeCookieStore() {} + +void FakeCookieStore::SetAllCookies(const net::CookieList& all_cookies) { + all_cookies_ = all_cookies; +} + +void FakeCookieStore::GetAllCookiesAsync(GetAllCookiesCallback callback) { + DCHECK_CURRENTLY_ON(WebThread::IO); + base::PostTask(FROM_HERE, {WebThread::IO}, + base::BindOnce(std::move(callback), all_cookies_)); +} + +void FakeCookieStore::SetCanonicalCookieAsync( + std::unique_ptr<net::CanonicalCookie> cookie, + std::string source_scheme, + const net::CookieOptions& options, + SetCookiesCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::GetCookieListWithOptionsAsync( + const GURL& url, + const net::CookieOptions& options, + GetCookieListCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::DeleteCanonicalCookieAsync( + const net::CanonicalCookie& cookie, + DeleteCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::DeleteAllCreatedInTimeRangeAsync( + const net::CookieDeletionInfo::TimeRange& creation_range, + DeleteCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::DeleteAllMatchingInfoAsync( + net::CookieDeletionInfo delete_info, + DeleteCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::DeleteSessionCookiesAsync(DeleteCallback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::FlushStore(base::OnceClosure callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +void FakeCookieStore::SetCookieableSchemes( + const std::vector<std::string>& schemes, + SetCookieableSchemesCallback callback) { + NOTIMPLEMENTED() << "Implement this if necessary."; +} + +net::CookieChangeDispatcher& FakeCookieStore::GetChangeDispatcher() { + // This is NOTREACHED not NOTIMPLEMENTED because it would likely cause a weird + // SEGV in the next line anyways. Crashing here with a more friendly error + // message is preferred. + NOTREACHED() << "Not implemented. Implement this if necessary."; + // Perform a crazy thing here just to make the compiler happy. It doesn't + // matter because it should never reach here. + return *reinterpret_cast<net::CookieChangeDispatcher*>(this); +} + +} // namespace web
diff --git a/ios/web/public/test/fakes/fake_cookie_store.h b/ios/web/public/test/fakes/fake_cookie_store.h new file mode 100644 index 0000000..6f99eaf --- /dev/null +++ b/ios/web/public/test/fakes/fake_cookie_store.h
@@ -0,0 +1,53 @@ +// Copyright 2019 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_WEB_PUBLIC_TEST_FAKES_FAKE_COOKIE_STORE_H_ +#define IOS_WEB_PUBLIC_TEST_FAKES_FAKE_COOKIE_STORE_H_ + +#include "net/cookies/cookie_store.h" + +namespace web { + +// Fake implementation for net::CookieStore interface. Can be used for testing. +class FakeCookieStore : public net::CookieStore { + public: + FakeCookieStore(); + ~FakeCookieStore() override; + + /// Sets cookies returned by GetAllCookiesAsync(). + void SetAllCookies(const net::CookieList& all_cookies); + + void GetAllCookiesAsync(GetAllCookiesCallback callback) override; + + // Methods below have not been implemented in this fake. Implement them when + // necessary. + + void SetCanonicalCookieAsync(std::unique_ptr<net::CanonicalCookie> cookie, + std::string source_scheme, + const net::CookieOptions& options, + SetCookiesCallback callback) override; + void GetCookieListWithOptionsAsync(const GURL& url, + const net::CookieOptions& options, + GetCookieListCallback callback) override; + void DeleteCanonicalCookieAsync(const net::CanonicalCookie& cookie, + DeleteCallback callback) override; + void DeleteAllCreatedInTimeRangeAsync( + const net::CookieDeletionInfo::TimeRange& creation_range, + DeleteCallback callback) override; + void DeleteAllMatchingInfoAsync(net::CookieDeletionInfo delete_info, + DeleteCallback callback) override; + void DeleteSessionCookiesAsync(DeleteCallback) override; + void FlushStore(base::OnceClosure callback) override; + void SetCookieableSchemes(const std::vector<std::string>& schemes, + SetCookieableSchemesCallback callback) override; + net::CookieChangeDispatcher& GetChangeDispatcher() override; + + private: + net::CookieList all_cookies_; + net::CookieStatusList excluded_list_; +}; + +} // namespace web + +#endif // IOS_WEB_PUBLIC_TEST_FAKES_FAKE_COOKIE_STORE_H_
diff --git a/media/base/mac/video_frame_mac_unittests.cc b/media/base/mac/video_frame_mac_unittests.cc index abe9e5142..86ecdf5 100644 --- a/media/base/mac/video_frame_mac_unittests.cc +++ b/media/base/mac/video_frame_mac_unittests.cc
@@ -94,7 +94,7 @@ int instances_destroyed = 0; auto wrapper_frame = VideoFrame::WrapVideoFrame( - *frame, frame->format(), frame->visible_rect(), frame->natural_size()); + frame, frame->format(), frame->visible_rect(), frame->natural_size()); wrapper_frame->AddDestructionObserver( base::Bind(&Increment, &instances_destroyed)); ASSERT_TRUE(wrapper_frame.get());
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc index e6957b81..2191c10c 100644 --- a/media/base/video_frame.cc +++ b/media/base/video_frame.cc
@@ -617,60 +617,61 @@ // static scoped_refptr<VideoFrame> VideoFrame::WrapVideoFrame( - const VideoFrame& frame, + scoped_refptr<VideoFrame> frame, VideoPixelFormat format, const gfx::Rect& visible_rect, const gfx::Size& natural_size) { - // Frames with textures need mailbox info propagated, and there's no support - // for that here yet, see http://crbug/362521. - CHECK(!frame.HasTextures()); - DCHECK(frame.visible_rect().Contains(visible_rect)); + DCHECK(frame->visible_rect().Contains(visible_rect)); // The following storage type should not be wrapped as the shared region // cannot be owned by both the wrapped frame and the wrapping frame. - DCHECK(frame.storage_type() != STORAGE_MOJO_SHARED_BUFFER); + // + // TODO: We can support this now since we have a reference to the wrapped + // frame through |wrapped_frame_|. + DCHECK(frame->storage_type() != STORAGE_MOJO_SHARED_BUFFER); - if (!AreValidPixelFormatsForWrap(frame.format(), format)) { + if (!AreValidPixelFormatsForWrap(frame->format(), format)) { DLOG(ERROR) << __func__ << " Invalid format conversion." - << VideoPixelFormatToString(frame.format()) << " to " + << VideoPixelFormatToString(frame->format()) << " to " << VideoPixelFormatToString(format); return nullptr; } - if (!IsValidConfig(format, frame.storage_type(), frame.coded_size(), + if (!IsValidConfig(format, frame->storage_type(), frame->coded_size(), visible_rect, natural_size)) { DLOG(ERROR) << __func__ << " Invalid config." - << ConfigToString(format, frame.storage_type(), - frame.coded_size(), visible_rect, + << ConfigToString(format, frame->storage_type(), + frame->coded_size(), visible_rect, natural_size); return nullptr; } scoped_refptr<VideoFrame> wrapping_frame( - new VideoFrame(frame.layout(), frame.storage_type(), visible_rect, - natural_size, frame.timestamp())); + new VideoFrame(frame->layout(), frame->storage_type(), visible_rect, + natural_size, frame->timestamp())); - // Copy all metadata to the wrapped frame. - wrapping_frame->metadata()->MergeMetadataFrom(frame.metadata()); + // Copy all metadata to the wrapped frame-> + wrapping_frame->metadata()->MergeMetadataFrom(frame->metadata()); - if (frame.IsMappable()) { + if (frame->IsMappable()) { for (size_t i = 0; i < NumPlanes(format); ++i) { - wrapping_frame->data_[i] = frame.data_[i]; + wrapping_frame->data_[i] = frame->data_[i]; } } #if defined(OS_LINUX) - DCHECK(frame.dmabuf_fds_); + DCHECK(frame->dmabuf_fds_); // If there are any |dmabuf_fds_| plugged in, we should refer them too. - wrapping_frame->dmabuf_fds_ = frame.dmabuf_fds_; + wrapping_frame->dmabuf_fds_ = frame->dmabuf_fds_; #endif - if (frame.storage_type() == STORAGE_SHMEM) { - DCHECK(frame.shm_region_ && frame.shm_region_->IsValid()); - wrapping_frame->BackWithSharedMemory(frame.shm_region_, - frame.shared_memory_offset()); + if (frame->storage_type() == STORAGE_SHMEM) { + DCHECK(frame->shm_region_ && frame->shm_region_->IsValid()); + wrapping_frame->BackWithSharedMemory(frame->shm_region_, + frame->shared_memory_offset()); } + wrapping_frame->wrapped_frame_ = std::move(frame); return wrapping_frame; } @@ -906,16 +907,19 @@ } bool VideoFrame::HasTextures() const { - return !mailbox_holders_[0].mailbox.IsZero(); + return wrapped_frame_ ? wrapped_frame_->HasTextures() + : !mailbox_holders_[0].mailbox.IsZero(); } size_t VideoFrame::NumTextures() const { if (!HasTextures()) return 0; + const auto& mailbox_holders = + wrapped_frame_ ? wrapped_frame_->mailbox_holders_ : mailbox_holders_; size_t i = 0; for (; i < NumPlanes(format()); ++i) { - if (mailbox_holders_[i].mailbox.IsZero()) { + if (mailbox_holders[i].mailbox.IsZero()) { return i; } } @@ -923,11 +927,13 @@ } bool VideoFrame::HasGpuMemoryBuffer() const { - return !!gpu_memory_buffer_; + return wrapped_frame_ ? wrapped_frame_->HasGpuMemoryBuffer() + : !!gpu_memory_buffer_; } gfx::GpuMemoryBuffer* VideoFrame::GetGpuMemoryBuffer() const { - return gpu_memory_buffer_.get(); + return wrapped_frame_ ? wrapped_frame_->GetGpuMemoryBuffer() + : gpu_memory_buffer_.get(); } gfx::ColorSpace VideoFrame::ColorSpace() const { @@ -970,7 +976,8 @@ VideoFrame::mailbox_holder(size_t texture_index) const { DCHECK(HasTextures()); DCHECK(IsValidPlane(texture_index, format())); - return mailbox_holders_[texture_index]; + return wrapped_frame_ ? wrapped_frame_->mailbox_holders_[texture_index] + : mailbox_holders_[texture_index]; } #if defined(OS_LINUX) @@ -1000,11 +1007,16 @@ void VideoFrame::SetReleaseMailboxCB(ReleaseMailboxCB release_mailbox_cb) { DCHECK(release_mailbox_cb); DCHECK(!mailbox_holders_release_cb_); + // We don't relay SetReleaseMailboxCB to |wrapped_frame_| because the method + // is not thread safe. This method should only be called by the owner of + // |wrapped_frame_| directly. + DCHECK(!wrapped_frame_); mailbox_holders_release_cb_ = std::move(release_mailbox_cb); } bool VideoFrame::HasReleaseMailboxCB() const { - return !!mailbox_holders_release_cb_; + return wrapped_frame_ ? wrapped_frame_->HasReleaseMailboxCB() + : !!mailbox_holders_release_cb_; } void VideoFrame::AddDestructionObserver(base::OnceClosure callback) { @@ -1014,6 +1026,9 @@ gpu::SyncToken VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { DCHECK(HasTextures()); + if (wrapped_frame_) { + return wrapped_frame_->UpdateReleaseSyncToken(client); + } base::AutoLock locker(release_sync_token_lock_); // Must wait on the previous sync point before inserting a new sync point so // that |mailbox_holders_release_cb_| guarantees the previous sync point
diff --git a/media/base/video_frame.h b/media/base/video_frame.h index d955bd7..641caade 100644 --- a/media/base/video_frame.h +++ b/media/base/video_frame.h
@@ -281,7 +281,7 @@ // Wraps |frame|. |visible_rect| must be a sub rect within // frame->visible_rect(). static scoped_refptr<VideoFrame> WrapVideoFrame( - const VideoFrame& frame, + scoped_refptr<VideoFrame> frame, VideoPixelFormat format, const gfx::Rect& visible_rect, const gfx::Size& natural_size); @@ -617,6 +617,10 @@ // VideFrameLayout (includes format, coded_size, and strides). const VideoFrameLayout layout_; + // Set by WrapVideoFrame to soft-apply a new set of format, visible rectangle, + // and natural size on |wrapped_frame_| + scoped_refptr<VideoFrame> wrapped_frame_; + // Storage type for the different planes. StorageType storage_type_; // TODO(mcasas): make const
diff --git a/media/base/video_frame_pool.cc b/media/base/video_frame_pool.cc index 16156e9..b70a1f3 100644 --- a/media/base/video_frame_pool.cc +++ b/media/base/video_frame_pool.cc
@@ -111,7 +111,7 @@ } scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame( - *frame, frame->format(), frame->visible_rect(), frame->natural_size()); + frame, frame->format(), frame->visible_rect(), frame->natural_size()); wrapped_frame->AddDestructionObserver(base::Bind( &VideoFramePool::PoolImpl::FrameReleased, this, std::move(frame))); return wrapped_frame;
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc index a7f3008..b17866d 100644 --- a/media/base/video_frame_unittest.cc +++ b/media/base/video_frame_unittest.cc
@@ -260,8 +260,7 @@ } } -static void FrameNoLongerNeededCallback(scoped_refptr<media::VideoFrame> frame, - bool* triggered) { +static void FrameNoLongerNeededCallback(bool* triggered) { *triggered = true; } @@ -282,9 +281,9 @@ wrapped_frame->metadata()->SetTimeDelta( media::VideoFrameMetadata::FRAME_DURATION, kFrameDuration); frame = media::VideoFrame::WrapVideoFrame( - *wrapped_frame, wrapped_frame->format(), visible_rect, natural_size); - frame->AddDestructionObserver(base::Bind( - &FrameNoLongerNeededCallback, wrapped_frame, &done_callback_was_run)); + wrapped_frame, wrapped_frame->format(), visible_rect, natural_size); + wrapped_frame->AddDestructionObserver( + base::Bind(&FrameNoLongerNeededCallback, &done_callback_was_run)); EXPECT_EQ(wrapped_frame->coded_size(), frame->coded_size()); EXPECT_EQ(wrapped_frame->data(media::VideoFrame::kYPlane), frame->data(media::VideoFrame::kYPlane)); @@ -308,6 +307,7 @@ frame->metadata()->HasKey(media::VideoFrameMetadata::FRAME_DURATION)); } + // Verify that |wrapped_frame| outlives |frame|. EXPECT_FALSE(done_callback_was_run); frame = NULL; EXPECT_TRUE(done_callback_was_run); @@ -454,13 +454,13 @@ // Wrapped DMABUF frames must share the same memory as their wrappee. auto wrapped_frame = VideoFrame::WrapVideoFrame( - *frame, frame->format(), visible_rect, visible_rect.size()); + frame, frame->format(), visible_rect, visible_rect.size()); ASSERT_NE(wrapped_frame, nullptr); ASSERT_EQ(wrapped_frame->IsSameDmaBufsAs(*frame), true); // Multi-level wrapping should share same memory as well. auto wrapped_frame2 = VideoFrame::WrapVideoFrame( - *wrapped_frame, frame->format(), visible_rect, visible_rect.size()); + wrapped_frame, frame->format(), visible_rect, visible_rect.size()); ASSERT_NE(wrapped_frame2, nullptr); ASSERT_EQ(wrapped_frame2->IsSameDmaBufsAs(*wrapped_frame), true); ASSERT_EQ(wrapped_frame2->IsSameDmaBufsAs(*frame), true);
diff --git a/media/base/video_util.cc b/media/base/video_util.cc index 8f4e0c22..e97350a 100644 --- a/media/base/video_util.cc +++ b/media/base/video_util.cc
@@ -17,9 +17,6 @@ namespace { -// Empty method used for keeping a reference to the original media::VideoFrame. -void ReleaseOriginalFrame(scoped_refptr<media::VideoFrame> frame) {} - // Helper to apply padding to the region outside visible rect up to the coded // size with the repeated last column / row of the visible rect. void FillRegionOutsideVisibleRect(uint8_t* data, @@ -428,13 +425,11 @@ DCHECK_EQ(PIXEL_FORMAT_I420A, frame->format()); scoped_refptr<media::VideoFrame> wrapped_frame = - media::VideoFrame::WrapVideoFrame(*frame, PIXEL_FORMAT_I420, + media::VideoFrame::WrapVideoFrame(frame, PIXEL_FORMAT_I420, frame->visible_rect(), frame->natural_size()); if (!wrapped_frame) return nullptr; - wrapped_frame->AddDestructionObserver( - base::BindOnce(&ReleaseOriginalFrame, std::move(frame))); return wrapped_frame; }
diff --git a/media/gpu/linux/platform_video_frame_pool.cc b/media/gpu/linux/platform_video_frame_pool.cc index 9dde20e..91c750d9 100644 --- a/media/gpu/linux/platform_video_frame_pool.cc +++ b/media/gpu/linux/platform_video_frame_pool.cc
@@ -84,7 +84,7 @@ DCHECK_EQ(origin_frame->coded_size(), coded_size); scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame( - *origin_frame, format, visible_rect_, natural_size_); + origin_frame, format, visible_rect_, natural_size_); DCHECK(wrapped_frame); frames_in_use_.emplace(GetDmabufId(*wrapped_frame), origin_frame.get()); wrapped_frame->AddDestructionObserver(
diff --git a/media/gpu/linux/platform_video_frame_pool_unittest.cc b/media/gpu/linux/platform_video_frame_pool_unittest.cc index 00d90fc..9b76824 100644 --- a/media/gpu/linux/platform_video_frame_pool_unittest.cc +++ b/media/gpu/linux/platform_video_frame_pool_unittest.cc
@@ -164,7 +164,7 @@ SetFrameFormat(PIXEL_FORMAT_I420); scoped_refptr<VideoFrame> frame_1 = GetFrame(10); scoped_refptr<VideoFrame> frame_2 = VideoFrame::WrapVideoFrame( - *frame_1, frame_1->format(), frame_1->visible_rect(), + frame_1, frame_1->format(), frame_1->visible_rect(), frame_1->natural_size()); EXPECT_EQ(pool_->UnwrapFrame(*frame_1), pool_->UnwrapFrame(*frame_2)); EXPECT_TRUE(frame_1->IsSameDmaBufsAs(*frame_2));
diff --git a/media/gpu/test/texture_ref.cc b/media/gpu/test/texture_ref.cc index 6cac302..63b17b0 100644 --- a/media/gpu/test/texture_ref.cc +++ b/media/gpu/test/texture_ref.cc
@@ -75,7 +75,7 @@ scoped_refptr<VideoFrame> TextureRef::ExportVideoFrame( gfx::Rect visible_rect) const { #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) - return VideoFrame::WrapVideoFrame(*frame_, frame_->format(), visible_rect, + return VideoFrame::WrapVideoFrame(frame_, frame_->format(), visible_rect, visible_rect.size()); #else return nullptr;
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.cc b/media/gpu/test/video_player/test_vda_video_decoder.cc index 5343d5a..e8bf41ba 100644 --- a/media/gpu/test/video_player/test_vda_video_decoder.cc +++ b/media/gpu/test/video_player/test_vda_video_decoder.cc
@@ -294,7 +294,7 @@ // new video frame using the same mailbox. if (!video_frame->HasTextures()) { wrapped_video_frame = VideoFrame::WrapVideoFrame( - *video_frame, video_frame->format(), picture.visible_rect(), + video_frame, video_frame->format(), picture.visible_rect(), picture.visible_rect().size()); } else { gpu::MailboxHolder mailbox_holders[media::VideoFrame::kMaxPlanes]; @@ -319,15 +319,13 @@ // (e.g. on a resolution change). base::OnceClosure reuse_cb = BindToCurrentLoop( base::BindOnce(&TestVDAVideoDecoder::ReusePictureBufferTask, weak_this_, - picture.picture_buffer_id(), video_frame)); + picture.picture_buffer_id())); wrapped_video_frame->AddDestructionObserver(std::move(reuse_cb)); output_cb_.Run(std::move(wrapped_video_frame)); } // Called when a picture buffer is ready to be re-used. -void TestVDAVideoDecoder::ReusePictureBufferTask( - int32_t picture_buffer_id, - scoped_refptr<VideoFrame> /*video_frame*/) { +void TestVDAVideoDecoder::ReusePictureBufferTask(int32_t picture_buffer_id) { DCHECK_CALLED_ON_VALID_SEQUENCE(vda_wrapper_sequence_checker_); DCHECK(decoder_); DVLOGF(4) << "Picture buffer ID: " << picture_buffer_id;
diff --git a/media/gpu/test/video_player/test_vda_video_decoder.h b/media/gpu/test/video_player/test_vda_video_decoder.h index f439d3c..bda6726c 100644 --- a/media/gpu/test/video_player/test_vda_video_decoder.h +++ b/media/gpu/test/video_player/test_vda_video_decoder.h
@@ -71,8 +71,7 @@ uint32_t texture_target) override; void DismissPictureBuffer(int32_t picture_buffer_id) override; void PictureReady(const Picture& picture) override; - void ReusePictureBufferTask(int32_t picture_buffer_id, - scoped_refptr<VideoFrame> video_frame); + void ReusePictureBufferTask(int32_t picture_buffer_id); void NotifyEndOfBitstreamBuffer(int32_t bitstream_buffer_id) override; void NotifyFlushDone() override; void NotifyResetDone() override;
diff --git a/media/gpu/v4l2/v4l2_image_processor.cc b/media/gpu/v4l2/v4l2_image_processor.cc index 739bf920..04e5cdb 100644 --- a/media/gpu/v4l2/v4l2_image_processor.cc +++ b/media/gpu/v4l2/v4l2_image_processor.cc
@@ -758,7 +758,7 @@ { const auto& orig_frame = buffer->GetVideoFrame(); output_frame = VideoFrame::WrapVideoFrame( - *orig_frame, orig_frame->format(), orig_frame->visible_rect(), + orig_frame, orig_frame->format(), orig_frame->visible_rect(), orig_frame->natural_size()); output_frame->AddDestructionObserver(BindToCurrentLoop( base::BindOnce(&V4L2ImageProcessor::V4L2VFDestructionObserver,
diff --git a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc index a3313c4c..4afafc5b 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decode_accelerator.cc
@@ -2187,8 +2187,8 @@ // We will set a destruction observer to the output frame, so wrap the // imported frame into another one that we can destruct. scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame( - *output_frame.get(), output_frame->format(), - output_frame->visible_rect(), output_frame->coded_size()); + output_frame, output_frame->format(), output_frame->visible_rect(), + output_frame->coded_size()); DCHECK(output_frame != nullptr); image_processor_->Process(
diff --git a/media/gpu/v4l2/v4l2_slice_video_decoder.cc b/media/gpu/v4l2/v4l2_slice_video_decoder.cc index 63b0c41..da4ba41b 100644 --- a/media/gpu/v4l2/v4l2_slice_video_decoder.cc +++ b/media/gpu/v4l2/v4l2_slice_video_decoder.cc
@@ -1061,10 +1061,8 @@ frame->timestamp() != timestamp) { gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_); scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame( - *frame, frame->format(), visible_rect, natural_size); + frame, frame->format(), visible_rect, natural_size); wrapped_frame->set_timestamp(timestamp); - wrapped_frame->AddDestructionObserver(base::BindOnce( - base::DoNothing::Once<scoped_refptr<VideoFrame>>(), std::move(frame))); frame = std::move(wrapped_frame); }
diff --git a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc index ee49c63..43f8c985 100644 --- a/media/gpu/v4l2/v4l2_video_encode_accelerator.cc +++ b/media/gpu/v4l2/v4l2_video_encode_accelerator.cc
@@ -728,7 +728,7 @@ if (image_processor_->output_mode() == ImageProcessor::OutputMode::IMPORT) { const auto& buf = image_processor_output_buffers_[output_buffer_index]; auto output_frame = VideoFrame::WrapVideoFrame( - *buf, buf->format(), buf->visible_rect(), buf->natural_size()); + buf, buf->format(), buf->visible_rect(), buf->natural_size()); // Unretained(this) is safe here, because image_processor is destroyed // before video_encoder_thread stops.
diff --git a/media/gpu/vaapi/vaapi_video_decoder.cc b/media/gpu/vaapi/vaapi_video_decoder.cc index cf4f0ac..37b7b40b 100644 --- a/media/gpu/vaapi/vaapi_video_decoder.cc +++ b/media/gpu/vaapi/vaapi_video_decoder.cc
@@ -481,11 +481,8 @@ video_frame->timestamp() != timestamp) { gfx::Size natural_size = GetNaturalSize(visible_rect, pixel_aspect_ratio_); scoped_refptr<VideoFrame> wrapped_frame = VideoFrame::WrapVideoFrame( - *video_frame, video_frame->format(), visible_rect, natural_size); + video_frame, video_frame->format(), visible_rect, natural_size); wrapped_frame->set_timestamp(timestamp); - wrapped_frame->AddDestructionObserver( - base::BindOnce(base::DoNothing::Once<scoped_refptr<VideoFrame>>(), - std::move(video_frame))); video_frame = std::move(wrapped_frame); }
diff --git a/media/mojo/mojom/cdm_proxy.mojom b/media/mojo/mojom/cdm_proxy.mojom index b9170bb4..d503763 100644 --- a/media/mojo/mojom/cdm_proxy.mojom +++ b/media/mojo/mojom/cdm_proxy.mojom
@@ -27,10 +27,11 @@ // If the proxy created a crypto session, then the ID for the crypto session // is |crypto_session_id|. // |cdm_id| can be used to connect the remote media pipeline and CdmProxy. - Initialize(associated CdmProxyClient client) => (Status status, - Protocol protocol, - uint32 crypto_session_id, - int32 cdm_id); + Initialize(pending_associated_remote<CdmProxyClient> client) + => (Status status, + Protocol protocol, + uint32 crypto_session_id, + int32 cdm_id); // Processes and updates the state of the proxy. // |func| specifies what type of function to use.
diff --git a/media/mojo/services/mojo_cdm_proxy_service.cc b/media/mojo/services/mojo_cdm_proxy_service.cc index ac7866e..1c74993 100644 --- a/media/mojo/services/mojo_cdm_proxy_service.cc +++ b/media/mojo/services/mojo_cdm_proxy_service.cc
@@ -27,7 +27,7 @@ } void MojoCdmProxyService::Initialize( - mojom::CdmProxyClientAssociatedPtrInfo client, + mojo::PendingAssociatedRemote<mojom::CdmProxyClient> client, InitializeCallback callback) { DVLOG(2) << __func__;
diff --git a/media/mojo/services/mojo_cdm_proxy_service.h b/media/mojo/services/mojo_cdm_proxy_service.h index 1ee107c..e8eaa95 100644 --- a/media/mojo/services/mojo_cdm_proxy_service.h +++ b/media/mojo/services/mojo_cdm_proxy_service.h
@@ -16,6 +16,8 @@ #include "media/cdm/cdm_proxy.h" #include "media/mojo/mojom/cdm_proxy.mojom.h" #include "media/mojo/services/media_mojo_export.h" +#include "mojo/public/cpp/bindings/associated_remote.h" +#include "mojo/public/cpp/bindings/pending_associated_remote.h" namespace media { @@ -31,7 +33,7 @@ ~MojoCdmProxyService() final; // mojom::CdmProxy implementation. - void Initialize(mojom::CdmProxyClientAssociatedPtrInfo client, + void Initialize(mojo::PendingAssociatedRemote<mojom::CdmProxyClient> client, InitializeCallback callback) final; void Process(media::CdmProxy::Function function, uint32_t crypto_session_id, @@ -69,7 +71,7 @@ std::unique_ptr<::media::CdmProxy> cdm_proxy_; MojoCdmServiceContext* const context_ = nullptr; - mojom::CdmProxyClientAssociatedPtr client_; + mojo::AssociatedRemote<mojom::CdmProxyClient> client_; // Set to a valid CDM ID if the |cdm_proxy_| is successfully initialized. int cdm_id_ = CdmContext::kInvalidCdmId;
diff --git a/media/test/pipeline_integration_test.cc b/media/test/pipeline_integration_test.cc index fa6b68e..399000229c 100644 --- a/media/test/pipeline_integration_test.cc +++ b/media/test/pipeline_integration_test.cc
@@ -904,7 +904,15 @@ OnSelectedVideoTrackChanged(MediaTrack::Id("1")); } -TEST_F(PipelineIntegrationTest, TrackStatusChangesWhileSuspended) { +// TODO(https://crbug.com/1009964): Enable test when MacOS flake is fixed. +#if defined(OS_MACOSX) +#define MAYBE_TrackStatusChangesWhileSuspended \ + DISABLED_TrackStatusChangesWhileSuspended +#else +#define MAYBE_TrackStatusChangesWhileSuspended TrackStatusChangesWhileSuspended +#endif + +TEST_F(PipelineIntegrationTest, MAYBE_TrackStatusChangesWhileSuspended) { ASSERT_EQ(PIPELINE_OK, Start("bear-320x240.webm", kNoClockless)); Play();
diff --git a/rlz/chromeos/lib/rlz_value_store_chromeos.cc b/rlz/chromeos/lib/rlz_value_store_chromeos.cc index d8fdf8ab..c35dd1a 100644 --- a/rlz/chromeos/lib/rlz_value_store_chromeos.cc +++ b/rlz/chromeos/lib/rlz_value_store_chromeos.cc
@@ -21,7 +21,7 @@ #include "base/strings/string_piece.h" #include "base/values.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/debug_daemon_client.h" #include "chromeos/system/factory_ping_embargo_check.h" #include "chromeos/system/statistics_provider.h" #include "dbus/bus.h"
diff --git a/rlz/lib/rlz_lib_test.cc b/rlz/lib/rlz_lib_test.cc index b99171a..1d9183a 100644 --- a/rlz/lib/rlz_lib_test.cc +++ b/rlz/lib/rlz_lib_test.cc
@@ -53,7 +53,7 @@ #include "base/files/important_file_writer.h" #include "base/stl_util.h" #include "chromeos/dbus/dbus_thread_manager.h" -#include "chromeos/dbus/fake_debug_daemon_client.h" +#include "chromeos/dbus/debug_daemon/fake_debug_daemon_client.h" #include "rlz/chromeos/lib/rlz_value_store_chromeos.h" #endif
diff --git a/testing/buildbot/chromium.gpu.fyi.json b/testing/buildbot/chromium.gpu.fyi.json index 773dc482..152276c 100644 --- a/testing/buildbot/chromium.gpu.fyi.json +++ b/testing/buildbot/chromium.gpu.fyi.json
@@ -13660,6 +13660,36 @@ }, { "args": [ + "--enable-gpu", + "--test-launcher-bot-mode", + "--test-launcher-jobs=1", + "--gtest_filter=CastStreamingApiTestWithPixelOutput.EndToEnd*:TabCaptureApiPixelTest.EndToEnd*" + ], + "merge": { + "args": [], + "script": "//testing/merge_scripts/standard_gtest_merge.py" + }, + "name": "tab_capture_end2end_tests", + "swarming": { + "can_use_on_swarming_builders": true, + "containment_type": "AUTO", + "dimension_sets": [ + { + "gpu": "8086:0a2e", + "os": "mac-intel-stable" + }, + { + "gpu": "1002:6821", + "hidpi": "1", + "os": "mac-amd-stable", + "pool": "Chrome-GPU" + } + ] + }, + "test": "browser_tests" + }, + { + "args": [ "--use-gpu-in-tests", "--use-cmd-decoder=validating" ],
diff --git a/testing/buildbot/test_suite_exceptions.pyl b/testing/buildbot/test_suite_exceptions.pyl index af4c1cb..cd6fbed4 100644 --- a/testing/buildbot/test_suite_exceptions.pyl +++ b/testing/buildbot/test_suite_exceptions.pyl
@@ -1414,8 +1414,6 @@ 'Linux FYI SkiaRenderer Vulkan (Intel HD 630)', 'Linux FYI SkiaRenderer Vulkan (NVIDIA)', 'Linux Release (NVIDIA)', - # Fails on Mac ASAN due to crbug.com/1008508 - 'Mac FYI GPU ASAN Release', ], }, 'telemetry_perf_unittests': {
diff --git a/testing/variations/fieldtrial_testing_config.json b/testing/variations/fieldtrial_testing_config.json index e80e933..ccea4a0 100644 --- a/testing/variations/fieldtrial_testing_config.json +++ b/testing/variations/fieldtrial_testing_config.json
@@ -1605,6 +1605,52 @@ ] } ], + "ClickToCallV2Receiver": [ + { + "platforms": [ + "android" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ClickToCallOpenDialerDirectly" + ] + } + ] + } + ], + "ClickToCallV2Sender": [ + { + "platforms": [ + "linux", + "mac", + "windows" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ClickToCallContextMenuForSelectedText" + ] + } + ] + }, + { + "platforms": [ + "chromeos" + ], + "experiments": [ + { + "name": "Enabled", + "enable_features": [ + "ClickToCallContextMenuForSelectedText", + "ClickToCallUI" + ] + } + ] + } + ], "ClipboardContentBehavior": [ { "platforms": [
diff --git a/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom b/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom index 09534aa..a5d5ad16 100644 --- a/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom +++ b/third_party/blink/public/mojom/dwrite_font_proxy/dwrite_font_proxy.mojom
@@ -20,6 +20,13 @@ uint8 font_stretch; }; +struct FallbackFamilyAndStyle { + string fallback_family_name; + uint16 weight; + uint8 width; + uint8 slant; +}; + struct MapCharactersResult { uint32 family_index; mojo_base.mojom.String16 family_name; @@ -120,8 +127,8 @@ // Use only on Windows 8.0 and earlier - otherwise better fallback API is // available through using a proxies IDWriteFontFallback. [Sync] - FallbackFamilyNameForCodepoint(string base_family_name, - string bcp47_language_tag, - uint32 codepoint) - => (string fallback_family_name); + FallbackFamilyAndStyleForCodepoint(string base_family_name, + string bcp47_language_tag, + uint32 codepoint) + => (FallbackFamilyAndStyle fallback_result); };
diff --git a/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc b/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc index 7ee67ac..8ee1889 100644 --- a/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc +++ b/third_party/blink/renderer/bindings/core/v8/world_safe_v8_reference.cc
@@ -41,8 +41,12 @@ if (!value->IsObject()) return; - ScriptState* script_state = - ScriptState::From(value.As<v8::Object>()->CreationContext()); + v8::Local<v8::Context> context = value.As<v8::Object>()->CreationContext(); + // Creation context is null if the value is a remote object. + if (context.IsEmpty()) + return; + + ScriptState* script_state = ScriptState::From(context); CHECK_EQ(&world, &script_state->World()); }
diff --git a/third_party/blink/renderer/bindings/modules/v8/generated.gni b/third_party/blink/renderer/bindings/modules/v8/generated.gni index f933cbd..b690f31 100644 --- a/third_party/blink/renderer/bindings/modules/v8/generated.gni +++ b/third_party/blink/renderer/bindings/modules/v8/generated.gni
@@ -42,14 +42,16 @@ "$bindings_modules_v8_output_dir/dom_exception_or_overconstrained_error.h", "$bindings_modules_v8_output_dir/double_or_constrain_double_range.cc", "$bindings_modules_v8_output_dir/double_or_constrain_double_range.h", + "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.cc", + "$bindings_modules_v8_output_dir/double_sequence_or_gpu_color_dict.h", "$bindings_modules_v8_output_dir/worklet_animation_effect_or_worklet_group_effect.cc", "$bindings_modules_v8_output_dir/worklet_animation_effect_or_worklet_group_effect.h", "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.cc", "$bindings_modules_v8_output_dir/float32_array_or_float64_array_or_dom_matrix.h", "$bindings_modules_v8_output_dir/gpu_out_of_memory_error_or_gpu_validation_error.cc", "$bindings_modules_v8_output_dir/gpu_out_of_memory_error_or_gpu_validation_error.h", - "$bindings_modules_v8_output_dir/gpu_load_op_or_gpu_color.cc", - "$bindings_modules_v8_output_dir/gpu_load_op_or_gpu_color.h", + "$bindings_modules_v8_output_dir/gpu_load_op_or_double_sequence_or_gpu_color_dict.cc", + "$bindings_modules_v8_output_dir/gpu_load_op_or_double_sequence_or_gpu_color_dict.h", "$bindings_modules_v8_output_dir/gpu_load_op_or_float.cc", "$bindings_modules_v8_output_dir/gpu_load_op_or_float.h", "$bindings_modules_v8_output_dir/gpu_load_op_or_unsigned_long.cc",
diff --git a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc index 5120207..fe93eac 100644 --- a/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc +++ b/third_party/blink/renderer/core/css/invalidation/pending_invalidations.cc
@@ -103,28 +103,32 @@ scheduling_parent.SetNeedsStyleInvalidation(); + ContainerNode* subtree_root = &scheduling_parent; + if (RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) { + subtree_root = DynamicTo<Element>(scheduling_parent); + if (!subtree_root) + subtree_root = &To<ShadowRoot>(scheduling_parent).host(); + } + for (auto& invalidation_set : invalidation_lists.siblings) { - if (invalidation_set->WholeSubtreeInvalid()) { - scheduling_parent.SetNeedsStyleRecalc( + DescendantInvalidationSet* descendants = + To<SiblingInvalidationSet>(*invalidation_set).SiblingDescendants(); + if (invalidation_set->WholeSubtreeInvalid() || + (descendants && descendants->WholeSubtreeInvalid())) { + subtree_root->SetNeedsStyleRecalc( kSubtreeStyleChange, StyleChangeReasonForTracing::Create( style_change_reason::kStyleInvalidator)); return; } - if (invalidation_set->InvalidatesSelf() && - !pending_invalidations.Descendants().Contains(invalidation_set)) - pending_invalidations.Descendants().push_back(invalidation_set); - if (DescendantInvalidationSet* descendants = - To<SiblingInvalidationSet>(*invalidation_set) - .SiblingDescendants()) { - if (descendants->WholeSubtreeInvalid()) { - scheduling_parent.SetNeedsStyleRecalc( - kSubtreeStyleChange, StyleChangeReasonForTracing::Create( - style_change_reason::kStyleInvalidator)); - return; - } - if (!pending_invalidations.Descendants().Contains(descendants)) - pending_invalidations.Descendants().push_back(descendants); + if (invalidation_set->InvalidatesSelf() && + !pending_invalidations.Descendants().Contains(invalidation_set)) { + pending_invalidations.Descendants().push_back(invalidation_set); + } + + if (descendants && + !pending_invalidations.Descendants().Contains(descendants)) { + pending_invalidations.Descendants().push_back(descendants); } } }
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc index 0a5cdb1f2..b8a58ca 100644 --- a/third_party/blink/renderer/core/dom/element.cc +++ b/third_party/blink/renderer/core/dom/element.cc
@@ -2926,7 +2926,12 @@ if (ShadowRoot* root = GetShadowRoot()) { if (child_change.TraverseChild(*root)) root->RecalcStyle(child_change); - RecalcDescendantStyles(StyleRecalcChange::kClearEnsured); + if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) + RecalcDescendantStyles(StyleRecalcChange::kClearEnsured); + } else if (auto* slot = ToHTMLSlotElementIfSupportsAssignmentOrNull(this)) { + slot->RecalcStyleForSlotChildren(child_change); + } else if (auto* insertion_point = DynamicTo<V0InsertionPoint>(this)) { + insertion_point->RecalcStyleForInsertionPointChildren(child_change); } else { RecalcDescendantStyles(child_change); }
diff --git a/third_party/blink/renderer/core/dom/node.cc b/third_party/blink/renderer/core/dom/node.cc index f98fa7c5..2d68f98d 100644 --- a/third_party/blink/renderer/core/dom/node.cc +++ b/third_party/blink/renderer/core/dom/node.cc
@@ -1308,7 +1308,9 @@ // RescheduleSiblingInvalidationsAsDescendants() for WholeSubtreeInvalid(). We // should instead mark the shadow host for subtree recalc when we traverse the // flat tree (and skip non-slotted host children). - DCHECK(IsElementNode() || IsTextNode() || IsShadowRoot()); + DCHECK(IsElementNode() || IsTextNode() || + (IsShadowRoot() && + !RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled())); if (!InActiveDocument()) return;
diff --git a/third_party/blink/renderer/core/dom/shadow_root.cc b/third_party/blink/renderer/core/dom/shadow_root.cc index 15cb42c..8c4234e 100644 --- a/third_party/blink/renderer/core/dom/shadow_root.cc +++ b/third_party/blink/renderer/core/dom/shadow_root.cc
@@ -141,6 +141,8 @@ void ShadowRoot::RecalcStyle(const StyleRecalcChange change) { // ShadowRoot doesn't support custom callbacks. DCHECK(!HasCustomStyleCallbacks()); + DCHECK(!NeedsStyleRecalc() || + !RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()); StyleRecalcChange child_change = change; if (GetStyleChangeType() == kSubtreeStyleChange)
diff --git a/third_party/blink/renderer/core/dom/v0_insertion_point.cc b/third_party/blink/renderer/core/dom/v0_insertion_point.cc index f0e3f99..f2694f2 100644 --- a/third_party/blink/renderer/core/dom/v0_insertion_point.cc +++ b/third_party/blink/renderer/core/dom/v0_insertion_point.cc
@@ -46,7 +46,8 @@ Document& document) : HTMLElement(tag_name, document, kCreateV0InsertionPoint), registered_with_shadow_root_(false) { - SetHasCustomStyleCallbacks(); + if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) + SetHasCustomStyleCallbacks(); } V0InsertionPoint::~V0InsertionPoint() = default; @@ -143,6 +144,7 @@ } void V0InsertionPoint::DidRecalcStyle(const StyleRecalcChange change) { + DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()); if (DistributedNodesAreFallback()) { // Fallback children have already been recalculated in // ContainerNode::RecalcDescendantStyles(). @@ -160,6 +162,23 @@ } } +void V0InsertionPoint::RecalcStyleForInsertionPointChildren( + const StyleRecalcChange change) { + if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) { + RecalcDescendantStyles(change); + return; + } + for (wtf_size_t i = 0; i < distributed_nodes_.size(); ++i) { + Node* node = distributed_nodes_.at(i); + if (!change.TraverseChild(*node)) + continue; + if (auto* this_element = DynamicTo<Element>(node)) + this_element->RecalcStyle(change); + else if (auto* text_node = DynamicTo<Text>(node)) + text_node->RecalcTextStyle(change); + } +} + bool V0InsertionPoint::CanBeActive() const { ShadowRoot* shadow_root = ContainingShadowRoot(); if (!shadow_root)
diff --git a/third_party/blink/renderer/core/dom/v0_insertion_point.h b/third_party/blink/renderer/core/dom/v0_insertion_point.h index 327aa38..a4883c2a 100644 --- a/third_party/blink/renderer/core/dom/v0_insertion_point.h +++ b/third_party/blink/renderer/core/dom/v0_insertion_point.h
@@ -81,6 +81,8 @@ return !HasDistribution() || DistributedNodeAt(0)->parentNode() == this; } + void RecalcStyleForInsertionPointChildren(const StyleRecalcChange); + void Trace(Visitor*) override; protected:
diff --git a/third_party/blink/renderer/core/html/html_slot_element.cc b/third_party/blink/renderer/core/html/html_slot_element.cc index a8d9f87..e302289 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.cc +++ b/third_party/blink/renderer/core/html/html_slot_element.cc
@@ -74,7 +74,8 @@ HTMLSlotElement::HTMLSlotElement(Document& document) : HTMLElement(kSlotTag, document) { UseCounter::Count(document, WebFeature::kHTMLSlotElement); - SetHasCustomStyleCallbacks(); + if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) + SetHasCustomStyleCallbacks(); } // static @@ -384,6 +385,7 @@ } void HTMLSlotElement::DidRecalcStyle(const StyleRecalcChange change) { + DCHECK(!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()); if (!change.RecalcChildren()) return; for (auto& node : assigned_nodes_) { @@ -396,6 +398,22 @@ } } +void HTMLSlotElement::RecalcStyleForSlotChildren( + const StyleRecalcChange change) { + if (!RuntimeEnabledFeatures::FlatTreeStyleRecalcEnabled()) { + RecalcDescendantStyles(change); + return; + } + for (auto& node : flat_tree_children_) { + if (!change.TraverseChild(*node)) + continue; + if (auto* element = DynamicTo<Element>(node.Get())) + element->RecalcStyle(change); + else if (auto* text_node = DynamicTo<Text>(node.Get())) + text_node->RecalcTextStyle(change); + } +} + void HTMLSlotElement::NotifySlottedNodesOfFlatTreeChangeByDynamicProgramming( const HeapVector<Member<Node>>& old_slotted, const HeapVector<Member<Node>>& new_slotted) {
diff --git a/third_party/blink/renderer/core/html/html_slot_element.h b/third_party/blink/renderer/core/html/html_slot_element.h index 89dc1d5..0b75211 100644 --- a/third_party/blink/renderer/core/html/html_slot_element.h +++ b/third_party/blink/renderer/core/html/html_slot_element.h
@@ -104,6 +104,8 @@ static AtomicString NormalizeSlotName(const AtomicString&); + void RecalcStyleForSlotChildren(const StyleRecalcChange); + // For User-Agent Shadow DOM static const AtomicString& UserAgentCustomAssignSlotName(); static const AtomicString& UserAgentDefaultSlotName();
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc index 4333b4d..32c9a40 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.cc
@@ -563,13 +563,13 @@ FindEarlyBreakpoint(child, &previous_inflow_position))) break; - bool abort; + NGLayoutResult::EStatus status; if (child.CreatesNewFormattingContext()) { - abort = !HandleNewFormattingContext(child, child_break_token, + status = HandleNewFormattingContext(child, child_break_token, &previous_inflow_position); previous_inline_break_token = nullptr; } else { - abort = !HandleInflow( + status = HandleInflow( child, child_break_token, &previous_inflow_position, inline_child_layout_context, &previous_inline_break_token); if (container_builder_.FoundColumnSpanner()) @@ -581,10 +581,9 @@ // container. DCHECK(!container_builder_.FoundColumnSpanner()); - if (abort) { - // We need to abort the layout, as our BFC block offset was resolved. - return container_builder_.Abort( - NGLayoutResult::kBfcBlockOffsetResolved); + if (status != NGLayoutResult::kSuccess) { + // We need to abort the layout. No fragment will be generated. + return container_builder_.Abort(status); } if (ConstraintSpace().HasBlockFragmentation()) { if (container_builder_.DidBreak() && @@ -801,9 +800,8 @@ if (!IsEarlyBreakpoint(*early_break_, container_builder_)) return false; - container_builder_.AddBreakBeforeChild(child, /* is_forced_break */ false); - previous_inflow_position->logical_block_offset = - FragmentainerSpaceAvailable(); + BreakBeforeChild(child, /* is_forced_break */ false, + previous_inflow_position); return true; } @@ -982,7 +980,7 @@ container_builder_.AddResult(*positioned_float.layout_result, logical_offset); } -bool NGBlockLayoutAlgorithm::HandleNewFormattingContext( +NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleNewFormattingContext( NGLayoutInputNode child, const NGBreakToken* child_break_token, NGPreviousInflowPosition* previous_inflow_position) { @@ -1074,7 +1072,7 @@ // If we need to abort here, it means that we had preceding unpositioned // floats. This is only expected if we're here for the first time. DCHECK(!bfc_offset_already_resolved); - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } // We reset the block offset here as it may have been affected by clearance. @@ -1133,7 +1131,7 @@ // incorrect estimate is with the child's margin adjoining. Any other // incorrect estimate will result in failed layout. DCHECK_EQ(old_offset, adjoining_bfc_offset_estimate); - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } } @@ -1160,9 +1158,10 @@ has_processed_first_child_ || child_margin_got_separated || child_bfc_offset.block_offset > child_bfc_offset_estimate || layout_result->IsPushedByFloats(); - if (BreakBeforeChild(child, *layout_result, previous_inflow_position, - logical_offset.block_offset, has_container_separation)) - return true; + if (BreakBeforeChildIfNeeded( + child, *layout_result, previous_inflow_position, + logical_offset.block_offset, has_container_separation)) + return NGLayoutResult::kSuccess; EBreakBetween break_after = JoinFragmentainerBreakValues( layout_result->FinalBreakAfter(), child.Style().BreakAfter()); container_builder_.SetPreviousBreakAfter(break_after); @@ -1170,7 +1169,7 @@ if (!PositionOrPropagateListMarker(*layout_result, &logical_offset, previous_inflow_position)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; container_builder_.AddResult(*layout_result, logical_offset); @@ -1186,7 +1185,7 @@ child_bfc_offset.block_offset, logical_offset, *layout_result, fragment, /* self_collapsing_child_had_clearance */ false); - return true; + return NGLayoutResult::kSuccess; } scoped_refptr<const NGLayoutResult> @@ -1342,7 +1341,7 @@ return nullptr; } -bool NGBlockLayoutAlgorithm::HandleInflow( +NGLayoutResult::EStatus NGBlockLayoutAlgorithm::HandleInflow( NGLayoutInputNode child, const NGBreakToken* child_break_token, NGPreviousInflowPosition* previous_inflow_position, @@ -1361,9 +1360,9 @@ *previous_inline_break_token = TryReuseFragmentsFromCache( *child_inline_node, previous_inflow_position, &aborted); if (*previous_inline_break_token) - return true; + return NGLayoutResult::kSuccess; if (aborted) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } bool is_non_empty_inline = @@ -1385,7 +1384,7 @@ // keep in sync. if (has_clearance_past_adjoining_floats || is_non_empty_inline) { if (!ResolveBfcBlockOffset(previous_inflow_position)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; // If we had clearance past any adjoining floats, we already know where the // child is going to be (the child's margins won't have any effect). @@ -1418,7 +1417,7 @@ previous_inline_break_token); } -bool NGBlockLayoutAlgorithm::FinishInflow( +NGLayoutResult::EStatus NGBlockLayoutAlgorithm::FinishInflow( NGLayoutInputNode child, const NGBreakToken* child_break_token, const NGConstraintSpace& child_space, @@ -1472,7 +1471,7 @@ if (!ResolveBfcBlockOffset(previous_inflow_position, bfc_block_offset, /* forced_bfc_block_offset */ base::nullopt)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } // We have special behaviour for a self-collapsing child which gets pushed @@ -1505,7 +1504,7 @@ // is therefore resolvable, and if it hasn't already been resolved, we'll // do it now to separate the child's collapsed margin from this container. if (!ResolveBfcBlockOffset(previous_inflow_position)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } else if (layout_result->SubtreeModifiedMarginStrut()) { // The child doesn't have clearance, and modified its incoming // margin-strut. Propagate this information up to our parent if needed. @@ -1540,7 +1539,7 @@ // resolved. if (!ResolveBfcBlockOffset(previous_inflow_position, *child_bfc_block_offset)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; } // We need to re-layout a self-collapsing child if it was affected by @@ -1648,9 +1647,10 @@ bool has_container_separation = has_processed_first_child_ || (layout_result->IsPushedByFloats() && !container_builder_.IsPushedByFloats()); - if (BreakBeforeChild(child, *layout_result, previous_inflow_position, - logical_offset.block_offset, has_container_separation)) - return true; + if (BreakBeforeChildIfNeeded( + child, *layout_result, previous_inflow_position, + logical_offset.block_offset, has_container_separation)) + return NGLayoutResult::kSuccess; EBreakBetween break_after = JoinFragmentainerBreakValues( layout_result->FinalBreakAfter(), child.Style().BreakAfter()); container_builder_.SetPreviousBreakAfter(break_after); @@ -1658,7 +1658,7 @@ if (!PositionOrPropagateListMarker(*layout_result, &logical_offset, previous_inflow_position)) - return false; + return NGLayoutResult::kBfcBlockOffsetResolved; container_builder_.AddResult(*layout_result, logical_offset); @@ -1702,7 +1702,7 @@ } } - return true; + return NGLayoutResult::kSuccess; } NGInflowChildData NGBlockLayoutAlgorithm::ComputeChildData( @@ -1937,15 +1937,6 @@ } bool NGBlockLayoutAlgorithm::FinalizeForFragmentation() { - if (first_overflowing_line_ && !fit_all_lines_) { - // A line box overflowed the fragmentainer, but we continued layout anyway, - // in order to determine where to break in order to honor the widows - // request. We never got around to actually breaking, before we ran out of - // lines. So do it now. - intrinsic_block_size_ = FragmentainerSpaceAvailable(); - container_builder_.SetDidBreak(); - } - LayoutUnit consumed_block_size = BreakToken() ? BreakToken()->ConsumedBlockSize() : LayoutUnit(); LayoutUnit block_size = @@ -2002,36 +1993,84 @@ return true; } -bool NGBlockLayoutAlgorithm::BreakBeforeChild( +bool NGBlockLayoutAlgorithm::BreakBeforeChildIfNeeded( NGLayoutInputNode child, const NGLayoutResult& layout_result, NGPreviousInflowPosition* previous_inflow_position, LayoutUnit block_offset, bool has_container_separation) { DCHECK(ConstraintSpace().HasBlockFragmentation()); - BreakType break_type = BreakTypeBeforeChild( - child, layout_result, block_offset, has_container_separation); - if (break_type == NoBreak) + + // If the BFC offset is unknown, there's nowhere to break, since there's no + // non-empty child content yet (as that would have resolved the BFC offset). + if (!container_builder_.BfcBlockOffset()) return false; - LayoutUnit space_available = FragmentainerSpaceAvailable(); - LayoutUnit space_shortage; - if (layout_result.MinimalSpaceShortage() == LayoutUnit::Max()) { - // Calculate space shortage: Figure out how much more space would have been - // sufficient to make the child fit right here in the current fragment. - NGFragment fragment(ConstraintSpace().GetWritingMode(), - layout_result.PhysicalFragment()); - LayoutUnit space_left = space_available - block_offset; - space_shortage = fragment.BlockSize() - space_left; - } else { - // However, if space shortage was reported inside the child, use that. If we - // broke inside the child, we didn't complete layout, so calculating space - // shortage for the child as a whole would be impossible and pointless. - space_shortage = layout_result.MinimalSpaceShortage(); + if (has_container_separation) { + EBreakBetween break_between = + CalculateBreakBetweenValue(child, layout_result, container_builder_); + if (IsForcedBreakValue(ConstraintSpace(), break_between)) { + BreakBeforeChild(child, layout_result, block_offset, + /* is_forced_break */ true, previous_inflow_position); + return true; + } } + const auto& physical_fragment = layout_result.PhysicalFragment(); + if (const NGBlockBreakToken* child_token = + DynamicTo<NGBlockBreakToken>(physical_fragment.BreakToken())) { + // The block child broke inside. We now need to decide whether to keep that + // break, or if it would be better to break before it. + if ((!child_token->HasLastResortBreak() && + !IsAvoidBreakValue(ConstraintSpace(), child.Style().BreakInside())) || + layout_result.HasForcedBreak()) { + // The break inside is perfect. Keep it. + return false; + } + if (!has_container_separation) { + // The break inside wasn't perfect, but breaking before wouldn't be any + // better, since we're at the start of the container, with no valid class + // C break point [1]. Keep the break inside, since that gives more content + // progression, but mark the break as undesirable. We might find something + // better further up the tree. + // + // [1] https://www.w3.org/TR/css-break-3/#possible-breaks + container_builder_.SetHasLastResortBreak(); + return false; + } + } else { + LayoutUnit space_left = FragmentainerSpaceAvailable() - block_offset; + bool want_break; + if (child.IsInline()) { + // If the line doesn't fit, we need a break. + NGFragment fragment(ConstraintSpace().GetWritingMode(), + physical_fragment); + want_break = fragment.BlockSize() > space_left; + } else { + // If the block-offset is past the fragmentainer boundary (or exactly at + // the boundary), no part of the fragment is going to fit in the current + // fragmentainer. Fragments may be pushed past the fragmentainer boundary + // by margins. + want_break = space_left <= LayoutUnit(); + } + if (want_break) { + // If we haven't used any space at all in the fragmentainer yet, though, + // we cannot break even if we really want to, or there'd be no progress. + // We'd end up creating an infinite number of fragmentainers without + // putting any content into them. + if (space_left >= ConstraintSpace().FragmentainerBlockSize()) + want_break = false; + } + + if (!want_break) + return false; + } + + // Figure out where to insert a soft break. It will either be before this + // child, or before an earlier sibling, if there's a more appealing breakpoint + // there. + if (child.IsInline()) { - DCHECK_EQ(break_type, SoftBreak); if (!first_overflowing_line_) { // We're at the first overflowing line. This is the space shortage that // we are going to report. We do this in spite of not yet knowing @@ -2042,7 +2081,7 @@ // require an additional piece of machinery. This case should be rare // enough (to worry about performance), so let's focus on code // simplicity instead. - container_builder_.PropagateSpaceShortage(space_shortage); + PropagateSpaceShortage(layout_result, block_offset); } // Attempt to honor orphans and widows requests. if (int line_count = container_builder_.LineCount()) { @@ -2067,9 +2106,6 @@ // but mark it as undesirable. container_builder_.SetHasLastResortBreak(); } - // We're already failing with orphans, so don't even try to deal with - // widows. - fit_all_lines_ = true; } else { // There are enough lines before the break. Try to make sure that // there'll be enough lines after the break as well. Attempt to honor @@ -2085,14 +2121,13 @@ // current fragment (that we have already laid out) may have to be // saved for the next fragment. return false; - } else { - // We have determined that there are plenty of lines for the next - // fragment, so we can just break exactly where we ran out of space, - // rather than pushing some of the line boxes over to the next - // fragment. - fit_all_lines_ = true; } + + // We have determined that there are plenty of lines for the next + // fragment, so we can just break exactly where we ran out of space, + // rather than pushing some of the line boxes over to the next fragment. } + fit_all_lines_ = true; } } @@ -2105,104 +2140,73 @@ container_builder_.SetHasLastResortBreak(); } - // The remaining part of the fragmentainer (the unusable space for child - // content, due to the break) should still be occupied by this container. - // TODO(mstensho): Figure out if we really need to <0 here. It doesn't seem - // right to have negative available space. - previous_inflow_position->logical_block_offset = - space_available.ClampNegativeToZero(); - // Drop the fragment on the floor and retry at the start of the next - // fragmentainer. - container_builder_.AddBreakBeforeChild(child, break_type == ForcedBreak); - if (break_type == ForcedBreak) { - container_builder_.SetHasForcedBreak(); - } else { - // Report space shortage, unless we're at a line box (in that case we've - // already dealt with it further up). - if (!child.IsInline()) { - // TODO(mstensho): Turn this into a DCHECK, when the engine is ready for - // it. Space shortage should really be positive here, or we might - // ultimately fail to stretch the columns (column balancing). - if (space_shortage > LayoutUnit()) - container_builder_.PropagateSpaceShortage(space_shortage); - } - } + // Break before the child. Note that there may be a better break further up + // with higher appeal (but it's too early to tell), in which case this + // breakpoint will be replaced. + BreakBeforeChild(child, layout_result, block_offset, + /* is_forced_break */ false, previous_inflow_position); return true; } -NGBlockLayoutAlgorithm::BreakType NGBlockLayoutAlgorithm::BreakTypeBeforeChild( +void NGBlockLayoutAlgorithm::BreakBeforeChild( NGLayoutInputNode child, const NGLayoutResult& layout_result, LayoutUnit block_offset, - bool has_container_separation) const { - if (!container_builder_.BfcBlockOffset().has_value()) - return NoBreak; - - const NGPhysicalContainerFragment& physical_fragment = - layout_result.PhysicalFragment(); - - // If we haven't used any space at all in the fragmentainer yet, we cannot - // break, or there'd be no progress. We'd end up creating an infinite number - // of fragmentainers without putting any content into them. - auto space_left = FragmentainerSpaceAvailable() - block_offset; - if (space_left >= ConstraintSpace().FragmentainerBlockSize()) - return NoBreak; - - if (child.IsInline()) { - NGFragment fragment(ConstraintSpace().GetWritingMode(), physical_fragment); - return fragment.BlockSize() > space_left ? SoftBreak : NoBreak; - } - - EBreakBetween break_before = JoinFragmentainerBreakValues( - child.Style().BreakBefore(), layout_result.InitialBreakBefore()); - EBreakBetween break_between = - container_builder_.JoinedBreakBetweenValue(break_before); - if (IsForcedBreakValue(ConstraintSpace(), break_between)) { - // There should be a forced break before this child, and if we're at a valid - // breakpoint (class A or C), just go ahead and break. If we're not at a - // valid breakpoint, the forced break will be propagated upwards until we - // find a valid breakpoint. - if (has_container_separation) - return ForcedBreak; - } - - // If the block offset is past the fragmentainer boundary (or exactly at the - // boundary), no part of the fragment is going to fit in the current - // fragmentainer. Fragments may be pushed past the fragmentainer boundary by - // margins. - if (space_left <= LayoutUnit()) - return SoftBreak; - - const NGBreakToken* token = physical_fragment.BreakToken(); - if (!token || token->IsFinished()) - return NoBreak; - auto* block_break_token = DynamicTo<NGBlockBreakToken>(token); - if (block_break_token && block_break_token->HasLastResortBreak()) { - // We've already found a place to break inside the child, but it wasn't an - // optimal one, because it would violate some rules for breaking. Consider - // breaking before this child instead, but only do so if it's at a valid - // break point. It's a valid break point if we're between siblings, or if - // it's a first child at a class C break point [1] (if it got pushed down by - // floats). The break we've already found has been marked as a last-resort - // break, but moving that last-resort break to an earlier (but equally bad) - // last-resort break would just waste fragmentainer space and slow down - // content progression. - // - // [1] https://www.w3.org/TR/css-break-3/#possible-breaks - if (has_container_separation) { - // This is a valid break point, and we can resolve the last-resort - // situation. - return SoftBreak; - } - } - if (!IsAvoidBreakValue(ConstraintSpace(), child.Style().BreakInside())) - return NoBreak; - - // The child broke, and we're not at the start of a fragmentainer, and we're - // supposed to avoid breaking inside the child. + bool is_forced_break, + NGPreviousInflowPosition* previous_inflow_position) { +#if DCHECK_IS_ON() + // In order to successfully break before a node, this has to be its first + // fragment. + const auto& physical_fragment = layout_result.PhysicalFragment(); DCHECK(!physical_fragment.IsBox() || To<NGPhysicalBoxFragment>(physical_fragment).IsFirstForNode()); - return SoftBreak; +#endif + + // Report space shortage. Note that we're not doing this for line boxes here + // (only blocks), because line boxes need handle it in their own way (due to + // how we implement widows). + if (child.IsBlock()) + PropagateSpaceShortage(layout_result, block_offset); + + BreakBeforeChild(child, is_forced_break, previous_inflow_position); +} + +void NGBlockLayoutAlgorithm::BreakBeforeChild( + NGLayoutInputNode child, + bool is_forced_break, + NGPreviousInflowPosition* previous_inflow_position) { + // The remaining part of the fragmentainer (the unusable space for child + // content, due to the break) should still be occupied by this container. + previous_inflow_position->logical_block_offset = + FragmentainerSpaceAvailable(); + // This will drop the fragment (if any) on the floor and retry at the start of + // the next fragmentainer. + container_builder_.AddBreakBeforeChild(child, is_forced_break); +} + +void NGBlockLayoutAlgorithm::PropagateSpaceShortage( + const NGLayoutResult& layout_result, + LayoutUnit block_offset) { + LayoutUnit space_shortage; + if (layout_result.MinimalSpaceShortage() == LayoutUnit::Max()) { + // Calculate space shortage: Figure out how much more space would have been + // sufficient to make the child fit right here in the current fragment. + NGFragment fragment(ConstraintSpace().GetWritingMode(), + layout_result.PhysicalFragment()); + LayoutUnit space_left = FragmentainerSpaceAvailable() - block_offset; + space_shortage = fragment.BlockSize() - space_left; + } else { + // However, if space shortage was reported inside the child, use that. If we + // broke inside the child, we didn't complete layout, so calculating space + // shortage for the child as a whole would be impossible and pointless. + space_shortage = layout_result.MinimalSpaceShortage(); + } + + // TODO(mstensho): Turn this into a DCHECK, when the engine is ready for + // it. Space shortage should really be positive here, or we might ultimately + // fail to stretch the columns (column balancing). + if (space_shortage > LayoutUnit()) + container_builder_.PropagateSpaceShortage(space_shortage); } NGBoxStrut NGBlockLayoutAlgorithm::CalculateMargins(
diff --git a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h index e6893cdd..9ce4675 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h +++ b/third_party/blink/renderer/core/layout/ng/ng_block_layout_algorithm.h
@@ -15,6 +15,7 @@ #include "third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h" #include "third_party/blink/renderer/core/layout/ng/ng_floats_utils.h" #include "third_party/blink/renderer/core/layout/ng/ng_layout_algorithm.h" +#include "third_party/blink/renderer/core/layout/ng/ng_layout_result.h" #include "third_party/blink/renderer/core/layout/ng/ng_unpositioned_float.h" namespace blink { @@ -22,7 +23,6 @@ class NGConstraintSpace; class NGEarlyBreak; class NGFragment; -class NGLayoutResult; class NGPhysicalLineBoxFragment; // This struct is used for communicating to a child the position of the previous @@ -179,9 +179,10 @@ // // Returns false if we need to abort layout, because a previously unknown BFC // block offset has now been resolved. - bool HandleNewFormattingContext(NGLayoutInputNode child, - const NGBreakToken* child_break_token, - NGPreviousInflowPosition*); + NGLayoutResult::EStatus HandleNewFormattingContext( + NGLayoutInputNode child, + const NGBreakToken* child_break_token, + NGPreviousInflowPosition*); // Performs the actual layout of a new formatting context. This may be called // multiple times from HandleNewFormattingContext. @@ -196,14 +197,14 @@ // Handle an in-flow child. // Returns false if we need to abort layout, because a previously unknown BFC // block offset has now been resolved. (Same as HandleNewFormattingContext). - bool HandleInflow( + NGLayoutResult::EStatus HandleInflow( NGLayoutInputNode child, const NGBreakToken* child_break_token, NGPreviousInflowPosition*, NGInlineChildLayoutContext*, scoped_refptr<const NGInlineBreakToken>* previous_inline_break_token); - bool FinishInflow( + NGLayoutResult::EStatus FinishInflow( NGLayoutInputNode child, const NGBreakToken* child_break_token, const NGConstraintSpace&, @@ -224,6 +225,14 @@ // whether fits within the fragmentainer or not. bool IsFragmentainerOutOfSpace(LayoutUnit block_offset) const; + // Final adjustments before fragment creation. We need to prevent the fragment + // from crossing fragmentainer boundaries, and rather create a break token if + // we're out of space. As part of finalizing we may also discover that we need + // to abort layout, because we've run out of space at a less-than-ideal + // location. In this case, false will be returned. Otherwise, true will be + // returned. + bool FinalizeForFragmentation(); + // Insert a fragmentainer break before the child if necessary. // Update previous in-flow position and return true if a break was inserted. // Otherwise return false. @@ -237,28 +246,24 @@ // block-start content edge of the container and the block-start margin edge // of the first in-flow child. This can happen when in-flow content is pushed // down by floats. https://www.w3.org/TR/css-break-3/#possible-breaks - bool BreakBeforeChild(NGLayoutInputNode child, + bool BreakBeforeChildIfNeeded(NGLayoutInputNode child, + const NGLayoutResult&, + NGPreviousInflowPosition*, + LayoutUnit block_offset, + bool has_container_separation); + + // Insert either a soft or forced break before the child. + void BreakBeforeChild(NGLayoutInputNode child, const NGLayoutResult&, - NGPreviousInflowPosition*, LayoutUnit block_offset, - bool has_container_separation); + bool is_forced_break, + NGPreviousInflowPosition*); + void BreakBeforeChild(NGLayoutInputNode child, + bool is_forced_break, + NGPreviousInflowPosition*); - enum BreakType { NoBreak, SoftBreak, ForcedBreak }; - - // Given a child fragment and the corresponding node's style, determine the - // type of break we should insert in front of it, if any. - BreakType BreakTypeBeforeChild(NGLayoutInputNode child, - const NGLayoutResult&, - LayoutUnit block_offset, - bool has_container_separation) const; - - // Final adjustments before fragment creation. We need to prevent the fragment - // from crossing fragmentainer boundaries, and rather create a break token if - // we're out of space. As part of finalizing we may also discover that we need - // to abort layout, because we've run out of space at a less-than-ideal - // location. In this case, false will be returned. Otherwise, true will be - // returned. - bool FinalizeForFragmentation(); + // Propagate the minimal space shortage from a child. + void PropagateSpaceShortage(const NGLayoutResult&, LayoutUnit block_offset); void PropagateBaselinesFromChildren(); bool AddBaseline(const NGBaselineRequest&,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc index 2771884..2fe5759 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.cc
@@ -81,6 +81,9 @@ void NGBoxFragmentBuilder::AddBreakBeforeChild(NGLayoutInputNode child, bool is_forced_break) { + if (is_forced_break) + SetHasForcedBreak(); + DCHECK(has_block_fragmentation_); SetDidBreak(); if (auto* child_inline_node = DynamicTo<NGInlineNode>(child)) { @@ -210,7 +213,7 @@ } scoped_refptr<const NGLayoutResult> NGBoxFragmentBuilder::Abort( - NGLayoutResult::NGLayoutResultStatus status) { + NGLayoutResult::EStatus status) { return base::AdoptRef(new NGLayoutResult(status, this)); }
diff --git a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h index ca29d37..0d6e4b6 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h +++ b/third_party/blink/renderer/core/layout/ng/ng_box_fragment_builder.h
@@ -117,11 +117,6 @@ // This will result in a fragment which has an unfinished break token. void SetDidBreak() { did_break_ = true; } - void SetHasForcedBreak() { - has_forced_break_ = true; - minimal_space_shortage_ = LayoutUnit(); - } - // Report space shortage, i.e. how much more space would have been sufficient // to prevent some piece of content from breaking. This information may be // used by the column balancer to stretch columns. @@ -186,8 +181,7 @@ return ToBoxFragment(ToLineWritingMode(GetWritingMode())); } - scoped_refptr<const NGLayoutResult> Abort( - NGLayoutResult::NGLayoutResultStatus); + scoped_refptr<const NGLayoutResult> Abort(NGLayoutResult::EStatus); NGPhysicalFragment::NGBoxType BoxType() const; void SetBoxType(NGPhysicalFragment::NGBoxType box_type) { @@ -252,6 +246,11 @@ // Update whether we have fragmented in this flow. void PropagateBreak(const NGLayoutResult&); + void SetHasForcedBreak() { + has_forced_break_ = true; + minimal_space_shortage_ = LayoutUnit(); + } + scoped_refptr<const NGLayoutResult> ToBoxFragment(WritingMode); const NGFragmentGeometry* initial_fragment_geometry_ = nullptr;
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc index 4fd21fd7..6ce52ce 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.cc
@@ -90,6 +90,16 @@ return false; } +EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child, + const NGLayoutResult& layout_result, + const NGBoxFragmentBuilder& builder) { + if (child.IsInline()) + return EBreakBetween::kAuto; + EBreakBetween break_before = JoinFragmentainerBreakValues( + child.Style().BreakBefore(), layout_result.InitialBreakBefore()); + return builder.JoinedBreakBetweenValue(break_before); +} + void SetupFragmentation(const NGConstraintSpace& parent_space, LayoutUnit new_bfc_block_offset, NGConstraintSpaceBuilder* builder,
diff --git a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h index 432ed5f..9a7b815 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h +++ b/third_party/blink/renderer/core/layout/ng/ng_fragmentation_utils.h
@@ -13,7 +13,9 @@ namespace blink { +class NGBoxFragmentBuilder; class NGConstraintSpace; +class NGLayoutResult; // Join two adjacent break values specified on break-before and/or break- // after. avoid* values win over auto values, and forced break values win over @@ -41,6 +43,13 @@ return token && !token->IsBreakBefore(); } +// Calculate the final "break-between" value at a class A or C breakpoint. This +// is the combination of all break-before and break-after values that met at the +// breakpoint. +EBreakBetween CalculateBreakBetweenValue(NGLayoutInputNode child, + const NGLayoutResult&, + const NGBoxFragmentBuilder&); + // Set up a child's constraint space builder for block fragmentation. The child // participates in the same fragmentation context as parent_space. If the child // establishes a new formatting context, new_bfc_block_offset must be set to the
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc index d991ccd..24515a2 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result.cc
@@ -67,8 +67,7 @@ builder, /* cache_space */ false) {} -NGLayoutResult::NGLayoutResult(NGLayoutResultStatus status, - NGBoxFragmentBuilder* builder) +NGLayoutResult::NGLayoutResult(EStatus status, NGBoxFragmentBuilder* builder) : NGLayoutResult(/* physical_fragment */ nullptr, builder, /* cache_space */ false) {
diff --git a/third_party/blink/renderer/core/layout/ng/ng_layout_result.h b/third_party/blink/renderer/core/layout/ng/ng_layout_result.h index f30903d..015cbe7 100644 --- a/third_party/blink/renderer/core/layout/ng/ng_layout_result.h +++ b/third_party/blink/renderer/core/layout/ng/ng_layout_result.h
@@ -36,7 +36,7 @@ // NGFragment et al. class CORE_EXPORT NGLayoutResult : public RefCounted<NGLayoutResult> { public: - enum NGLayoutResultStatus { + enum EStatus { kSuccess = 0, kBfcBlockOffsetResolved = 1, kNeedsEarlierBreak = 2, @@ -57,7 +57,7 @@ const NGPhysicalContainerFragment& PhysicalFragment() const { DCHECK(physical_fragment_); - DCHECK_EQ(NGLayoutResultStatus::kSuccess, Status()); + DCHECK_EQ(kSuccess, Status()); return *physical_fragment_; } @@ -92,9 +92,7 @@ return space_.ExclusionSpace(); } - NGLayoutResultStatus Status() const { - return static_cast<NGLayoutResultStatus>(bitfields_.status); - } + EStatus Status() const { return static_cast<EStatus>(bitfields_.status); } LayoutUnit BfcLineOffset() const { if (HasRareData()) @@ -263,7 +261,7 @@ scoped_refptr<const NGPhysicalContainerFragment> physical_fragment, NGLineBoxFragmentBuilder*); // This constructor is for a non-success status. - NGLayoutResult(NGLayoutResultStatus, NGBoxFragmentBuilder*); + NGLayoutResult(EStatus, NGBoxFragmentBuilder*); // We don't need the copy constructor, move constructor, copy // assigmnment-operator, or move assignment-operator today. @@ -371,7 +369,7 @@ unsigned initial_break_before : 4; // EBreakBetween unsigned final_break_after : 4; // EBreakBetween - unsigned status : 2; // NGLayoutResultStatus + unsigned status : 2; // EStatus }; // The constraint space which generated this layout result, may not be valid
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc index eb6a136..9f2a98a 100644 --- a/third_party/blink/renderer/core/loader/document_loader.cc +++ b/third_party/blink/renderer/core/loader/document_loader.cc
@@ -738,7 +738,14 @@ void DocumentLoader::HandleRedirect(const KURL& current_request_url) { // Browser process should have already checked that redirecting url is // allowed to display content from the target origin. - CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_)); + // When the referrer page is in an unsigned bundled exchanges file in local + // (eg: file:///tmp/a.wbn), Chrome internally redirects the navigation to the + // page (eg: https://example.com/page.html) inside the bundled exchanges file + // to the file's URL (file:///tmp/a.wbn?https://example.com/page.html). In + // this case, CanDisplay() returns false, and + // base_url_override_for_bundled_exchanges must not be null. + CHECK(SecurityOrigin::Create(current_request_url)->CanDisplay(url_) || + !params_->base_url_override_for_bundled_exchanges.IsNull()); DCHECK(!GetTiming().FetchStart().is_null()); redirect_chain_.push_back(url_);
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc index 3b3d0d62..a40dae4 100644 --- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc +++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.cc
@@ -27,6 +27,7 @@ #include <algorithm> +#include "base/auto_reset.h" #include "third_party/blink/public/platform/task_type.h" #include "third_party/blink/renderer/bindings/core/v8/script_event_listener.h" #include "third_party/blink/renderer/core/dom/document.h" @@ -198,8 +199,8 @@ cached_repeat_count_(SMILRepeatCount::Invalid()), cached_min_(kInvalidCachedTime), cached_max_(kInvalidCachedTime), - interval_has_changed_(false) { -} + interval_has_changed_(false), + is_notifying_dependents_(false) {} SVGSMILElement::~SVGSMILElement() = default; @@ -1136,23 +1137,14 @@ } void SVGSMILElement::NotifyDependents(const NotifyDependentsInfo& info) { - // |loopBreaker| is used to avoid infinite recursions which may be caused by: - // |notifyDependentsIntervalChanged| -> |createInstanceTimesFromSyncBase| -> - // |add{Begin,End}Time| -> |{begin,end}TimeChanged| -> - // |notifyDependentsIntervalChanged| - // - // As the set here records SVGSMILElements on the stack, it is acceptable to - // use a HashSet of untraced heap references -- any conservative GC which - // strikes before unwinding will find these elements on the stack. - DEFINE_STATIC_LOCAL(HashSet<UntracedMember<SVGSMILElement>>, loop_breaker, - ()); - if (!loop_breaker.insert(this).is_new_entry) + // Avoid infinite recursion which may be caused by: + // |NotifyDependents| -> |CreateInstanceTimesFromSyncBase| -> + // |AddInstanceTime| -> |InstanceListChanged| -> |NotifyDependents| + if (is_notifying_dependents_) return; - + base::AutoReset<bool> reentrancy_guard(&is_notifying_dependents_, true); for (SVGSMILElement* element : sync_base_dependents_) element->CreateInstanceTimesFromSyncBase(this, info); - - loop_breaker.erase(this); } void SVGSMILElement::CreateInstanceTimesFromSyncBase(
diff --git a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h index 8020ba62..53eae370 100644 --- a/third_party/blink/renderer/core/svg/animation/svg_smil_element.h +++ b/third_party/blink/renderer/core/svg/animation/svg_smil_element.h
@@ -118,16 +118,6 @@ // animations are rendered useless. virtual bool OverwritesUnderlyingAnimationValue() const = 0; - bool AnimatedTypeIsLocked() const { return animated_property_locked_; } - void LockAnimatedType() { - DCHECK(!animated_property_locked_); - animated_property_locked_ = true; - } - void UnlockAnimatedType() { - DCHECK(animated_property_locked_); - animated_property_locked_ = false; - } - void ScheduleEvent(const AtomicString& event_type); void ScheduleRepeatEvents(); void DispatchPendingEvent(const AtomicString& event_type); @@ -287,8 +277,8 @@ mutable SMILTime cached_min_; mutable SMILTime cached_max_; - bool animated_property_locked_; bool interval_has_changed_; + bool is_notifying_dependents_; friend class ConditionEventListener; };
diff --git a/third_party/blink/renderer/core/svg/svg_animate_element.cc b/third_party/blink/renderer/core/svg/svg_animate_element.cc index c4c8633..954a9349 100644 --- a/third_party/blink/renderer/core/svg/svg_animate_element.cc +++ b/third_party/blink/renderer/core/svg/svg_animate_element.cc
@@ -443,12 +443,6 @@ if (!animated_value_) return; - // The animated property lock is held for the "result animation" (see - // SMILTimeContainer::updateAnimations()) while we're processing an animation - // group. We will very likely crash later if we clear the animated type while - // the lock is held. See crbug.com/581546. - DCHECK(!AnimatedTypeIsLocked()); - SVGElement* target_element = targetElement(); if (!target_element) { animated_value_.Clear();
diff --git a/third_party/blink/renderer/devtools/BUILD.gn b/third_party/blink/renderer/devtools/BUILD.gn index 22aa080..62ce7cf 100644 --- a/third_party/blink/renderer/devtools/BUILD.gn +++ b/third_party/blink/renderer/devtools/BUILD.gn
@@ -329,12 +329,7 @@ "front_end/help/releaseNote.css", "front_end/help/ReleaseNoteText.js", "front_end/help/ReleaseNoteView.js", - "front_end/host/InspectorFrontendHost.js", - "front_end/host/InspectorFrontendHostAPI.js", "front_end/host/module.json", - "front_end/host/Platform.js", - "front_end/host/ResourceLoader.js", - "front_end/host/UserMetrics.js", "front_end/inline_editor/bezierEditor.css", "front_end/inline_editor/BezierEditor.js", "front_end/inline_editor/bezierSwatch.css", @@ -953,6 +948,12 @@ all_devtools_files += lighthouse_locale_files all_devtools_modules = [ + "front_end/host/host.js", + "front_end/host/UserMetrics.js", + "front_end/host/ResourceLoader.js", + "front_end/host/Platform.js", + "front_end/host/InspectorFrontendHost.js", + "front_end/host/InspectorFrontendHostAPI.js", "front_end/root.js", "front_end/Runtime.js", "front_end/ui/ARIAUtils.js", @@ -1177,6 +1178,12 @@ ] copied_devtools_modules = [ + "$resources_out_dir/host/host.js", + "$resources_out_dir/host/UserMetrics.js", + "$resources_out_dir/host/ResourceLoader.js", + "$resources_out_dir/host/Platform.js", + "$resources_out_dir/host/InspectorFrontendHost.js", + "$resources_out_dir/host/InspectorFrontendHostAPI.js", "$resources_out_dir/root.js", "$resources_out_dir/Runtime.js", "$resources_out_dir/ui/ARIAUtils.js",
diff --git a/third_party/blink/renderer/devtools/front_end/Tests.js b/third_party/blink/renderer/devtools/front_end/Tests.js index 8704a71..1b3f736 100644 --- a/third_party/blink/renderer/devtools/front_end/Tests.js +++ b/third_party/blink/renderer/devtools/front_end/Tests.js
@@ -749,9 +749,9 @@ this.assertEquals(119, event.data.keyCode); this.assertEquals(0, event.data.modifiers); this.assertEquals('', event.data.code); - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyUp, this); SDK.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent( {type: 'keyUp', key: 'F8', code: 'F8', windowsVirtualKeyCode: 119, nativeVirtualKeyCode: 119}); @@ -765,7 +765,7 @@ this.releaseControl(); } this.takeControl(); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, onKeyEventUnhandledKeyDown, this); SDK.targetManager.mainTarget().inputAgent().invoke_dispatchKeyEvent( {type: 'rawKeyDown', key: 'F8', windowsVirtualKeyCode: 119, nativeVirtualKeyCode: 119}); @@ -780,7 +780,7 @@ // Check that showing the certificate viewer does not crash, crbug.com/954874 TestSuite.prototype.testShowCertificate = function() { - InspectorFrontendHost.showCertificateViewer([ + Host.InspectorFrontendHost.showCertificateViewer([ 'MIIFIDCCBAigAwIBAgIQE0TsEu6R8FUHQv+9fE7j8TANBgkqhkiG9w0BAQsF' + 'ADBUMQswCQYDVQQGEwJVUzEeMBwGA1UEChMVR29vZ2xlIFRydXN0IFNlcnZp' + 'Y2VzMSUwIwYDVQQDExxHb29nbGUgSW50ZXJuZXQgQXV0aG9yaXR5IEczMB4X' + @@ -1034,7 +1034,7 @@ function reset() { Root.Runtime.experiments.clearForTest(); - InspectorFrontendHost.getPreferences(gotPreferences); + Host.InspectorFrontendHost.getPreferences(gotPreferences); } function gotPreferences(prefs) {
diff --git a/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js b/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js index 949e485..b450cdf9 100644 --- a/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js +++ b/third_party/blink/renderer/devtools/front_end/bindings_test_runner/IsolatedFilesystemTestRunner.js
@@ -7,7 +7,7 @@ * @suppress {accessControls} */ -InspectorFrontendHost.isolatedFileSystem = function(name) { +Host.InspectorFrontendHost.isolatedFileSystem = function(name) { return BindingsTestRunner.TestFileSystem._instances[name]; }; @@ -43,7 +43,7 @@ const fileSystemPath = this.fileSystemPath; BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath] = this; - InspectorFrontendHost.events.dispatchEventToListeners( + Host.InspectorFrontendHost.events.dispatchEventToListeners( Host.InspectorFrontendHostAPI.Events.FileSystemAdded, {fileSystem: {fileSystemPath: this.fileSystemPath, fileSystemName: this.fileSystemPath, type}}); @@ -65,7 +65,7 @@ reportRemoved: function() { delete BindingsTestRunner.TestFileSystem._instances[this.fileSystemPath]; - InspectorFrontendHost.events.dispatchEventToListeners( + Host.InspectorFrontendHost.events.dispatchEventToListeners( Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this.fileSystemPath); }, @@ -127,7 +127,7 @@ delete this._childrenMap[child.name]; child.parent = null; - InspectorFrontendHost.events.dispatchEventToListeners( + Host.InspectorFrontendHost.events.dispatchEventToListeners( Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, {changed: [], added: [], removed: [fullPath]}); @@ -152,7 +152,7 @@ const fullPath = this._fileSystem.fileSystemPath + child.fullPath; - InspectorFrontendHost.events.dispatchEventToListeners( + Host.InspectorFrontendHost.events.dispatchEventToListeners( Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, {changed: [], added: [fullPath], removed: []}); @@ -165,7 +165,7 @@ this._timestamp += 1000; const fullPath = this._fileSystem.fileSystemPath + this.fullPath; - InspectorFrontendHost.events.dispatchEventToListeners( + Host.InspectorFrontendHost.events.dispatchEventToListeners( Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, {changed: [fullPath], added: [], removed: []}); },
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js b/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js index 0590988..261bc0d 100644 --- a/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js +++ b/third_party/blink/renderer/devtools/front_end/color_picker/ContrastDetails.js
@@ -150,7 +150,7 @@ } static _showHelp() { - InspectorFrontendHost.openInNewTab( + Host.InspectorFrontendHost.openInNewTab( 'https://developers.google.com/web/fundamentals/accessibility/accessible-styles#color_and_contrast'); } @@ -254,12 +254,12 @@ this.dispatchEventToListeners(ColorPicker.ContrastDetails.Events.BackgroundColorPickerWillBeToggled, enabled); } - InspectorFrontendHost.setEyeDropperActive(enabled); + Host.InspectorFrontendHost.setEyeDropperActive(enabled); if (enabled) { - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound); } else { - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._bgColorPickedBound); } } @@ -273,7 +273,7 @@ const color = Common.Color.fromRGBA(rgba); this._contrastInfo.setBgColor(color); this._toggleBackgroundColorPicker(false); - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); } };
diff --git a/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js b/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js index 0e82aae..1034a32 100644 --- a/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js +++ b/third_party/blink/renderer/devtools/front_end/color_picker/Spectrum.js
@@ -930,12 +930,12 @@ this._contrastDetails.toggleBackgroundColorPicker(false); } - InspectorFrontendHost.setEyeDropperActive(enabled); + Host.InspectorFrontendHost.setEyeDropperActive(enabled); if (enabled) { - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound); } else { - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, this._colorPickedBound); } } @@ -949,7 +949,7 @@ const color = Common.Color.fromRGBA(rgba); this._innerSetColor( color.hsva(), '', undefined /* colorName */, undefined, ColorPicker.Spectrum._ChangeSource.Other); - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); } }; @@ -1151,7 +1151,7 @@ _onCopyIconClick() { this._swatchCopyIcon.setIconType('largeicon-checkmark'); - InspectorFrontendHost.copyText(this._colorString); + Host.InspectorFrontendHost.copyText(this._colorString); } _onCopyIconMouseout() {
diff --git a/third_party/blink/renderer/devtools/front_end/components/DockController.js b/third_party/blink/renderer/devtools/front_end/components/DockController.js index 9b77e3f..a87605e 100644 --- a/third_party/blink/renderer/devtools/front_end/components/DockController.js +++ b/third_party/blink/renderer/devtools/front_end/components/DockController.js
@@ -41,7 +41,7 @@ this._closeButton = new UI.ToolbarButton(Common.UIString('Close'), 'largeicon-delete'); this._closeButton.addEventListener( - UI.ToolbarButton.Events.Click, InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost)); + UI.ToolbarButton.Events.Click, Host.InspectorFrontendHost.closeWindow.bind(Host.InspectorFrontendHost)); if (!canDock) { this._dockSide = Components.DockController.State.Undocked; @@ -125,7 +125,7 @@ console.timeStamp('DockController.setIsDocked'); this._dockSide = dockSide; this._currentDockStateSetting.set(dockSide); - InspectorFrontendHost.setIsDocked( + Host.InspectorFrontendHost.setIsDocked( dockSide !== Components.DockController.State.Undocked, this._setIsDockedResponse.bind(this, eventData)); this._closeButton.setVisible(this._dockSide !== Components.DockController.State.Undocked); this.dispatchEventToListeners(Components.DockController.Events.DockSideChanged, eventData);
diff --git a/third_party/blink/renderer/devtools/front_end/components/Linkifier.js b/third_party/blink/renderer/devtools/front_end/components/Linkifier.js index 6d652b40..55b79ce 100644 --- a/third_party/blink/renderer/devtools/front_end/components/Linkifier.js +++ b/third_party/blink/renderer/devtools/front_end/components/Linkifier.js
@@ -626,10 +626,13 @@ result.push({ section: 'reveal', title: UI.openLinkExternallyLabel(), - handler: () => InspectorFrontendHost.openInNewTab(url) + handler: () => Host.InspectorFrontendHost.openInNewTab(url) }); - result.push( - {section: 'clipboard', title: UI.copyLinkAddressLabel(), handler: () => InspectorFrontendHost.copyText(url)}); + result.push({ + section: 'clipboard', + title: UI.copyLinkAddressLabel(), + handler: () => Host.InspectorFrontendHost.copyText(url) + }); } return result; } @@ -787,7 +790,7 @@ } contextMenu.revealSection().appendItem( - UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(contentProvider.contentURL())); + UI.openLinkExternallyLabel(), () => Host.InspectorFrontendHost.openInNewTab(contentProvider.contentURL())); for (const title of Components.Linkifier._linkHandlers.keys()) { const handler = Components.Linkifier._linkHandlers.get(title); contextMenu.revealSection().appendItem( @@ -798,6 +801,6 @@ } contextMenu.clipboardSection().appendItem( - UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(contentProvider.contentURL())); + UI.copyLinkAddressLabel(), () => Host.InspectorFrontendHost.copyText(contentProvider.contentURL())); } };
diff --git a/third_party/blink/renderer/devtools/front_end/components/Reload.js b/third_party/blink/renderer/devtools/front_end/components/Reload.js index 5544717..2fb94e06e 100644 --- a/third_party/blink/renderer/devtools/front_end/components/Reload.js +++ b/third_party/blink/renderer/devtools/front_end/components/Reload.js
@@ -4,7 +4,7 @@ Components.reload = function() { if (Components.dockController.canDock() && Components.dockController.dockSide() === Components.DockController.State.Undocked) { - InspectorFrontendHost.setIsDocked(true, function() {}); + Host.InspectorFrontendHost.setIsDocked(true, function() {}); } window.location.reload(); };
diff --git a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js index 7581535b..af780fcf 100644 --- a/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js +++ b/third_party/blink/renderer/devtools/front_end/console/ConsoleView.js
@@ -1554,7 +1554,7 @@ handleAction(context, actionId) { switch (actionId) { case 'console.show': - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); Common.console.show(); Console.ConsoleView.instance()._focusPrompt(); return true;
diff --git a/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js b/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js index 581f019e..20fa9eb7 100644 --- a/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js +++ b/third_party/blink/renderer/devtools/front_end/devices/DevicesView.js
@@ -43,11 +43,11 @@ this._updateFooter(); this._selectSidebarListItem(this._discoveryListItem, this._discoveryView); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DevicesUpdated, this._devicesUpdated, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged, this._devicesPortForwardingStatusChanged, this); } @@ -191,7 +191,7 @@ */ wasShown() { super.wasShown(); - InspectorFrontendHost.setDevicesUpdatesEnabled(true); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true); } /** @@ -199,7 +199,7 @@ */ willHide() { super.willHide(); - InspectorFrontendHost.setDevicesUpdatesEnabled(false); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false); } }; @@ -218,7 +218,7 @@ this._discoverUsbDevicesCheckbox = discoverUsbDevicesCheckbox.checkboxElement; this._discoverUsbDevicesCheckbox.addEventListener('click', () => { this._config.discoverUsbDevices = this._discoverUsbDevicesCheckbox.checked; - InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); + Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); }, false); const help = this.element.createChild('div', 'discovery-help'); @@ -236,7 +236,7 @@ for (const rule of config) { this._config.portForwardingConfig[rule.port] = rule.address; } - InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); + Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); }); this._portForwardingView.show(this.element); } @@ -589,7 +589,7 @@ function openNewTab() { if (section.browser) { - InspectorFrontendHost.openRemotePage(section.browser.id, newTabInput.value.trim() || 'about:blank'); + Host.InspectorFrontendHost.openRemotePage(section.browser.id, newTabInput.value.trim() || 'about:blank'); newTabInput.value = ''; } } @@ -677,7 +677,7 @@ */ function doAction(action) { if (section.page) { - InspectorFrontendHost.performActionOnRemotePage(section.page.id, action); + Host.InspectorFrontendHost.performActionOnRemotePage(section.page.id, action); } } }
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js b/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js index c4449be..b597ad7 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js +++ b/third_party/blink/renderer/devtools/front_end/elements/ElementsPanel.js
@@ -711,7 +711,7 @@ if (!this._notFirstInspectElement) { Elements.ElementsPanel._firstInspectElementNodeNameForTest = node.nodeName(); Elements.ElementsPanel._firstInspectElementCompletedForTest(); - InspectorFrontendHost.inspectElementCompleted(); + Host.InspectorFrontendHost.inspectElementCompleted(); } this._notFirstInspectElement = true; });
diff --git a/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js b/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js index cfd01cac..184a9b5 100644 --- a/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js +++ b/third_party/blink/renderer/devtools/front_end/elements/ElementsTreeElement.js
@@ -1726,19 +1726,19 @@ } _copyCSSPath() { - InspectorFrontendHost.copyText(Elements.DOMPath.cssPath(this._node, true)); + Host.InspectorFrontendHost.copyText(Elements.DOMPath.cssPath(this._node, true)); } _copyJSPath() { - InspectorFrontendHost.copyText(Elements.DOMPath.jsPath(this._node, true)); + Host.InspectorFrontendHost.copyText(Elements.DOMPath.jsPath(this._node, true)); } _copyXPath() { - InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, true)); + Host.InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, true)); } _copyFullXPath() { - InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, false)); + Host.InspectorFrontendHost.copyText(Elements.DOMPath.xPath(this._node, false)); } async _copyStyles() { @@ -1767,7 +1767,7 @@ lines.push(`${property.name}: ${property.value};`); } } - InspectorFrontendHost.copyText(lines.join('\n')); + Host.InspectorFrontendHost.copyText(lines.join('\n')); } _highlightSearchResults() {
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js b/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js index 49c8d16..740d45a 100644 --- a/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js +++ b/third_party/blink/renderer/devtools/front_end/emulation/AdvancedApp.js
@@ -186,7 +186,7 @@ } const bounds = /** @type {{x: number, y: number, width: number, height: number}} */ (event.data); console.timeStamp('AdvancedApp.setInspectedPageBounds'); - InspectorFrontendHost.setInspectedPageBounds(bounds); + Host.InspectorFrontendHost.setInspectedPageBounds(bounds); } };
diff --git a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js index c8445957..0d47280 100644 --- a/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js +++ b/third_party/blink/renderer/devtools/front_end/emulation/DeviceModeToolbar.js
@@ -308,7 +308,7 @@ contextMenu.appendItemsAtLocation('deviceModeMenu'); contextMenu.footerSection().appendItem(Common.UIString('Reset to defaults'), this._reset.bind(this)); contextMenu.footerSection().appendItem( - ls`Close DevTools`, InspectorFrontendHost.closeWindow.bind(InspectorFrontendHost)); + ls`Close DevTools`, Host.InspectorFrontendHost.closeWindow.bind(Host.InspectorFrontendHost)); /** * @param {!UI.ContextMenuSection} section
diff --git a/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js b/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js index 17fc8ce..91e2dc7 100644 --- a/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js +++ b/third_party/blink/renderer/devtools/front_end/extensions/ExtensionServer.js
@@ -82,14 +82,14 @@ this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this)); window.addEventListener('message', this._onWindowMessage.bind(this), false); // Only for main window. - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.SetInspectedTabId, this._setInspectedTabId, this); this._initExtensions(); } initializeExtensions() { - InspectorFrontendHost.setAddExtensionCallback(this._addExtension.bind(this)); + Host.InspectorFrontendHost.setAddExtensionCallback(this._addExtension.bind(this)); } /** @@ -713,7 +713,7 @@ extensionInfo, this._inspectedTabId, UI.themeSupport.themeName(), UI.shortcutRegistry.globalShortcutKeys(), Extensions.extensionServer['_extensionAPITestHook']); - InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI); + Host.InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, injectedAPI); this._registeredExtensions[extensionOrigin] = {name: name}; } const iframe = createElement('iframe');
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js index d8f75e69..5ec5249 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/AcornTokenizer.js
@@ -11,8 +11,7 @@ constructor(content) { this._content = content; this._comments = []; - this._tokenizer = - acorn.tokenizer(this._content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION, onComment: this._comments}); + this._tokenizer = acorn.tokenizer(this._content, {onComment: this._comments}); this._textCursor = new TextUtils.TextCursor(this._content.computeLineEndings()); this._tokenLineStart = 0; this._tokenLineEnd = 0;
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js index 56649a6..a453891 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/FormatterWorker.js
@@ -28,8 +28,6 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -FormatterWorker.ACORN_ECMA_VERSION = 2018; - /** * @param {string} mimeType * @return {function(string, function(string, ?string, number, number):(!Object|undefined))} @@ -114,7 +112,7 @@ * @param {string} content */ FormatterWorker.evaluatableJavaScriptSubstring = function(content) { - const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + const tokenizer = acorn.tokenizer(content, {}); let result = ''; try { let token = tokenizer.getToken(); @@ -163,7 +161,7 @@ let root; let body; try { - root = acorn.parse(wrapped, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + root = acorn.parse(wrapped, {}); body = root.body[0].expression.callee.body; } catch (e) { postMessage(''); @@ -265,7 +263,7 @@ FormatterWorker.javaScriptIdentifiers = function(content) { let root = null; try { - root = acorn.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + root = acorn.parse(content, {ranges: false}); } catch (e) { } @@ -370,7 +368,7 @@ return null; } try { - const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + const tokenizer = acorn.tokenizer(content, {}); while (tokenizer.getToken().type !== acorn.tokTypes.eof) { } } catch (e) { @@ -418,13 +416,13 @@ let parsed = null; try { // Try to parse as a function, anonymous function, or arrow function. - parsed = acorn.parse(`(${content})`, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + parsed = acorn.parse(`(${content})`, {}); } catch (e) { } if (!parsed) { try { // Try to parse as a method. - parsed = acorn.parse(`({${content}})`, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + parsed = acorn.parse(`({${content}})`, {}); } catch (e) { } } @@ -485,7 +483,7 @@ return null; } try { - const tokenizer = acorn.tokenizer(content, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + const tokenizer = acorn.tokenizer(content, {}); while (tokenizer.getToken().type !== acorn.tokTypes.eof) { } } catch (e) { @@ -494,7 +492,7 @@ const suffix = '.DEVTOOLS'; try { - acorn.parse(content + suffix, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + acorn.parse(content + suffix, {}); } catch (parseError) { // If this is an invalid location for a '.', don't attempt to give autocomplete if (parseError.message.startsWith('Unexpected token') && parseError.pos === content.length) { @@ -524,7 +522,7 @@ try { // Wrap content in paren to successfully parse object literals parsedContent = content[i] === '{' ? `(${content.substring(i)})${suffix}` : `${content.substring(i)}${suffix}`; - ast = acorn.parse(parsedContent, {ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + ast = acorn.parse(parsedContent, {}); break; } catch (e) { }
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js index 8db99f9..e735745f 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptFormatter.js
@@ -51,8 +51,7 @@ this._content = text.substring(this._fromOffset, this._toOffset); this._lastLineNumber = 0; this._tokenizer = new FormatterWorker.AcornTokenizer(this._content); - const ast = acorn.parse( - this._content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION, preserveParens: true}); + const ast = acorn.parse(this._content, {ranges: false, preserveParens: true}); const walker = new FormatterWorker.ESTreeWalker(this._beforeVisit.bind(this), this._afterVisit.bind(this)); walker.walk(ast); }
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js index 3f0f74d..e15d00e 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/JavaScriptOutline.js
@@ -11,9 +11,9 @@ let ast; try { - ast = acorn.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + ast = acorn.parse(content, {ranges: false}); } catch (e) { - ast = acorn.loose.parse(content, {ranges: false, ecmaVersion: FormatterWorker.ACORN_ECMA_VERSION}); + ast = acorn.loose.parse(content, {ranges: false}); } const textCursor = new TextUtils.TextCursor(content.computeLineEndings());
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js index 189c222..fae8eae 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn.js
@@ -2,5312 +2,5002 @@ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) : typeof define === 'function' && define.amd ? define(['exports'], factory) : - (factory((global.acorn = {}))); -}(this, (function (exports) { 'use strict'; + (global = global || self, factory(global.acorn = {})); +}(this, function (exports) { 'use strict'; -// Reserved word lists for various dialects of the language + // Reserved word lists for various dialects of the language -var reservedWords = { - 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", - 5: "class enum extends super const export import", - 6: "enum", - strict: "implements interface let package private protected public static yield", - strictBind: "eval arguments" -}; + var reservedWords = { + 3: "abstract boolean byte char class double enum export extends final float goto implements import int interface long native package private protected public short static super synchronized throws transient volatile", + 5: "class enum extends super const export import", + 6: "enum", + strict: "implements interface let package private protected public static yield", + strictBind: "eval arguments" + }; -// And the keywords + // And the keywords -var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; + var ecma5AndLessKeywords = "break case catch continue debugger default do else finally for function if return switch throw try var while with null true false instanceof typeof void delete new in this"; -var keywords = { - 5: ecma5AndLessKeywords, - 6: ecma5AndLessKeywords + " const class extends export import super" -}; + var keywords = { + 5: ecma5AndLessKeywords, + "5module": ecma5AndLessKeywords + " export import", + 6: ecma5AndLessKeywords + " const class extends export import super" + }; -var keywordRelationalOperator = /^in(stanceof)?$/; + var keywordRelationalOperator = /^in(stanceof)?$/; -// ## Character categories + // ## Character categories -// Big ugly regular expressions that match characters in the -// whitespace, identifier, and identifier-start categories. These -// are only applied when a character is found to actually have a -// code point above 128. -// Generated by `bin/generate-identifier-regex.js`. + // Big ugly regular expressions that match characters in the + // whitespace, identifier, and identifier-start categories. These + // are only applied when a character is found to actually have a + // code point above 128. + // Generated by `bin/generate-identifier-regex.js`. + var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e86-\u0e8a\u0e8c-\u0ea3\u0ea5\u0ea7-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1cfa\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7bf\ua7c2-\ua7c6\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab67\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; + var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; -var nonASCIIidentifierStartChars = "\xaa\xb5\xba\xc0-\xd6\xd8-\xf6\xf8-\u02c1\u02c6-\u02d1\u02e0-\u02e4\u02ec\u02ee\u0370-\u0374\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0481\u048a-\u052f\u0531-\u0556\u0559\u0560-\u0588\u05d0-\u05ea\u05ef-\u05f2\u0620-\u064a\u066e\u066f\u0671-\u06d3\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u06fc\u06ff\u0710\u0712-\u072f\u074d-\u07a5\u07b1\u07ca-\u07ea\u07f4\u07f5\u07fa\u0800-\u0815\u081a\u0824\u0828\u0840-\u0858\u0860-\u086a\u08a0-\u08b4\u08b6-\u08bd\u0904-\u0939\u093d\u0950\u0958-\u0961\u0971-\u0980\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd\u09ce\u09dc\u09dd\u09df-\u09e1\u09f0\u09f1\u09fc\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a59-\u0a5c\u0a5e\u0a72-\u0a74\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd\u0ad0\u0ae0\u0ae1\u0af9\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b5c\u0b5d\u0b5f-\u0b61\u0b71\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bd0\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c58-\u0c5a\u0c60\u0c61\u0c80\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd\u0cde\u0ce0\u0ce1\u0cf1\u0cf2\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d\u0d4e\u0d54-\u0d56\u0d5f-\u0d61\u0d7a-\u0d7f\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0edc-\u0edf\u0f00\u0f40-\u0f47\u0f49-\u0f6c\u0f88-\u0f8c\u1000-\u102a\u103f\u1050-\u1055\u105a-\u105d\u1061\u1065\u1066\u106e-\u1070\u1075-\u1081\u108e\u10a0-\u10c5\u10c7\u10cd\u10d0-\u10fa\u10fc-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u166c\u166f-\u167f\u1681-\u169a\u16a0-\u16ea\u16ee-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17d7\u17dc\u1820-\u1878\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1950-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u1a00-\u1a16\u1a20-\u1a54\u1aa7\u1b05-\u1b33\u1b45-\u1b4b\u1b83-\u1ba0\u1bae\u1baf\u1bba-\u1be5\u1c00-\u1c23\u1c4d-\u1c4f\u1c5a-\u1c7d\u1c80-\u1c88\u1c90-\u1cba\u1cbd-\u1cbf\u1ce9-\u1cec\u1cee-\u1cf1\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2118-\u211d\u2124\u2126\u2128\u212a-\u2139\u213c-\u213f\u2145-\u2149\u214e\u2160-\u2188\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309b-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312f\u3131-\u318e\u31a0-\u31ba\u31f0-\u31ff\u3400-\u4db5\u4e00-\u9fef\ua000-\ua48c\ua4d0-\ua4fd\ua500-\ua60c\ua610-\ua61f\ua62a\ua62b\ua640-\ua66e\ua67f-\ua69d\ua6a0-\ua6ef\ua717-\ua71f\ua722-\ua788\ua78b-\ua7b9\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua822\ua840-\ua873\ua882-\ua8b3\ua8f2-\ua8f7\ua8fb\ua8fd\ua8fe\ua90a-\ua925\ua930-\ua946\ua960-\ua97c\ua984-\ua9b2\ua9cf\ua9e0-\ua9e4\ua9e6-\ua9ef\ua9fa-\ua9fe\uaa00-\uaa28\uaa40-\uaa42\uaa44-\uaa4b\uaa60-\uaa76\uaa7a\uaa7e-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaadd\uaae0-\uaaea\uaaf2-\uaaf4\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab5a\uab5c-\uab65\uab70-\uabe2\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\uf900-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\ufb1d\ufb1f-\ufb28\ufb2a-\ufb36\ufb38-\ufb3c\ufb3e\ufb40\ufb41\ufb43\ufb44\ufb46-\ufbb1\ufbd3-\ufd3d\ufd50-\ufd8f\ufd92-\ufdc7\ufdf0-\ufdfb\ufe70-\ufe74\ufe76-\ufefc\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc"; -var nonASCIIidentifierChars = "\u200c\u200d\xb7\u0300-\u036f\u0387\u0483-\u0487\u0591-\u05bd\u05bf\u05c1\u05c2\u05c4\u05c5\u05c7\u0610-\u061a\u064b-\u0669\u0670\u06d6-\u06dc\u06df-\u06e4\u06e7\u06e8\u06ea-\u06ed\u06f0-\u06f9\u0711\u0730-\u074a\u07a6-\u07b0\u07c0-\u07c9\u07eb-\u07f3\u07fd\u0816-\u0819\u081b-\u0823\u0825-\u0827\u0829-\u082d\u0859-\u085b\u08d3-\u08e1\u08e3-\u0903\u093a-\u093c\u093e-\u094f\u0951-\u0957\u0962\u0963\u0966-\u096f\u0981-\u0983\u09bc\u09be-\u09c4\u09c7\u09c8\u09cb-\u09cd\u09d7\u09e2\u09e3\u09e6-\u09ef\u09fe\u0a01-\u0a03\u0a3c\u0a3e-\u0a42\u0a47\u0a48\u0a4b-\u0a4d\u0a51\u0a66-\u0a71\u0a75\u0a81-\u0a83\u0abc\u0abe-\u0ac5\u0ac7-\u0ac9\u0acb-\u0acd\u0ae2\u0ae3\u0ae6-\u0aef\u0afa-\u0aff\u0b01-\u0b03\u0b3c\u0b3e-\u0b44\u0b47\u0b48\u0b4b-\u0b4d\u0b56\u0b57\u0b62\u0b63\u0b66-\u0b6f\u0b82\u0bbe-\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcd\u0bd7\u0be6-\u0bef\u0c00-\u0c04\u0c3e-\u0c44\u0c46-\u0c48\u0c4a-\u0c4d\u0c55\u0c56\u0c62\u0c63\u0c66-\u0c6f\u0c81-\u0c83\u0cbc\u0cbe-\u0cc4\u0cc6-\u0cc8\u0cca-\u0ccd\u0cd5\u0cd6\u0ce2\u0ce3\u0ce6-\u0cef\u0d00-\u0d03\u0d3b\u0d3c\u0d3e-\u0d44\u0d46-\u0d48\u0d4a-\u0d4d\u0d57\u0d62\u0d63\u0d66-\u0d6f\u0d82\u0d83\u0dca\u0dcf-\u0dd4\u0dd6\u0dd8-\u0ddf\u0de6-\u0def\u0df2\u0df3\u0e31\u0e34-\u0e3a\u0e47-\u0e4e\u0e50-\u0e59\u0eb1\u0eb4-\u0eb9\u0ebb\u0ebc\u0ec8-\u0ecd\u0ed0-\u0ed9\u0f18\u0f19\u0f20-\u0f29\u0f35\u0f37\u0f39\u0f3e\u0f3f\u0f71-\u0f84\u0f86\u0f87\u0f8d-\u0f97\u0f99-\u0fbc\u0fc6\u102b-\u103e\u1040-\u1049\u1056-\u1059\u105e-\u1060\u1062-\u1064\u1067-\u106d\u1071-\u1074\u1082-\u108d\u108f-\u109d\u135d-\u135f\u1369-\u1371\u1712-\u1714\u1732-\u1734\u1752\u1753\u1772\u1773\u17b4-\u17d3\u17dd\u17e0-\u17e9\u180b-\u180d\u1810-\u1819\u18a9\u1920-\u192b\u1930-\u193b\u1946-\u194f\u19d0-\u19da\u1a17-\u1a1b\u1a55-\u1a5e\u1a60-\u1a7c\u1a7f-\u1a89\u1a90-\u1a99\u1ab0-\u1abd\u1b00-\u1b04\u1b34-\u1b44\u1b50-\u1b59\u1b6b-\u1b73\u1b80-\u1b82\u1ba1-\u1bad\u1bb0-\u1bb9\u1be6-\u1bf3\u1c24-\u1c37\u1c40-\u1c49\u1c50-\u1c59\u1cd0-\u1cd2\u1cd4-\u1ce8\u1ced\u1cf2-\u1cf4\u1cf7-\u1cf9\u1dc0-\u1df9\u1dfb-\u1dff\u203f\u2040\u2054\u20d0-\u20dc\u20e1\u20e5-\u20f0\u2cef-\u2cf1\u2d7f\u2de0-\u2dff\u302a-\u302f\u3099\u309a\ua620-\ua629\ua66f\ua674-\ua67d\ua69e\ua69f\ua6f0\ua6f1\ua802\ua806\ua80b\ua823-\ua827\ua880\ua881\ua8b4-\ua8c5\ua8d0-\ua8d9\ua8e0-\ua8f1\ua8ff-\ua909\ua926-\ua92d\ua947-\ua953\ua980-\ua983\ua9b3-\ua9c0\ua9d0-\ua9d9\ua9e5\ua9f0-\ua9f9\uaa29-\uaa36\uaa43\uaa4c\uaa4d\uaa50-\uaa59\uaa7b-\uaa7d\uaab0\uaab2-\uaab4\uaab7\uaab8\uaabe\uaabf\uaac1\uaaeb-\uaaef\uaaf5\uaaf6\uabe3-\uabea\uabec\uabed\uabf0-\uabf9\ufb1e\ufe00-\ufe0f\ufe20-\ufe2f\ufe33\ufe34\ufe4d-\ufe4f\uff10-\uff19\uff3f"; + var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); + var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); -var nonASCIIidentifierStart = new RegExp("[" + nonASCIIidentifierStartChars + "]"); -var nonASCIIidentifier = new RegExp("[" + nonASCIIidentifierStartChars + nonASCIIidentifierChars + "]"); + nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; -nonASCIIidentifierStartChars = nonASCIIidentifierChars = null; + // These are a run-length and offset encoded representation of the + // >0xffff code points that are a valid part of identifiers. The + // offset starts at 0x10000, and each pair of numbers represents an + // offset to the next range, and then a size of the range. They were + // generated by bin/generate-identifier-regex.js -// These are a run-length and offset encoded representation of the -// >0xffff code points that are a valid part of identifiers. The -// offset starts at 0x10000, and each pair of numbers represents an -// offset to the next range, and then a size of the range. They were -// generated by bin/generate-identifier-regex.js + // eslint-disable-next-line comma-spacing + var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,155,22,13,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,21,0,33,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,14,0,72,26,230,43,117,63,32,0,161,7,3,38,17,0,2,0,29,0,11,39,8,0,22,0,12,45,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,74,6,0,67,12,65,1,2,0,29,6135,9,754,9486,286,50,2,18,3,9,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,2357,44,11,6,17,0,370,43,1301,196,60,67,8,0,1205,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541]; -// eslint-disable-next-line comma-spacing -var astralIdentifierStartCodes = [0,11,2,25,2,18,2,1,2,14,3,13,35,122,70,52,268,28,4,48,48,31,14,29,6,37,11,29,3,35,5,7,2,4,43,157,19,35,5,35,5,39,9,51,157,310,10,21,11,7,153,5,3,0,2,43,2,1,4,0,3,22,11,22,10,30,66,18,2,1,11,21,11,25,71,55,7,1,65,0,16,3,2,2,2,28,43,28,4,28,36,7,2,27,28,53,11,21,11,18,14,17,111,72,56,50,14,50,14,35,477,28,11,0,9,21,190,52,76,44,33,24,27,35,30,0,12,34,4,0,13,47,15,3,22,0,2,0,36,17,2,24,85,6,2,0,2,3,2,14,2,9,8,46,39,7,3,1,3,21,2,6,2,1,2,4,4,0,19,0,13,4,159,52,19,3,54,47,21,1,2,0,185,46,42,3,37,47,21,0,60,42,86,26,230,43,117,63,32,0,257,0,11,39,8,0,22,0,12,39,3,3,20,0,35,56,264,8,2,36,18,0,50,29,113,6,2,1,2,37,22,0,26,5,2,1,2,31,15,0,328,18,270,921,103,110,18,195,2749,1070,4050,582,8634,568,8,30,114,29,19,47,17,3,32,20,6,18,689,63,129,68,12,0,67,12,65,1,31,6129,15,754,9486,286,82,395,2309,106,6,12,4,8,8,9,5991,84,2,70,2,1,3,0,3,1,3,3,2,11,2,0,2,6,2,64,2,3,3,7,2,6,2,27,2,3,2,4,2,0,4,6,2,339,3,24,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,30,2,24,2,7,4149,196,60,67,1213,3,2,26,2,1,2,0,3,0,2,9,2,3,2,0,2,0,7,0,5,0,2,0,2,0,2,2,2,1,2,0,3,0,2,0,2,0,2,0,2,0,2,1,2,0,3,3,2,6,2,3,2,3,2,0,2,9,2,16,6,2,2,4,2,16,4421,42710,42,4148,12,221,3,5761,15,7472,3104,541]; + // eslint-disable-next-line comma-spacing + var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,232,6,3,6,4,0,29,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1014,0,2,54,8,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,262,6,10,9,419,13,1495,6,110,6,6,9,792487,239]; -// eslint-disable-next-line comma-spacing -var astralIdentifierCodes = [509,0,227,0,150,4,294,9,1368,2,2,1,6,3,41,2,5,0,166,1,574,3,9,9,525,10,176,2,54,14,32,9,16,3,46,10,54,9,7,2,37,13,2,9,6,1,45,0,13,2,49,13,9,3,4,9,83,11,7,0,161,11,6,9,7,3,56,1,2,6,3,1,3,2,10,0,11,1,3,6,4,4,193,17,10,9,5,0,82,19,13,9,214,6,3,8,28,1,83,16,16,9,82,12,9,9,84,14,5,9,243,14,166,9,280,9,41,6,2,3,9,0,10,10,47,15,406,7,2,7,17,9,57,21,2,13,123,5,4,0,2,1,2,6,2,0,9,9,49,4,2,1,2,4,9,9,330,3,19306,9,135,4,60,6,26,9,1016,45,17,3,19723,1,5319,4,4,5,9,7,3,6,31,3,149,2,1418,49,513,54,5,49,9,0,15,0,23,4,2,14,1361,6,2,16,3,6,2,1,2,4,2214,6,110,6,6,9,792487,239]; - -// This has a complexity linear to the value of the code. The -// assumption is that looking up astral identifier characters is -// rare. -function isInAstralSet(code, set) { - var pos = 0x10000; - for (var i = 0; i < set.length; i += 2) { - pos += set[i]; - if (pos > code) { return false } - pos += set[i + 1]; - if (pos >= code) { return true } + // This has a complexity linear to the value of the code. The + // assumption is that looking up astral identifier characters is + // rare. + function isInAstralSet(code, set) { + var pos = 0x10000; + for (var i = 0; i < set.length; i += 2) { + pos += set[i]; + if (pos > code) { return false } + pos += set[i + 1]; + if (pos >= code) { return true } + } } -} -// Test whether a given character code starts an identifier. + // Test whether a given character code starts an identifier. -function isIdentifierStart(code, astral) { - if (code < 65) { return code === 36 } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) -} + function isIdentifierStart(code, astral) { + if (code < 65) { return code === 36 } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifierStart.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) + } -// Test whether a given character is part of an identifier. + // Test whether a given character is part of an identifier. -function isIdentifierChar(code, astral) { - if (code < 48) { return code === 36 } - if (code < 58) { return true } - if (code < 65) { return false } - if (code < 91) { return true } - if (code < 97) { return code === 95 } - if (code < 123) { return true } - if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } - if (astral === false) { return false } - return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) -} + function isIdentifierChar(code, astral) { + if (code < 48) { return code === 36 } + if (code < 58) { return true } + if (code < 65) { return false } + if (code < 91) { return true } + if (code < 97) { return code === 95 } + if (code < 123) { return true } + if (code <= 0xffff) { return code >= 0xaa && nonASCIIidentifier.test(String.fromCharCode(code)) } + if (astral === false) { return false } + return isInAstralSet(code, astralIdentifierStartCodes) || isInAstralSet(code, astralIdentifierCodes) + } -// ## Token types + // ## Token types -// The assignment of fine-grained, information-carrying type objects -// allows the tokenizer to store the information it has about a -// token in a way that is very cheap for the parser to look up. + // The assignment of fine-grained, information-carrying type objects + // allows the tokenizer to store the information it has about a + // token in a way that is very cheap for the parser to look up. -// All token type variables start with an underscore, to make them -// easy to recognize. + // All token type variables start with an underscore, to make them + // easy to recognize. -// The `beforeExpr` property is used to disambiguate between regular -// expressions and divisions. It is set on all token types that can -// be followed by an expression (thus, a slash after them would be a -// regular expression). -// -// The `startsExpr` property is used to check if the token ends a -// `yield` expression. It is set on all token types that either can -// directly start an expression (like a quotation mark) or can -// continue an expression (like the body of a string). -// -// `isLoop` marks a keyword as starting a loop, which is important -// to know when parsing a label, in order to allow or disallow -// continue jumps to that label. - -var TokenType = function TokenType(label, conf) { - if ( conf === void 0 ) conf = {}; - - this.label = label; - this.keyword = conf.keyword; - this.beforeExpr = !!conf.beforeExpr; - this.startsExpr = !!conf.startsExpr; - this.isLoop = !!conf.isLoop; - this.isAssign = !!conf.isAssign; - this.prefix = !!conf.prefix; - this.postfix = !!conf.postfix; - this.binop = conf.binop || null; - this.updateContext = null; -}; - -function binop(name, prec) { - return new TokenType(name, {beforeExpr: true, binop: prec}) -} -var beforeExpr = {beforeExpr: true}; -var startsExpr = {startsExpr: true}; - -// Map keyword names to token types. - -var keywords$1 = {}; - -// Succinct definitions of keyword token types -function kw(name, options) { - if ( options === void 0 ) options = {}; - - options.keyword = name; - return keywords$1[name] = new TokenType(name, options) -} - -var types = { - num: new TokenType("num", startsExpr), - regexp: new TokenType("regexp", startsExpr), - string: new TokenType("string", startsExpr), - name: new TokenType("name", startsExpr), - eof: new TokenType("eof"), - - // Punctuation token types. - bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), - bracketR: new TokenType("]"), - braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), - braceR: new TokenType("}"), - parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), - parenR: new TokenType(")"), - comma: new TokenType(",", beforeExpr), - semi: new TokenType(";", beforeExpr), - colon: new TokenType(":", beforeExpr), - dot: new TokenType("."), - question: new TokenType("?", beforeExpr), - arrow: new TokenType("=>", beforeExpr), - template: new TokenType("template"), - invalidTemplate: new TokenType("invalidTemplate"), - ellipsis: new TokenType("...", beforeExpr), - backQuote: new TokenType("`", startsExpr), - dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), - - // Operators. These carry several kinds of properties to help the - // parser use them properly (the presence of these properties is - // what categorizes them as operators). + // The `beforeExpr` property is used to disambiguate between regular + // expressions and divisions. It is set on all token types that can + // be followed by an expression (thus, a slash after them would be a + // regular expression). // - // `binop`, when present, specifies that this operator is a binary - // operator, and will refer to its precedence. + // The `startsExpr` property is used to check if the token ends a + // `yield` expression. It is set on all token types that either can + // directly start an expression (like a quotation mark) or can + // continue an expression (like the body of a string). // - // `prefix` and `postfix` mark the operator as a prefix or postfix - // unary operator. - // - // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as - // binary operators with a very low precedence, that should result - // in AssignmentExpression nodes. + // `isLoop` marks a keyword as starting a loop, which is important + // to know when parsing a label, in order to allow or disallow + // continue jumps to that label. - eq: new TokenType("=", {beforeExpr: true, isAssign: true}), - assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), - incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), - prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), - logicalOR: binop("||", 1), - logicalAND: binop("&&", 2), - bitwiseOR: binop("|", 3), - bitwiseXOR: binop("^", 4), - bitwiseAND: binop("&", 5), - equality: binop("==/!=/===/!==", 6), - relational: binop("</>/<=/>=", 7), - bitShift: binop("<</>>/>>>", 8), - plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), - modulo: binop("%", 10), - star: binop("*", 10), - slash: binop("/", 10), - starstar: new TokenType("**", {beforeExpr: true}), + var TokenType = function TokenType(label, conf) { + if ( conf === void 0 ) conf = {}; - // Keyword token types. - _break: kw("break"), - _case: kw("case", beforeExpr), - _catch: kw("catch"), - _continue: kw("continue"), - _debugger: kw("debugger"), - _default: kw("default", beforeExpr), - _do: kw("do", {isLoop: true, beforeExpr: true}), - _else: kw("else", beforeExpr), - _finally: kw("finally"), - _for: kw("for", {isLoop: true}), - _function: kw("function", startsExpr), - _if: kw("if"), - _return: kw("return", beforeExpr), - _switch: kw("switch"), - _throw: kw("throw", beforeExpr), - _try: kw("try"), - _var: kw("var"), - _const: kw("const"), - _while: kw("while", {isLoop: true}), - _with: kw("with"), - _new: kw("new", {beforeExpr: true, startsExpr: true}), - _this: kw("this", startsExpr), - _super: kw("super", startsExpr), - _class: kw("class", startsExpr), - _extends: kw("extends", beforeExpr), - _export: kw("export"), - _import: kw("import"), - _null: kw("null", startsExpr), - _true: kw("true", startsExpr), - _false: kw("false", startsExpr), - _in: kw("in", {beforeExpr: true, binop: 7}), - _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), - _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), - _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), - _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) -}; + this.label = label; + this.keyword = conf.keyword; + this.beforeExpr = !!conf.beforeExpr; + this.startsExpr = !!conf.startsExpr; + this.isLoop = !!conf.isLoop; + this.isAssign = !!conf.isAssign; + this.prefix = !!conf.prefix; + this.postfix = !!conf.postfix; + this.binop = conf.binop || null; + this.updateContext = null; + }; -// Matches a whole line break (where CRLF is considered a single -// line break). Used to count lines. + function binop(name, prec) { + return new TokenType(name, {beforeExpr: true, binop: prec}) + } + var beforeExpr = {beforeExpr: true}, startsExpr = {startsExpr: true}; -var lineBreak = /\r\n?|\n|\u2028|\u2029/; -var lineBreakG = new RegExp(lineBreak.source, "g"); + // Map keyword names to token types. -function isNewLine(code, ecma2019String) { - return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029)) -} + var keywords$1 = {}; -var nonASCIIwhitespace = /[\u1680\u180e\u2000-\u200a\u202f\u205f\u3000\ufeff]/; + // Succinct definitions of keyword token types + function kw(name, options) { + if ( options === void 0 ) options = {}; -var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + options.keyword = name; + return keywords$1[name] = new TokenType(name, options) + } -var ref = Object.prototype; -var hasOwnProperty = ref.hasOwnProperty; -var toString = ref.toString; + var types = { + num: new TokenType("num", startsExpr), + regexp: new TokenType("regexp", startsExpr), + string: new TokenType("string", startsExpr), + name: new TokenType("name", startsExpr), + eof: new TokenType("eof"), -// Checks if an object has a property. + // Punctuation token types. + bracketL: new TokenType("[", {beforeExpr: true, startsExpr: true}), + bracketR: new TokenType("]"), + braceL: new TokenType("{", {beforeExpr: true, startsExpr: true}), + braceR: new TokenType("}"), + parenL: new TokenType("(", {beforeExpr: true, startsExpr: true}), + parenR: new TokenType(")"), + comma: new TokenType(",", beforeExpr), + semi: new TokenType(";", beforeExpr), + colon: new TokenType(":", beforeExpr), + dot: new TokenType("."), + question: new TokenType("?", beforeExpr), + arrow: new TokenType("=>", beforeExpr), + template: new TokenType("template"), + invalidTemplate: new TokenType("invalidTemplate"), + ellipsis: new TokenType("...", beforeExpr), + backQuote: new TokenType("`", startsExpr), + dollarBraceL: new TokenType("${", {beforeExpr: true, startsExpr: true}), -function has(obj, propName) { - return hasOwnProperty.call(obj, propName) -} + // Operators. These carry several kinds of properties to help the + // parser use them properly (the presence of these properties is + // what categorizes them as operators). + // + // `binop`, when present, specifies that this operator is a binary + // operator, and will refer to its precedence. + // + // `prefix` and `postfix` mark the operator as a prefix or postfix + // unary operator. + // + // `isAssign` marks all of `=`, `+=`, `-=` etcetera, which act as + // binary operators with a very low precedence, that should result + // in AssignmentExpression nodes. -var isArray = Array.isArray || (function (obj) { return ( - toString.call(obj) === "[object Array]" -); }); + eq: new TokenType("=", {beforeExpr: true, isAssign: true}), + assign: new TokenType("_=", {beforeExpr: true, isAssign: true}), + incDec: new TokenType("++/--", {prefix: true, postfix: true, startsExpr: true}), + prefix: new TokenType("!/~", {beforeExpr: true, prefix: true, startsExpr: true}), + logicalOR: binop("||", 1), + logicalAND: binop("&&", 2), + bitwiseOR: binop("|", 3), + bitwiseXOR: binop("^", 4), + bitwiseAND: binop("&", 5), + equality: binop("==/!=/===/!==", 6), + relational: binop("</>/<=/>=", 7), + bitShift: binop("<</>>/>>>", 8), + plusMin: new TokenType("+/-", {beforeExpr: true, binop: 9, prefix: true, startsExpr: true}), + modulo: binop("%", 10), + star: binop("*", 10), + slash: binop("/", 10), + starstar: new TokenType("**", {beforeExpr: true}), -// These are used when `options.locations` is on, for the -// `startLoc` and `endLoc` properties. + // Keyword token types. + _break: kw("break"), + _case: kw("case", beforeExpr), + _catch: kw("catch"), + _continue: kw("continue"), + _debugger: kw("debugger"), + _default: kw("default", beforeExpr), + _do: kw("do", {isLoop: true, beforeExpr: true}), + _else: kw("else", beforeExpr), + _finally: kw("finally"), + _for: kw("for", {isLoop: true}), + _function: kw("function", startsExpr), + _if: kw("if"), + _return: kw("return", beforeExpr), + _switch: kw("switch"), + _throw: kw("throw", beforeExpr), + _try: kw("try"), + _var: kw("var"), + _const: kw("const"), + _while: kw("while", {isLoop: true}), + _with: kw("with"), + _new: kw("new", {beforeExpr: true, startsExpr: true}), + _this: kw("this", startsExpr), + _super: kw("super", startsExpr), + _class: kw("class", startsExpr), + _extends: kw("extends", beforeExpr), + _export: kw("export"), + _import: kw("import", startsExpr), + _null: kw("null", startsExpr), + _true: kw("true", startsExpr), + _false: kw("false", startsExpr), + _in: kw("in", {beforeExpr: true, binop: 7}), + _instanceof: kw("instanceof", {beforeExpr: true, binop: 7}), + _typeof: kw("typeof", {beforeExpr: true, prefix: true, startsExpr: true}), + _void: kw("void", {beforeExpr: true, prefix: true, startsExpr: true}), + _delete: kw("delete", {beforeExpr: true, prefix: true, startsExpr: true}) + }; -var Position = function Position(line, col) { - this.line = line; - this.column = col; -}; + // Matches a whole line break (where CRLF is considered a single + // line break). Used to count lines. -Position.prototype.offset = function offset (n) { - return new Position(this.line, this.column + n) -}; + var lineBreak = /\r\n?|\n|\u2028|\u2029/; + var lineBreakG = new RegExp(lineBreak.source, "g"); -var SourceLocation = function SourceLocation(p, start, end) { - this.start = start; - this.end = end; - if (p.sourceFile !== null) { this.source = p.sourceFile; } -}; + function isNewLine(code, ecma2019String) { + return code === 10 || code === 13 || (!ecma2019String && (code === 0x2028 || code === 0x2029)) + } -// The `getLineInfo` function is mostly useful when the -// `locations` option is off (for performance reasons) and you -// want to find the line/column position for a given character -// offset. `input` should be the code string that the offset refers -// into. + var nonASCIIwhitespace = /[\u1680\u2000-\u200a\u202f\u205f\u3000\ufeff]/; -function getLineInfo(input, offset) { - for (var line = 1, cur = 0;;) { - lineBreakG.lastIndex = cur; - var match = lineBreakG.exec(input); - if (match && match.index < offset) { - ++line; - cur = match.index + match[0].length; + var skipWhiteSpace = /(?:\s|\/\/.*|\/\*[^]*?\*\/)*/g; + + var ref = Object.prototype; + var hasOwnProperty = ref.hasOwnProperty; + var toString = ref.toString; + + // Checks if an object has a property. + + function has(obj, propName) { + return hasOwnProperty.call(obj, propName) + } + + var isArray = Array.isArray || (function (obj) { return ( + toString.call(obj) === "[object Array]" + ); }); + + function wordsRegexp(words) { + return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") + } + + // These are used when `options.locations` is on, for the + // `startLoc` and `endLoc` properties. + + var Position = function Position(line, col) { + this.line = line; + this.column = col; + }; + + Position.prototype.offset = function offset (n) { + return new Position(this.line, this.column + n) + }; + + var SourceLocation = function SourceLocation(p, start, end) { + this.start = start; + this.end = end; + if (p.sourceFile !== null) { this.source = p.sourceFile; } + }; + + // The `getLineInfo` function is mostly useful when the + // `locations` option is off (for performance reasons) and you + // want to find the line/column position for a given character + // offset. `input` should be the code string that the offset refers + // into. + + function getLineInfo(input, offset) { + for (var line = 1, cur = 0;;) { + lineBreakG.lastIndex = cur; + var match = lineBreakG.exec(input); + if (match && match.index < offset) { + ++line; + cur = match.index + match[0].length; + } else { + return new Position(line, offset - cur) + } + } + } + + // A second optional argument can be given to further configure + // the parser process. These options are recognized: + + var defaultOptions = { + // `ecmaVersion` indicates the ECMAScript version to parse. Must be + // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10 + // (2019). This influences support for strict mode, the set of + // reserved words, and support for new syntax features. The default + // is 10. + ecmaVersion: 10, + // `sourceType` indicates the mode the code should be parsed in. + // Can be either `"script"` or `"module"`. This influences global + // strict mode and parsing of `import` and `export` declarations. + sourceType: "script", + // `onInsertedSemicolon` can be a callback that will be called + // when a semicolon is automatically inserted. It will be passed + // the position of the comma as an offset, and if `locations` is + // enabled, it is given the location as a `{line, column}` object + // as second argument. + onInsertedSemicolon: null, + // `onTrailingComma` is similar to `onInsertedSemicolon`, but for + // trailing commas. + onTrailingComma: null, + // By default, reserved words are only enforced if ecmaVersion >= 5. + // Set `allowReserved` to a boolean value to explicitly turn this on + // an off. When this option has the value "never", reserved words + // and keywords can also not be used as property names. + allowReserved: null, + // When enabled, a return at the top level is not considered an + // error. + allowReturnOutsideFunction: false, + // When enabled, import/export statements are not constrained to + // appearing at the top of the program. + allowImportExportEverywhere: false, + // When enabled, await identifiers are allowed to appear at the top-level scope, + // but they are still not allowed in non-async functions. + allowAwaitOutsideFunction: false, + // When enabled, hashbang directive in the beginning of file + // is allowed and treated as a line comment. + allowHashBang: false, + // When `locations` is on, `loc` properties holding objects with + // `start` and `end` properties in `{line, column}` form (with + // line being 1-based and column 0-based) will be attached to the + // nodes. + locations: false, + // A function can be passed as `onToken` option, which will + // cause Acorn to call that function with object in the same + // format as tokens returned from `tokenizer().getToken()`. Note + // that you are not allowed to call the parser from the + // callback—that will corrupt its internal state. + onToken: null, + // A function can be passed as `onComment` option, which will + // cause Acorn to call that function with `(block, text, start, + // end)` parameters whenever a comment is skipped. `block` is a + // boolean indicating whether this is a block (`/* */`) comment, + // `text` is the content of the comment, and `start` and `end` are + // character offsets that denote the start and end of the comment. + // When the `locations` option is on, two more parameters are + // passed, the full `{line, column}` locations of the start and + // end of the comments. Note that you are not allowed to call the + // parser from the callback—that will corrupt its internal state. + onComment: null, + // Nodes have their start and end characters offsets recorded in + // `start` and `end` properties (directly on the node, rather than + // the `loc` object, which holds line/column data. To also add a + // [semi-standardized][range] `range` property holding a `[start, + // end]` array with the same numbers, set the `ranges` option to + // `true`. + // + // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 + ranges: false, + // It is possible to parse multiple files into a single AST by + // passing the tree produced by parsing the first file as + // `program` option in subsequent parses. This will add the + // toplevel forms of the parsed file to the `Program` (top) node + // of an existing parse tree. + program: null, + // When `locations` is on, you can pass this to record the source + // file in every node's `loc` object. + sourceFile: null, + // This value, if given, is stored in every node, whether + // `locations` is on or off. + directSourceFile: null, + // When enabled, parenthesized expressions are represented by + // (non-standard) ParenthesizedExpression nodes + preserveParens: false + }; + + // Interpret and default an options object + + function getOptions(opts) { + var options = {}; + + for (var opt in defaultOptions) + { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } + + if (options.ecmaVersion >= 2015) + { options.ecmaVersion -= 2009; } + + if (options.allowReserved == null) + { options.allowReserved = options.ecmaVersion < 5; } + + if (isArray(options.onToken)) { + var tokens = options.onToken; + options.onToken = function (token) { return tokens.push(token); }; + } + if (isArray(options.onComment)) + { options.onComment = pushComment(options, options.onComment); } + + return options + } + + function pushComment(options, array) { + return function(block, text, start, end, startLoc, endLoc) { + var comment = { + type: block ? "Block" : "Line", + value: text, + start: start, + end: end + }; + if (options.locations) + { comment.loc = new SourceLocation(this, startLoc, endLoc); } + if (options.ranges) + { comment.range = [start, end]; } + array.push(comment); + } + } + + // Each scope gets a bitset that may contain these flags + var + SCOPE_TOP = 1, + SCOPE_FUNCTION = 2, + SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION, + SCOPE_ASYNC = 4, + SCOPE_GENERATOR = 8, + SCOPE_ARROW = 16, + SCOPE_SIMPLE_CATCH = 32, + SCOPE_SUPER = 64, + SCOPE_DIRECT_SUPER = 128; + + function functionFlags(async, generator) { + return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) + } + + // Used in checkLVal and declareName to determine the type of a binding + var + BIND_NONE = 0, // Not a binding + BIND_VAR = 1, // Var-style binding + BIND_LEXICAL = 2, // Let- or const-style binding + BIND_FUNCTION = 3, // Function declaration + BIND_SIMPLE_CATCH = 4, // Simple (identifier pattern) catch binding + BIND_OUTSIDE = 5; // Special case for function names as bound inside the function + + var Parser = function Parser(options, input, startPos) { + this.options = options = getOptions(options); + this.sourceFile = options.sourceFile; + this.keywords = wordsRegexp(keywords[options.ecmaVersion >= 6 ? 6 : options.sourceType === "module" ? "5module" : 5]); + var reserved = ""; + if (options.allowReserved !== true) { + for (var v = options.ecmaVersion;; v--) + { if (reserved = reservedWords[v]) { break } } + if (options.sourceType === "module") { reserved += " await"; } + } + this.reservedWords = wordsRegexp(reserved); + var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; + this.reservedWordsStrict = wordsRegexp(reservedStrict); + this.reservedWordsStrictBind = wordsRegexp(reservedStrict + " " + reservedWords.strictBind); + this.input = String(input); + + // Used to signal to callers of `readWord1` whether the word + // contained any escape sequences. This is needed because words with + // escape sequences must not be interpreted as keywords. + this.containsEsc = false; + + // Set up token state + + // The current position of the tokenizer in the input. + if (startPos) { + this.pos = startPos; + this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; + this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; } else { - return new Position(line, offset - cur) + this.pos = this.lineStart = 0; + this.curLine = 1; } - } -} -// A second optional argument can be given to further configure -// the parser process. These options are recognized: + // Properties of the current token: + // Its type + this.type = types.eof; + // For tokens that include more information than their type, the value + this.value = null; + // Its start and end offset + this.start = this.end = this.pos; + // And, if locations are used, the {line, column} object + // corresponding to those offsets + this.startLoc = this.endLoc = this.curPosition(); -var defaultOptions = { - // `ecmaVersion` indicates the ECMAScript version to parse. Must be - // either 3, 5, 6 (2015), 7 (2016), 8 (2017), 9 (2018), or 10 - // (2019). This influences support for strict mode, the set of - // reserved words, and support for new syntax features. The default - // is 9. - ecmaVersion: 9, - // `sourceType` indicates the mode the code should be parsed in. - // Can be either `"script"` or `"module"`. This influences global - // strict mode and parsing of `import` and `export` declarations. - sourceType: "script", - // `onInsertedSemicolon` can be a callback that will be called - // when a semicolon is automatically inserted. It will be passed - // th position of the comma as an offset, and if `locations` is - // enabled, it is given the location as a `{line, column}` object - // as second argument. - onInsertedSemicolon: null, - // `onTrailingComma` is similar to `onInsertedSemicolon`, but for - // trailing commas. - onTrailingComma: null, - // By default, reserved words are only enforced if ecmaVersion >= 5. - // Set `allowReserved` to a boolean value to explicitly turn this on - // an off. When this option has the value "never", reserved words - // and keywords can also not be used as property names. - allowReserved: null, - // When enabled, a return at the top level is not considered an - // error. - allowReturnOutsideFunction: false, - // When enabled, import/export statements are not constrained to - // appearing at the top of the program. - allowImportExportEverywhere: false, - // When enabled, await identifiers are allowed to appear at the top-level scope, - // but they are still not allowed in non-async functions. - allowAwaitOutsideFunction: false, - // When enabled, hashbang directive in the beginning of file - // is allowed and treated as a line comment. - allowHashBang: false, - // When `locations` is on, `loc` properties holding objects with - // `start` and `end` properties in `{line, column}` form (with - // line being 1-based and column 0-based) will be attached to the - // nodes. - locations: false, - // A function can be passed as `onToken` option, which will - // cause Acorn to call that function with object in the same - // format as tokens returned from `tokenizer().getToken()`. Note - // that you are not allowed to call the parser from the - // callback—that will corrupt its internal state. - onToken: null, - // A function can be passed as `onComment` option, which will - // cause Acorn to call that function with `(block, text, start, - // end)` parameters whenever a comment is skipped. `block` is a - // boolean indicating whether this is a block (`/* */`) comment, - // `text` is the content of the comment, and `start` and `end` are - // character offsets that denote the start and end of the comment. - // When the `locations` option is on, two more parameters are - // passed, the full `{line, column}` locations of the start and - // end of the comments. Note that you are not allowed to call the - // parser from the callback—that will corrupt its internal state. - onComment: null, - // Nodes have their start and end characters offsets recorded in - // `start` and `end` properties (directly on the node, rather than - // the `loc` object, which holds line/column data. To also add a - // [semi-standardized][range] `range` property holding a `[start, - // end]` array with the same numbers, set the `ranges` option to - // `true`. - // - // [range]: https://bugzilla.mozilla.org/show_bug.cgi?id=745678 - ranges: false, - // It is possible to parse multiple files into a single AST by - // passing the tree produced by parsing the first file as - // `program` option in subsequent parses. This will add the - // toplevel forms of the parsed file to the `Program` (top) node - // of an existing parse tree. - program: null, - // When `locations` is on, you can pass this to record the source - // file in every node's `loc` object. - sourceFile: null, - // This value, if given, is stored in every node, whether - // `locations` is on or off. - directSourceFile: null, - // When enabled, parenthesized expressions are represented by - // (non-standard) ParenthesizedExpression nodes - preserveParens: false -}; + // Position information for the previous token + this.lastTokEndLoc = this.lastTokStartLoc = null; + this.lastTokStart = this.lastTokEnd = this.pos; -// Interpret and default an options object + // The context stack is used to superficially track syntactic + // context to predict whether a regular expression is allowed in a + // given position. + this.context = this.initialContext(); + this.exprAllowed = true; -function getOptions(opts) { - var options = {}; + // Figure out if it's a module code. + this.inModule = options.sourceType === "module"; + this.strict = this.inModule || this.strictDirective(this.pos); - for (var opt in defaultOptions) - { options[opt] = opts && has(opts, opt) ? opts[opt] : defaultOptions[opt]; } + // Used to signify the start of a potential arrow function + this.potentialArrowAt = -1; - if (options.ecmaVersion >= 2015) - { options.ecmaVersion -= 2009; } + // Positions to delayed-check that yield/await does not exist in default parameters. + this.yieldPos = this.awaitPos = this.awaitIdentPos = 0; + // Labels in scope. + this.labels = []; + // Thus-far undefined exports. + this.undefinedExports = {}; - if (options.allowReserved == null) - { options.allowReserved = options.ecmaVersion < 5; } + // If enabled, skip leading hashbang line. + if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") + { this.skipLineComment(2); } - if (isArray(options.onToken)) { - var tokens = options.onToken; - options.onToken = function (token) { return tokens.push(token); }; - } - if (isArray(options.onComment)) - { options.onComment = pushComment(options, options.onComment); } + // Scope tracking for duplicate variable names (see scope.js) + this.scopeStack = []; + this.enterScope(SCOPE_TOP); - return options -} + // For RegExp validation + this.regexpState = null; + }; -function pushComment(options, array) { - return function(block, text, start, end, startLoc, endLoc) { - var comment = { - type: block ? "Block" : "Line", - value: text, - start: start, - end: end - }; - if (options.locations) - { comment.loc = new SourceLocation(this, startLoc, endLoc); } - if (options.ranges) - { comment.range = [start, end]; } - array.push(comment); - } -} + var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true },allowSuper: { configurable: true },allowDirectSuper: { configurable: true },treatFunctionsAsVar: { configurable: true } }; -// Each scope gets a bitset that may contain these flags -var SCOPE_TOP = 1; -var SCOPE_FUNCTION = 2; -var SCOPE_VAR = SCOPE_TOP | SCOPE_FUNCTION; -var SCOPE_ASYNC = 4; -var SCOPE_GENERATOR = 8; -var SCOPE_ARROW = 16; -var SCOPE_SIMPLE_CATCH = 32; + Parser.prototype.parse = function parse () { + var node = this.options.program || this.startNode(); + this.nextToken(); + return this.parseTopLevel(node) + }; -function functionFlags(async, generator) { - return SCOPE_FUNCTION | (async ? SCOPE_ASYNC : 0) | (generator ? SCOPE_GENERATOR : 0) -} + prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; + prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; + prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; + prototypeAccessors.allowSuper.get = function () { return (this.currentThisScope().flags & SCOPE_SUPER) > 0 }; + prototypeAccessors.allowDirectSuper.get = function () { return (this.currentThisScope().flags & SCOPE_DIRECT_SUPER) > 0 }; + prototypeAccessors.treatFunctionsAsVar.get = function () { return this.treatFunctionsAsVarInScope(this.currentScope()) }; -// Used in checkLVal and declareName to determine the type of a binding -var BIND_NONE = 0; -var BIND_VAR = 1; -var BIND_LEXICAL = 2; -var BIND_FUNCTION = 3; -var BIND_SIMPLE_CATCH = 4; -var BIND_OUTSIDE = 5; // Special case for function names as bound inside the function + // Switch to a getter for 7.0.0. + Parser.prototype.inNonArrowFunction = function inNonArrowFunction () { return (this.currentThisScope().flags & SCOPE_FUNCTION) > 0 }; -function keywordRegexp(words) { - return new RegExp("^(?:" + words.replace(/ /g, "|") + ")$") -} + Parser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; -var Parser = function Parser(options, input, startPos) { - this.options = options = getOptions(options); - this.sourceFile = options.sourceFile; - this.keywords = keywordRegexp(keywords[options.ecmaVersion >= 6 ? 6 : 5]); - var reserved = ""; - if (!options.allowReserved) { - for (var v = options.ecmaVersion;; v--) - { if (reserved = reservedWords[v]) { break } } - if (options.sourceType === "module") { reserved += " await"; } - } - this.reservedWords = keywordRegexp(reserved); - var reservedStrict = (reserved ? reserved + " " : "") + reservedWords.strict; - this.reservedWordsStrict = keywordRegexp(reservedStrict); - this.reservedWordsStrictBind = keywordRegexp(reservedStrict + " " + reservedWords.strictBind); - this.input = String(input); + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls + }; - // Used to signal to callers of `readWord1` whether the word - // contained any escape sequences. This is needed because words with - // escape sequences must not be interpreted as keywords. - this.containsEsc = false; + Parser.parse = function parse (input, options) { + return new this(options, input).parse() + }; - // Set up token state + Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { + var parser = new this(options, input, pos); + parser.nextToken(); + return parser.parseExpression() + }; - // The current position of the tokenizer in the input. - if (startPos) { - this.pos = startPos; - this.lineStart = this.input.lastIndexOf("\n", startPos - 1) + 1; - this.curLine = this.input.slice(0, this.lineStart).split(lineBreak).length; - } else { - this.pos = this.lineStart = 0; - this.curLine = 1; - } + Parser.tokenizer = function tokenizer (input, options) { + return new this(options, input) + }; - // Properties of the current token: - // Its type - this.type = types.eof; - // For tokens that include more information than their type, the value - this.value = null; - // Its start and end offset - this.start = this.end = this.pos; - // And, if locations are used, the {line, column} object - // corresponding to those offsets - this.startLoc = this.endLoc = this.curPosition(); + Object.defineProperties( Parser.prototype, prototypeAccessors ); - // Position information for the previous token - this.lastTokEndLoc = this.lastTokStartLoc = null; - this.lastTokStart = this.lastTokEnd = this.pos; + var pp = Parser.prototype; - // The context stack is used to superficially track syntactic - // context to predict whether a regular expression is allowed in a - // given position. - this.context = this.initialContext(); - this.exprAllowed = true; + // ## Parser utilities - // Figure out if it's a module code. - this.inModule = options.sourceType === "module"; - this.strict = this.inModule || this.strictDirective(this.pos); + var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)")/; + pp.strictDirective = function(start) { + for (;;) { + // Try to find string literal. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + var match = literal.exec(this.input.slice(start)); + if (!match) { return false } + if ((match[1] || match[2]) === "use strict") { return true } + start += match[0].length; - // Used to signify the start of a potential arrow function - this.potentialArrowAt = -1; - - // Positions to delayed-check that yield/await does not exist in default parameters. - this.yieldPos = this.awaitPos = 0; - // Labels in scope. - this.labels = []; - - // If enabled, skip leading hashbang line. - if (this.pos === 0 && options.allowHashBang && this.input.slice(0, 2) === "#!") - { this.skipLineComment(2); } - - // Scope tracking for duplicate variable names (see scope.js) - this.scopeStack = []; - this.enterScope(SCOPE_TOP); - - // For RegExp validation - this.regexpState = null; -}; - -var prototypeAccessors = { inFunction: { configurable: true },inGenerator: { configurable: true },inAsync: { configurable: true } }; - -Parser.prototype.parse = function parse () { - var node = this.options.program || this.startNode(); - this.nextToken(); - return this.parseTopLevel(node) -}; - -prototypeAccessors.inFunction.get = function () { return (this.currentVarScope().flags & SCOPE_FUNCTION) > 0 }; -prototypeAccessors.inGenerator.get = function () { return (this.currentVarScope().flags & SCOPE_GENERATOR) > 0 }; -prototypeAccessors.inAsync.get = function () { return (this.currentVarScope().flags & SCOPE_ASYNC) > 0 }; - -Parser.extend = function extend () { - var plugins = [], len = arguments.length; - while ( len-- ) plugins[ len ] = arguments[ len ]; - - var cls = this; - for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } - return cls -}; - -Parser.parse = function parse (input, options) { - return new this(options, input).parse() -}; - -Parser.parseExpressionAt = function parseExpressionAt (input, pos, options) { - var parser = new this(options, input, pos); - parser.nextToken(); - return parser.parseExpression() -}; - -Parser.tokenizer = function tokenizer (input, options) { - return new this(options, input) -}; - -Object.defineProperties( Parser.prototype, prototypeAccessors ); - -var pp = Parser.prototype; - -// ## Parser utilities - -var literal = /^(?:'((?:\\.|[^'])*?)'|"((?:\\.|[^"])*?)"|;)/; -pp.strictDirective = function(start) { - var this$1 = this; - - for (;;) { - skipWhiteSpace.lastIndex = start; - start += skipWhiteSpace.exec(this$1.input)[0].length; - var match = literal.exec(this$1.input.slice(start)); - if (!match) { return false } - if ((match[1] || match[2]) === "use strict") { return true } - start += match[0].length; - } -}; - -// Predicate that tests whether the next token is of the given -// type, and if yes, consumes it as a side effect. - -pp.eat = function(type) { - if (this.type === type) { - this.next(); - return true - } else { - return false - } -}; - -// Tests whether parsed token is a contextual keyword. - -pp.isContextual = function(name) { - return this.type === types.name && this.value === name && !this.containsEsc -}; - -// Consumes contextual keyword if possible. - -pp.eatContextual = function(name) { - if (!this.isContextual(name)) { return false } - this.next(); - return true -}; - -// Asserts that following token is given contextual keyword. - -pp.expectContextual = function(name) { - if (!this.eatContextual(name)) { this.unexpected(); } -}; - -// Test whether a semicolon can be inserted at the current position. - -pp.canInsertSemicolon = function() { - return this.type === types.eof || - this.type === types.braceR || - lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -pp.insertSemicolon = function() { - if (this.canInsertSemicolon()) { - if (this.options.onInsertedSemicolon) - { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } - return true - } -}; - -// Consume a semicolon, or, failing that, see if we are allowed to -// pretend that there is a semicolon at this position. - -pp.semicolon = function() { - if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } -}; - -pp.afterTrailingComma = function(tokType, notNext) { - if (this.type === tokType) { - if (this.options.onTrailingComma) - { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } - if (!notNext) - { this.next(); } - return true - } -}; - -// Expect a token of a given type. If found, consume it, otherwise, -// raise an unexpected token error. - -pp.expect = function(type) { - this.eat(type) || this.unexpected(); -}; - -// Raise an unexpected token error. - -pp.unexpected = function(pos) { - this.raise(pos != null ? pos : this.start, "Unexpected token"); -}; - -function DestructuringErrors() { - this.shorthandAssign = - this.trailingComma = - this.parenthesizedAssign = - this.parenthesizedBind = - this.doubleProto = - -1; -} - -pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { - if (!refDestructuringErrors) { return } - if (refDestructuringErrors.trailingComma > -1) - { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } - var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; - if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } -}; - -pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { - if (!refDestructuringErrors) { return false } - var shorthandAssign = refDestructuringErrors.shorthandAssign; - var doubleProto = refDestructuringErrors.doubleProto; - if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } - if (shorthandAssign >= 0) - { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } - if (doubleProto >= 0) - { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } -}; - -pp.checkYieldAwaitInDefaultParams = function() { - if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) - { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } - if (this.awaitPos) - { this.raise(this.awaitPos, "Await expression cannot be a default value"); } -}; - -pp.isSimpleAssignTarget = function(expr) { - if (expr.type === "ParenthesizedExpression") - { return this.isSimpleAssignTarget(expr.expression) } - return expr.type === "Identifier" || expr.type === "MemberExpression" -}; - -var pp$1 = Parser.prototype; - -// ### Statement parsing - -// Parse a program. Initializes the parser, reads any number of -// statements, and wraps them in a Program node. Optionally takes a -// `program` argument. If present, the statements will be appended -// to its body instead of creating a new node. - -pp$1.parseTopLevel = function(node) { - var this$1 = this; - - var exports = {}; - if (!node.body) { node.body = []; } - while (this.type !== types.eof) { - var stmt = this$1.parseStatement(null, true, exports); - node.body.push(stmt); - } - this.adaptDirectivePrologue(node.body); - this.next(); - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program") -}; - -var loopLabel = {kind: "loop"}; -var switchLabel = {kind: "switch"}; - -pp$1.isLet = function() { - if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); - if (nextCh === 91 || nextCh === 123) { return true } // '{' and '[' - if (isIdentifierStart(nextCh, true)) { - var pos = next + 1; - while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } - var ident = this.input.slice(next, pos); - if (!keywordRelationalOperator.test(ident)) { return true } - } - return false -}; - -// check 'async [no LineTerminator here] function' -// - 'async /*foo*/ function' is OK. -// - 'async /*\n*/ function' is invalid. -pp$1.isAsyncFunction = function() { - if (this.options.ecmaVersion < 8 || !this.isContextual("async")) - { return false } - - skipWhiteSpace.lastIndex = this.pos; - var skip = skipWhiteSpace.exec(this.input); - var next = this.pos + skip[0].length; - return !lineBreak.test(this.input.slice(this.pos, next)) && - this.input.slice(next, next + 8) === "function" && - (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) -}; - -// Parse a single statement. -// -// If expecting a statement and finding a slash operator, parse a -// regular expression literal. This is to handle cases like -// `if (foo) /blah/.exec(foo)`, where looking at the previous token -// does not help. - -pp$1.parseStatement = function(context, topLevel, exports) { - var starttype = this.type, node = this.startNode(), kind; - - if (this.isLet()) { - starttype = types._var; - kind = "let"; - } - - // Most types of statements are recognized by the keyword they - // start with. Many are trivial to parse, some require a bit of - // complexity. - - switch (starttype) { - case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) - case types._debugger: return this.parseDebuggerStatement(node) - case types._do: return this.parseDoStatement(node) - case types._for: return this.parseForStatement(node) - case types._function: - if ((context && (this.strict || context !== "if")) && this.options.ecmaVersion >= 6) { this.unexpected(); } - return this.parseFunctionStatement(node, false, !context) - case types._class: - if (context) { this.unexpected(); } - return this.parseClass(node, true) - case types._if: return this.parseIfStatement(node) - case types._return: return this.parseReturnStatement(node) - case types._switch: return this.parseSwitchStatement(node) - case types._throw: return this.parseThrowStatement(node) - case types._try: return this.parseTryStatement(node) - case types._const: case types._var: - kind = kind || this.value; - if (context && kind !== "var") { this.unexpected(); } - return this.parseVarStatement(node, kind) - case types._while: return this.parseWhileStatement(node) - case types._with: return this.parseWithStatement(node) - case types.braceL: return this.parseBlock(true, node) - case types.semi: return this.parseEmptyStatement(node) - case types._export: - case types._import: - if (!this.options.allowImportExportEverywhere) { - if (!topLevel) - { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } - if (!this.inModule) - { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } + // Skip semicolon, if any. + skipWhiteSpace.lastIndex = start; + start += skipWhiteSpace.exec(this.input)[0].length; + if (this.input[start] === ";") + { start++; } } - return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) + }; - // If the statement does not start with a statement keyword or a - // brace, it's an ExpressionStatement or LabeledStatement. We - // simply start parsing an expression, and afterwards, if the - // next token is a colon and the expression was a simple - // Identifier node, we switch to interpreting it as a label. - default: - if (this.isAsyncFunction()) { - if (context) { this.unexpected(); } + // Predicate that tests whether the next token is of the given + // type, and if yes, consumes it as a side effect. + + pp.eat = function(type) { + if (this.type === type) { this.next(); - return this.parseFunctionStatement(node, true, !context) + return true + } else { + return false } + }; - var maybeName = this.value, expr = this.parseExpression(); - if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) - { return this.parseLabeledStatement(node, maybeName, expr, context) } - else { return this.parseExpressionStatement(node, expr) } - } -}; + // Tests whether parsed token is a contextual keyword. -pp$1.parseBreakContinueStatement = function(node, keyword) { - var this$1 = this; + pp.isContextual = function(name) { + return this.type === types.name && this.value === name && !this.containsEsc + }; - var isBreak = keyword === "break"; - this.next(); - if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } - else if (this.type !== types.name) { this.unexpected(); } - else { - node.label = this.parseIdent(); - this.semicolon(); - } + // Consumes contextual keyword if possible. - // Verify that there is an actual destination to break or - // continue to. - var i = 0; - for (; i < this.labels.length; ++i) { - var lab = this$1.labels[i]; - if (node.label == null || lab.name === node.label.name) { - if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } - if (node.label && isBreak) { break } - } - } - if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") -}; - -pp$1.parseDebuggerStatement = function(node) { - this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement") -}; - -pp$1.parseDoStatement = function(node) { - this.next(); - this.labels.push(loopLabel); - node.body = this.parseStatement("do"); - this.labels.pop(); - this.expect(types._while); - node.test = this.parseParenExpression(); - if (this.options.ecmaVersion >= 6) - { this.eat(types.semi); } - else - { this.semicolon(); } - return this.finishNode(node, "DoWhileStatement") -}; - -// Disambiguating between a `for` and a `for`/`in` or `for`/`of` -// loop is non-trivial. Basically, we have to parse the init `var` -// statement or expression, disallowing the `in` operator (see -// the second parameter to `parseExpression`), and then check -// whether the next token is `in` or `of`. When there is no init -// part (semicolon immediately after the opening parenthesis), it -// is a regular `for` loop. - -pp$1.parseForStatement = function(node) { - this.next(); - var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1; - this.labels.push(loopLabel); - this.enterScope(0); - this.expect(types.parenL); - if (this.type === types.semi) { - if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, null) - } - var isLet = this.isLet(); - if (this.type === types._var || this.type === types._const || isLet) { - var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + pp.eatContextual = function(name) { + if (!this.isContextual(name)) { return false } this.next(); - this.parseVar(init$1, true, kind); - this.finishNode(init$1, "VariableDeclaration"); - if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1 && - !(kind !== "var" && init$1.declarations[0].init)) { + return true + }; + + // Asserts that following token is given contextual keyword. + + pp.expectContextual = function(name) { + if (!this.eatContextual(name)) { this.unexpected(); } + }; + + // Test whether a semicolon can be inserted at the current position. + + pp.canInsertSemicolon = function() { + return this.type === types.eof || + this.type === types.braceR || + lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + pp.insertSemicolon = function() { + if (this.canInsertSemicolon()) { + if (this.options.onInsertedSemicolon) + { this.options.onInsertedSemicolon(this.lastTokEnd, this.lastTokEndLoc); } + return true + } + }; + + // Consume a semicolon, or, failing that, see if we are allowed to + // pretend that there is a semicolon at this position. + + pp.semicolon = function() { + if (!this.eat(types.semi) && !this.insertSemicolon()) { this.unexpected(); } + }; + + pp.afterTrailingComma = function(tokType, notNext) { + if (this.type === tokType) { + if (this.options.onTrailingComma) + { this.options.onTrailingComma(this.lastTokStart, this.lastTokStartLoc); } + if (!notNext) + { this.next(); } + return true + } + }; + + // Expect a token of a given type. If found, consume it, otherwise, + // raise an unexpected token error. + + pp.expect = function(type) { + this.eat(type) || this.unexpected(); + }; + + // Raise an unexpected token error. + + pp.unexpected = function(pos) { + this.raise(pos != null ? pos : this.start, "Unexpected token"); + }; + + function DestructuringErrors() { + this.shorthandAssign = + this.trailingComma = + this.parenthesizedAssign = + this.parenthesizedBind = + this.doubleProto = + -1; + } + + pp.checkPatternErrors = function(refDestructuringErrors, isAssign) { + if (!refDestructuringErrors) { return } + if (refDestructuringErrors.trailingComma > -1) + { this.raiseRecoverable(refDestructuringErrors.trailingComma, "Comma is not permitted after the rest element"); } + var parens = isAssign ? refDestructuringErrors.parenthesizedAssign : refDestructuringErrors.parenthesizedBind; + if (parens > -1) { this.raiseRecoverable(parens, "Parenthesized pattern"); } + }; + + pp.checkExpressionErrors = function(refDestructuringErrors, andThrow) { + if (!refDestructuringErrors) { return false } + var shorthandAssign = refDestructuringErrors.shorthandAssign; + var doubleProto = refDestructuringErrors.doubleProto; + if (!andThrow) { return shorthandAssign >= 0 || doubleProto >= 0 } + if (shorthandAssign >= 0) + { this.raise(shorthandAssign, "Shorthand property assignments are valid only in destructuring patterns"); } + if (doubleProto >= 0) + { this.raiseRecoverable(doubleProto, "Redefinition of __proto__ property"); } + }; + + pp.checkYieldAwaitInDefaultParams = function() { + if (this.yieldPos && (!this.awaitPos || this.yieldPos < this.awaitPos)) + { this.raise(this.yieldPos, "Yield expression cannot be a default value"); } + if (this.awaitPos) + { this.raise(this.awaitPos, "Await expression cannot be a default value"); } + }; + + pp.isSimpleAssignTarget = function(expr) { + if (expr.type === "ParenthesizedExpression") + { return this.isSimpleAssignTarget(expr.expression) } + return expr.type === "Identifier" || expr.type === "MemberExpression" + }; + + var pp$1 = Parser.prototype; + + // ### Statement parsing + + // Parse a program. Initializes the parser, reads any number of + // statements, and wraps them in a Program node. Optionally takes a + // `program` argument. If present, the statements will be appended + // to its body instead of creating a new node. + + pp$1.parseTopLevel = function(node) { + var exports = {}; + if (!node.body) { node.body = []; } + while (this.type !== types.eof) { + var stmt = this.parseStatement(null, true, exports); + node.body.push(stmt); + } + if (this.inModule) + { for (var i = 0, list = Object.keys(this.undefinedExports); i < list.length; i += 1) + { + var name = list[i]; + + this.raiseRecoverable(this.undefinedExports[name].start, ("Export '" + name + "' is not defined")); + } } + this.adaptDirectivePrologue(node.body); + this.next(); + node.sourceType = this.options.sourceType; + return this.finishNode(node, "Program") + }; + + var loopLabel = {kind: "loop"}, switchLabel = {kind: "switch"}; + + pp$1.isLet = function(context) { + if (this.options.ecmaVersion < 6 || !this.isContextual("let")) { return false } + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + // For ambiguous cases, determine if a LexicalDeclaration (or only a + // Statement) is allowed here. If context is not empty then only a Statement + // is allowed. However, `let [` is an explicit negative lookahead for + // ExpressionStatement, so special-case it first. + if (nextCh === 91) { return true } // '[' + if (context) { return false } + + if (nextCh === 123) { return true } // '{' + if (isIdentifierStart(nextCh, true)) { + var pos = next + 1; + while (isIdentifierChar(this.input.charCodeAt(pos), true)) { ++pos; } + var ident = this.input.slice(next, pos); + if (!keywordRelationalOperator.test(ident)) { return true } + } + return false + }; + + // check 'async [no LineTerminator here] function' + // - 'async /*foo*/ function' is OK. + // - 'async /*\n*/ function' is invalid. + pp$1.isAsyncFunction = function() { + if (this.options.ecmaVersion < 8 || !this.isContextual("async")) + { return false } + + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length; + return !lineBreak.test(this.input.slice(this.pos, next)) && + this.input.slice(next, next + 8) === "function" && + (next + 8 === this.input.length || !isIdentifierChar(this.input.charAt(next + 8))) + }; + + // Parse a single statement. + // + // If expecting a statement and finding a slash operator, parse a + // regular expression literal. This is to handle cases like + // `if (foo) /blah/.exec(foo)`, where looking at the previous token + // does not help. + + pp$1.parseStatement = function(context, topLevel, exports) { + var starttype = this.type, node = this.startNode(), kind; + + if (this.isLet(context)) { + starttype = types._var; + kind = "let"; + } + + // Most types of statements are recognized by the keyword they + // start with. Many are trivial to parse, some require a bit of + // complexity. + + switch (starttype) { + case types._break: case types._continue: return this.parseBreakContinueStatement(node, starttype.keyword) + case types._debugger: return this.parseDebuggerStatement(node) + case types._do: return this.parseDoStatement(node) + case types._for: return this.parseForStatement(node) + case types._function: + // Function as sole body of either an if statement or a labeled statement + // works, but not when it is part of a labeled statement that is the sole + // body of an if statement. + if ((context && (this.strict || context !== "if" && context !== "label")) && this.options.ecmaVersion >= 6) { this.unexpected(); } + return this.parseFunctionStatement(node, false, !context) + case types._class: + if (context) { this.unexpected(); } + return this.parseClass(node, true) + case types._if: return this.parseIfStatement(node) + case types._return: return this.parseReturnStatement(node) + case types._switch: return this.parseSwitchStatement(node) + case types._throw: return this.parseThrowStatement(node) + case types._try: return this.parseTryStatement(node) + case types._const: case types._var: + kind = kind || this.value; + if (context && kind !== "var") { this.unexpected(); } + return this.parseVarStatement(node, kind) + case types._while: return this.parseWhileStatement(node) + case types._with: return this.parseWithStatement(node) + case types.braceL: return this.parseBlock(true, node) + case types.semi: return this.parseEmptyStatement(node) + case types._export: + case types._import: + if (this.options.ecmaVersion > 10 && starttype === types._import) { + skipWhiteSpace.lastIndex = this.pos; + var skip = skipWhiteSpace.exec(this.input); + var next = this.pos + skip[0].length, nextCh = this.input.charCodeAt(next); + if (nextCh === 40) // '(' + { return this.parseExpressionStatement(node, this.parseExpression()) } + } + + if (!this.options.allowImportExportEverywhere) { + if (!topLevel) + { this.raise(this.start, "'import' and 'export' may only appear at the top level"); } + if (!this.inModule) + { this.raise(this.start, "'import' and 'export' may appear only with 'sourceType: module'"); } + } + return starttype === types._import ? this.parseImport(node) : this.parseExport(node, exports) + + // If the statement does not start with a statement keyword or a + // brace, it's an ExpressionStatement or LabeledStatement. We + // simply start parsing an expression, and afterwards, if the + // next token is a colon and the expression was a simple + // Identifier node, we switch to interpreting it as a label. + default: + if (this.isAsyncFunction()) { + if (context) { this.unexpected(); } + this.next(); + return this.parseFunctionStatement(node, true, !context) + } + + var maybeName = this.value, expr = this.parseExpression(); + if (starttype === types.name && expr.type === "Identifier" && this.eat(types.colon)) + { return this.parseLabeledStatement(node, maybeName, expr, context) } + else { return this.parseExpressionStatement(node, expr) } + } + }; + + pp$1.parseBreakContinueStatement = function(node, keyword) { + var isBreak = keyword === "break"; + this.next(); + if (this.eat(types.semi) || this.insertSemicolon()) { node.label = null; } + else if (this.type !== types.name) { this.unexpected(); } + else { + node.label = this.parseIdent(); + this.semicolon(); + } + + // Verify that there is an actual destination to break or + // continue to. + var i = 0; + for (; i < this.labels.length; ++i) { + var lab = this.labels[i]; + if (node.label == null || lab.name === node.label.name) { + if (lab.kind != null && (isBreak || lab.kind === "loop")) { break } + if (node.label && isBreak) { break } + } + } + if (i === this.labels.length) { this.raise(node.start, "Unsyntactic " + keyword); } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + }; + + pp$1.parseDebuggerStatement = function(node) { + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + }; + + pp$1.parseDoStatement = function(node) { + this.next(); + this.labels.push(loopLabel); + node.body = this.parseStatement("do"); + this.labels.pop(); + this.expect(types._while); + node.test = this.parseParenExpression(); + if (this.options.ecmaVersion >= 6) + { this.eat(types.semi); } + else + { this.semicolon(); } + return this.finishNode(node, "DoWhileStatement") + }; + + // Disambiguating between a `for` and a `for`/`in` or `for`/`of` + // loop is non-trivial. Basically, we have to parse the init `var` + // statement or expression, disallowing the `in` operator (see + // the second parameter to `parseExpression`), and then check + // whether the next token is `in` or `of`. When there is no init + // part (semicolon immediately after the opening parenthesis), it + // is a regular `for` loop. + + pp$1.parseForStatement = function(node) { + this.next(); + var awaitAt = (this.options.ecmaVersion >= 9 && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) && this.eatContextual("await")) ? this.lastTokStart : -1; + this.labels.push(loopLabel); + this.enterScope(0); + this.expect(types.parenL); + if (this.type === types.semi) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, null) + } + var isLet = this.isLet(); + if (this.type === types._var || this.type === types._const || isLet) { + var init$1 = this.startNode(), kind = isLet ? "let" : this.value; + this.next(); + this.parseVar(init$1, true, kind); + this.finishNode(init$1, "VariableDeclaration"); + if ((this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) && init$1.declarations.length === 1) { + if (this.options.ecmaVersion >= 9) { + if (this.type === types._in) { + if (awaitAt > -1) { this.unexpected(awaitAt); } + } else { node.await = awaitAt > -1; } + } + return this.parseForIn(node, init$1) + } + if (awaitAt > -1) { this.unexpected(awaitAt); } + return this.parseFor(node, init$1) + } + var refDestructuringErrors = new DestructuringErrors; + var init = this.parseExpression(true, refDestructuringErrors); + if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { if (this.options.ecmaVersion >= 9) { if (this.type === types._in) { if (awaitAt > -1) { this.unexpected(awaitAt); } } else { node.await = awaitAt > -1; } } - return this.parseForIn(node, init$1) + this.toAssignable(init, false, refDestructuringErrors); + this.checkLVal(init); + return this.parseForIn(node, init) + } else { + this.checkExpressionErrors(refDestructuringErrors, true); } if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, init$1) - } - var refDestructuringErrors = new DestructuringErrors; - var init = this.parseExpression(true, refDestructuringErrors); - if (this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of"))) { - if (this.options.ecmaVersion >= 9) { - if (this.type === types._in) { - if (awaitAt > -1) { this.unexpected(awaitAt); } - } else { node.await = awaitAt > -1; } - } - this.toAssignable(init, false, refDestructuringErrors); - this.checkLVal(init); - return this.parseForIn(node, init) - } else { - this.checkExpressionErrors(refDestructuringErrors, true); - } - if (awaitAt > -1) { this.unexpected(awaitAt); } - return this.parseFor(node, init) -}; - -pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) { - this.next(); - return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) -}; - -pp$1.parseIfStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - // allow function declarations in branches, but only in non-strict mode - node.consequent = this.parseStatement("if"); - node.alternate = this.eat(types._else) ? this.parseStatement("if") : null; - return this.finishNode(node, "IfStatement") -}; - -pp$1.parseReturnStatement = function(node) { - if (!this.inFunction && !this.options.allowReturnOutsideFunction) - { this.raise(this.start, "'return' outside of function"); } - this.next(); - - // In `return` (and `break`/`continue`), the keywords with - // optional arguments, we eagerly look for a semicolon or the - // possibility to insert one. - - if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } - else { node.argument = this.parseExpression(); this.semicolon(); } - return this.finishNode(node, "ReturnStatement") -}; - -pp$1.parseSwitchStatement = function(node) { - var this$1 = this; - - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; - this.expect(types.braceL); - this.labels.push(switchLabel); - this.enterScope(0); - - // Statements under must be grouped (by label) in SwitchCase - // nodes. `cur` is used to keep the node that we are currently - // adding statements to. - - var cur; - for (var sawDefault = false; this.type !== types.braceR;) { - if (this$1.type === types._case || this$1.type === types._default) { - var isCase = this$1.type === types._case; - if (cur) { this$1.finishNode(cur, "SwitchCase"); } - node.cases.push(cur = this$1.startNode()); - cur.consequent = []; - this$1.next(); - if (isCase) { - cur.test = this$1.parseExpression(); - } else { - if (sawDefault) { this$1.raiseRecoverable(this$1.lastTokStart, "Multiple default clauses"); } - sawDefault = true; - cur.test = null; - } - this$1.expect(types.colon); - } else { - if (!cur) { this$1.unexpected(); } - cur.consequent.push(this$1.parseStatement(null)); - } - } - this.exitScope(); - if (cur) { this.finishNode(cur, "SwitchCase"); } - this.next(); // Closing brace - this.labels.pop(); - return this.finishNode(node, "SwitchStatement") -}; - -pp$1.parseThrowStatement = function(node) { - this.next(); - if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) - { this.raise(this.lastTokEnd, "Illegal newline after throw"); } - node.argument = this.parseExpression(); - this.semicolon(); - return this.finishNode(node, "ThrowStatement") -}; - -// Reused empty array added for node fields that are always empty. - -var empty = []; - -pp$1.parseTryStatement = function(node) { - this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.type === types._catch) { - var clause = this.startNode(); - this.next(); - if (this.eat(types.parenL)) { - clause.param = this.parseBindingAtom(); - var simple = clause.param.type === "Identifier"; - this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); - this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); - this.expect(types.parenR); - } else { - if (this.options.ecmaVersion < 10) { this.unexpected(); } - clause.param = null; - this.enterScope(0); - } - clause.body = this.parseBlock(false); - this.exitScope(); - node.handler = this.finishNode(clause, "CatchClause"); - } - node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) - { this.raise(node.start, "Missing catch or finally clause"); } - return this.finishNode(node, "TryStatement") -}; - -pp$1.parseVarStatement = function(node, kind) { - this.next(); - this.parseVar(node, false, kind); - this.semicolon(); - return this.finishNode(node, "VariableDeclaration") -}; - -pp$1.parseWhileStatement = function(node) { - this.next(); - node.test = this.parseParenExpression(); - this.labels.push(loopLabel); - node.body = this.parseStatement("while"); - this.labels.pop(); - return this.finishNode(node, "WhileStatement") -}; - -pp$1.parseWithStatement = function(node) { - if (this.strict) { this.raise(this.start, "'with' in strict mode"); } - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement("with"); - return this.finishNode(node, "WithStatement") -}; - -pp$1.parseEmptyStatement = function(node) { - this.next(); - return this.finishNode(node, "EmptyStatement") -}; - -pp$1.parseLabeledStatement = function(node, maybeName, expr, context) { - var this$1 = this; - - for (var i$1 = 0, list = this$1.labels; i$1 < list.length; i$1 += 1) - { - var label = list[i$1]; - - if (label.name === maybeName) - { this$1.raise(expr.start, "Label '" + maybeName + "' is already declared"); - } } - var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; - for (var i = this.labels.length - 1; i >= 0; i--) { - var label$1 = this$1.labels[i]; - if (label$1.statementStart === node.start) { - // Update information about previous labels on this node - label$1.statementStart = this$1.start; - label$1.kind = kind; - } else { break } - } - this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); - node.body = this.parseStatement(context); - if (node.body.type === "ClassDeclaration" || - node.body.type === "VariableDeclaration" && node.body.kind !== "var" || - node.body.type === "FunctionDeclaration" && (this.strict || node.body.generator || node.body.async)) - { this.raiseRecoverable(node.body.start, "Invalid labeled declaration"); } - this.labels.pop(); - node.label = expr; - return this.finishNode(node, "LabeledStatement") -}; - -pp$1.parseExpressionStatement = function(node, expr) { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement") -}; - -// Parse a semicolon-enclosed block of statements, handling `"use -// strict"` declarations when `allowStrict` is true (used for -// function bodies). - -pp$1.parseBlock = function(createNewLexicalScope, node) { - var this$1 = this; - if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; - if ( node === void 0 ) node = this.startNode(); - - node.body = []; - this.expect(types.braceL); - if (createNewLexicalScope) { this.enterScope(0); } - while (!this.eat(types.braceR)) { - var stmt = this$1.parseStatement(null); - node.body.push(stmt); - } - if (createNewLexicalScope) { this.exitScope(); } - return this.finishNode(node, "BlockStatement") -}; - -// Parse a regular `for` loop. The disambiguation code in -// `parseStatement` will already have parsed the init statement or -// expression. - -pp$1.parseFor = function(node, init) { - node.init = init; - this.expect(types.semi); - node.test = this.type === types.semi ? null : this.parseExpression(); - this.expect(types.semi); - node.update = this.type === types.parenR ? null : this.parseExpression(); - this.expect(types.parenR); - this.exitScope(); - node.body = this.parseStatement("for"); - this.labels.pop(); - return this.finishNode(node, "ForStatement") -}; - -// Parse a `for`/`in` and `for`/`of` loop, which are almost -// same from parser's perspective. - -pp$1.parseForIn = function(node, init) { - var type = this.type === types._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - if (type === "ForInStatement") { - if (init.type === "AssignmentPattern" || - (init.type === "VariableDeclaration" && init.declarations[0].init != null && - (this.strict || init.declarations[0].id.type !== "Identifier"))) - { this.raise(init.start, "Invalid assignment in for-in loop head"); } - } - node.left = init; - node.right = type === "ForInStatement" ? this.parseExpression() : this.parseMaybeAssign(); - this.expect(types.parenR); - this.exitScope(); - node.body = this.parseStatement("for"); - this.labels.pop(); - return this.finishNode(node, type) -}; - -// Parse a list of variable declarations. - -pp$1.parseVar = function(node, isFor, kind) { - var this$1 = this; - - node.declarations = []; - node.kind = kind; - for (;;) { - var decl = this$1.startNode(); - this$1.parseVarId(decl, kind); - if (this$1.eat(types.eq)) { - decl.init = this$1.parseMaybeAssign(isFor); - } else if (kind === "const" && !(this$1.type === types._in || (this$1.options.ecmaVersion >= 6 && this$1.isContextual("of")))) { - this$1.unexpected(); - } else if (decl.id.type !== "Identifier" && !(isFor && (this$1.type === types._in || this$1.isContextual("of")))) { - this$1.raise(this$1.lastTokEnd, "Complex binding patterns require an initialization value"); - } else { - decl.init = null; - } - node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); - if (!this$1.eat(types.comma)) { break } - } - return node -}; - -pp$1.parseVarId = function(decl, kind) { - decl.id = this.parseBindingAtom(kind); - this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); -}; - -var FUNC_STATEMENT = 1; -var FUNC_HANGING_STATEMENT = 2; -var FUNC_NULLABLE_ID = 4; - -// Parse a function declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) { - this.initFunction(node); - if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) - { node.generator = this.eat(types.star); } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - if (statement & FUNC_STATEMENT) { - node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent(); - if (node.id && !(statement & FUNC_HANGING_STATEMENT)) - { this.checkLVal(node.id, this.inModule && !this.inFunction ? BIND_LEXICAL : BIND_FUNCTION); } - } - - var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos; - this.yieldPos = 0; - this.awaitPos = 0; - this.enterScope(functionFlags(node.async, node.generator)); - - if (!(statement & FUNC_STATEMENT)) - { node.id = this.type === types.name ? this.parseIdent() : null; } - - this.parseFunctionParams(node); - this.parseFunctionBody(node, allowExpressionBody); - - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") -}; - -pp$1.parseFunctionParams = function(node) { - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); -}; - -// Parse a class declaration or literal (depending on the -// `isStatement` parameter). - -pp$1.parseClass = function(node, isStatement) { - var this$1 = this; - - this.next(); - - this.parseClassId(node, isStatement); - this.parseClassSuper(node); - var classBody = this.startNode(); - var hadConstructor = false; - classBody.body = []; - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - var element = this$1.parseClassElement(); - if (element) { - classBody.body.push(element); - if (element.type === "MethodDefinition" && element.kind === "constructor") { - if (hadConstructor) { this$1.raise(element.start, "Duplicate constructor in the same class"); } - hadConstructor = true; - } - } - } - node.body = this.finishNode(classBody, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") -}; - -pp$1.parseClassElement = function() { - var this$1 = this; - - if (this.eat(types.semi)) { return null } - - var method = this.startNode(); - var tryContextual = function (k, noLineBreak) { - if ( noLineBreak === void 0 ) noLineBreak = false; - - var start = this$1.start, startLoc = this$1.startLoc; - if (!this$1.eatContextual(k)) { return false } - if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } - if (method.key) { this$1.unexpected(); } - method.computed = false; - method.key = this$1.startNodeAt(start, startLoc); - method.key.name = k; - this$1.finishNode(method.key, "Identifier"); - return false + return this.parseFor(node, init) }; - method.kind = "method"; - method.static = tryContextual("static"); - var isGenerator = this.eat(types.star); - var isAsync = false; - if (!isGenerator) { - if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { - isAsync = true; - isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); - } else if (tryContextual("get")) { - method.kind = "get"; - } else if (tryContextual("set")) { - method.kind = "set"; + pp$1.parseFunctionStatement = function(node, isAsync, declarationPosition) { + this.next(); + return this.parseFunction(node, FUNC_STATEMENT | (declarationPosition ? 0 : FUNC_HANGING_STATEMENT), false, isAsync) + }; + + pp$1.parseIfStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + // allow function declarations in branches, but only in non-strict mode + node.consequent = this.parseStatement("if"); + node.alternate = this.eat(types._else) ? this.parseStatement("if") : null; + return this.finishNode(node, "IfStatement") + }; + + pp$1.parseReturnStatement = function(node) { + if (!this.inFunction && !this.options.allowReturnOutsideFunction) + { this.raise(this.start, "'return' outside of function"); } + this.next(); + + // In `return` (and `break`/`continue`), the keywords with + // optional arguments, we eagerly look for a semicolon or the + // possibility to insert one. + + if (this.eat(types.semi) || this.insertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + }; + + pp$1.parseSwitchStatement = function(node) { + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.expect(types.braceL); + this.labels.push(switchLabel); + this.enterScope(0); + + // Statements under must be grouped (by label) in SwitchCase + // nodes. `cur` is used to keep the node that we are currently + // adding statements to. + + var cur; + for (var sawDefault = false; this.type !== types.braceR;) { + if (this.type === types._case || this.type === types._default) { + var isCase = this.type === types._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { + cur.test = this.parseExpression(); + } else { + if (sawDefault) { this.raiseRecoverable(this.lastTokStart, "Multiple default clauses"); } + sawDefault = true; + cur.test = null; + } + this.expect(types.colon); + } else { + if (!cur) { this.unexpected(); } + cur.consequent.push(this.parseStatement(null)); + } } - } - if (!method.key) { this.parsePropertyName(method); } - var key = method.key; - if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || - key.type === "Literal" && key.value === "constructor")) { - if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } - if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } - if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } - method.kind = "constructor"; - } else if (method.static && key.type === "Identifier" && key.name === "prototype") { - this.raise(key.start, "Classes may not have a static property named prototype"); - } - this.parseClassMethod(method, isGenerator, isAsync); - if (method.kind === "get" && method.value.params.length !== 0) - { this.raiseRecoverable(method.value.start, "getter should have no params"); } - if (method.kind === "set" && method.value.params.length !== 1) - { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } - if (method.kind === "set" && method.value.params[0].type === "RestElement") - { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } - return method -}; + this.exitScope(); + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.next(); // Closing brace + this.labels.pop(); + return this.finishNode(node, "SwitchStatement") + }; -pp$1.parseClassMethod = function(method, isGenerator, isAsync) { - method.value = this.parseMethod(isGenerator, isAsync); - return this.finishNode(method, "MethodDefinition") -}; - -pp$1.parseClassId = function(node, isStatement) { - node.id = this.type === types.name ? this.parseIdent() : isStatement === true ? this.unexpected() : null; -}; - -pp$1.parseClassSuper = function(node) { - node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; -}; - -// Parses module export declaration. - -pp$1.parseExport = function(node, exports) { - var this$1 = this; - - this.next(); - // export * from '...' - if (this.eat(types.star)) { - this.expectContextual("from"); - if (this.type !== types.string) { this.unexpected(); } - node.source = this.parseExprAtom(); + pp$1.parseThrowStatement = function(node) { + this.next(); + if (lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) + { this.raise(this.lastTokEnd, "Illegal newline after throw"); } + node.argument = this.parseExpression(); this.semicolon(); - return this.finishNode(node, "ExportAllDeclaration") - } - if (this.eat(types._default)) { // export default ... - this.checkExport(exports, "default", this.lastTokStart); - var isAsync; - if (this.type === types._function || (isAsync = this.isAsyncFunction())) { - var fNode = this.startNode(); + return this.finishNode(node, "ThrowStatement") + }; + + // Reused empty array added for node fields that are always empty. + + var empty = []; + + pp$1.parseTryStatement = function(node) { + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.type === types._catch) { + var clause = this.startNode(); this.next(); - if (isAsync) { this.next(); } - node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync, true); - } else if (this.type === types._class) { - var cNode = this.startNode(); - node.declaration = this.parseClass(cNode, "nullableID"); - } else { - node.declaration = this.parseMaybeAssign(); - this.semicolon(); + if (this.eat(types.parenL)) { + clause.param = this.parseBindingAtom(); + var simple = clause.param.type === "Identifier"; + this.enterScope(simple ? SCOPE_SIMPLE_CATCH : 0); + this.checkLVal(clause.param, simple ? BIND_SIMPLE_CATCH : BIND_LEXICAL); + this.expect(types.parenR); + } else { + if (this.options.ecmaVersion < 10) { this.unexpected(); } + clause.param = null; + this.enterScope(0); + } + clause.body = this.parseBlock(false); + this.exitScope(); + node.handler = this.finishNode(clause, "CatchClause"); } - return this.finishNode(node, "ExportDefaultDeclaration") - } - // export var|const|let|function|class ... - if (this.shouldParseExportStatement()) { - node.declaration = this.parseStatement(null); - if (node.declaration.type === "VariableDeclaration") - { this.checkVariableExport(exports, node.declaration.declarations); } - else - { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } - node.specifiers = []; - node.source = null; - } else { // export { x, y as z } [from '...'] - node.declaration = null; - node.specifiers = this.parseExportSpecifiers(exports); - if (this.eatContextual("from")) { + node.finalizer = this.eat(types._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) + { this.raise(node.start, "Missing catch or finally clause"); } + return this.finishNode(node, "TryStatement") + }; + + pp$1.parseVarStatement = function(node, kind) { + this.next(); + this.parseVar(node, false, kind); + this.semicolon(); + return this.finishNode(node, "VariableDeclaration") + }; + + pp$1.parseWhileStatement = function(node) { + this.next(); + node.test = this.parseParenExpression(); + this.labels.push(loopLabel); + node.body = this.parseStatement("while"); + this.labels.pop(); + return this.finishNode(node, "WhileStatement") + }; + + pp$1.parseWithStatement = function(node) { + if (this.strict) { this.raise(this.start, "'with' in strict mode"); } + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement("with"); + return this.finishNode(node, "WithStatement") + }; + + pp$1.parseEmptyStatement = function(node) { + this.next(); + return this.finishNode(node, "EmptyStatement") + }; + + pp$1.parseLabeledStatement = function(node, maybeName, expr, context) { + for (var i$1 = 0, list = this.labels; i$1 < list.length; i$1 += 1) + { + var label = list[i$1]; + + if (label.name === maybeName) + { this.raise(expr.start, "Label '" + maybeName + "' is already declared"); + } } + var kind = this.type.isLoop ? "loop" : this.type === types._switch ? "switch" : null; + for (var i = this.labels.length - 1; i >= 0; i--) { + var label$1 = this.labels[i]; + if (label$1.statementStart === node.start) { + // Update information about previous labels on this node + label$1.statementStart = this.start; + label$1.kind = kind; + } else { break } + } + this.labels.push({name: maybeName, kind: kind, statementStart: this.start}); + node.body = this.parseStatement(context ? context.indexOf("label") === -1 ? context + "label" : context : "label"); + this.labels.pop(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + }; + + pp$1.parseExpressionStatement = function(node, expr) { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + }; + + // Parse a semicolon-enclosed block of statements, handling `"use + // strict"` declarations when `allowStrict` is true (used for + // function bodies). + + pp$1.parseBlock = function(createNewLexicalScope, node) { + if ( createNewLexicalScope === void 0 ) createNewLexicalScope = true; + if ( node === void 0 ) node = this.startNode(); + + node.body = []; + this.expect(types.braceL); + if (createNewLexicalScope) { this.enterScope(0); } + while (!this.eat(types.braceR)) { + var stmt = this.parseStatement(null); + node.body.push(stmt); + } + if (createNewLexicalScope) { this.exitScope(); } + return this.finishNode(node, "BlockStatement") + }; + + // Parse a regular `for` loop. The disambiguation code in + // `parseStatement` will already have parsed the init statement or + // expression. + + pp$1.parseFor = function(node, init) { + node.init = init; + this.expect(types.semi); + node.test = this.type === types.semi ? null : this.parseExpression(); + this.expect(types.semi); + node.update = this.type === types.parenR ? null : this.parseExpression(); + this.expect(types.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, "ForStatement") + }; + + // Parse a `for`/`in` and `for`/`of` loop, which are almost + // same from parser's perspective. + + pp$1.parseForIn = function(node, init) { + var isForIn = this.type === types._in; + this.next(); + + if ( + init.type === "VariableDeclaration" && + init.declarations[0].init != null && + ( + !isForIn || + this.options.ecmaVersion < 8 || + this.strict || + init.kind !== "var" || + init.declarations[0].id.type !== "Identifier" + ) + ) { + this.raise( + init.start, + ((isForIn ? "for-in" : "for-of") + " loop variable declaration may not have an initializer") + ); + } else if (init.type === "AssignmentPattern") { + this.raise(init.start, "Invalid left-hand side in for-loop"); + } + node.left = init; + node.right = isForIn ? this.parseExpression() : this.parseMaybeAssign(); + this.expect(types.parenR); + node.body = this.parseStatement("for"); + this.exitScope(); + this.labels.pop(); + return this.finishNode(node, isForIn ? "ForInStatement" : "ForOfStatement") + }; + + // Parse a list of variable declarations. + + pp$1.parseVar = function(node, isFor, kind) { + node.declarations = []; + node.kind = kind; + for (;;) { + var decl = this.startNode(); + this.parseVarId(decl, kind); + if (this.eat(types.eq)) { + decl.init = this.parseMaybeAssign(isFor); + } else if (kind === "const" && !(this.type === types._in || (this.options.ecmaVersion >= 6 && this.isContextual("of")))) { + this.unexpected(); + } else if (decl.id.type !== "Identifier" && !(isFor && (this.type === types._in || this.isContextual("of")))) { + this.raise(this.lastTokEnd, "Complex binding patterns require an initialization value"); + } else { + decl.init = null; + } + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + if (!this.eat(types.comma)) { break } + } + return node + }; + + pp$1.parseVarId = function(decl, kind) { + decl.id = this.parseBindingAtom(); + this.checkLVal(decl.id, kind === "var" ? BIND_VAR : BIND_LEXICAL, false); + }; + + var FUNC_STATEMENT = 1, FUNC_HANGING_STATEMENT = 2, FUNC_NULLABLE_ID = 4; + + // Parse a function declaration or literal (depending on the + // `statement & FUNC_STATEMENT`). + + // Remove `allowExpressionBody` for 7.0.0, as it is only called with false + pp$1.parseFunction = function(node, statement, allowExpressionBody, isAsync) { + this.initFunction(node); + if (this.options.ecmaVersion >= 9 || this.options.ecmaVersion >= 6 && !isAsync) { + if (this.type === types.star && (statement & FUNC_HANGING_STATEMENT)) + { this.unexpected(); } + node.generator = this.eat(types.star); + } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + + if (statement & FUNC_STATEMENT) { + node.id = (statement & FUNC_NULLABLE_ID) && this.type !== types.name ? null : this.parseIdent(); + if (node.id && !(statement & FUNC_HANGING_STATEMENT)) + // If it is a regular function declaration in sloppy mode, then it is + // subject to Annex B semantics (BIND_FUNCTION). Otherwise, the binding + // mode depends on properties of the current scope (see + // treatFunctionsAsVar). + { this.checkLVal(node.id, (this.strict || node.generator || node.async) ? this.treatFunctionsAsVar ? BIND_VAR : BIND_LEXICAL : BIND_FUNCTION); } + } + + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + this.enterScope(functionFlags(node.async, node.generator)); + + if (!(statement & FUNC_STATEMENT)) + { node.id = this.type === types.name ? this.parseIdent() : null; } + + this.parseFunctionParams(node); + this.parseFunctionBody(node, allowExpressionBody, false); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, (statement & FUNC_STATEMENT) ? "FunctionDeclaration" : "FunctionExpression") + }; + + pp$1.parseFunctionParams = function(node) { + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + }; + + // Parse a class declaration or literal (depending on the + // `isStatement` parameter). + + pp$1.parseClass = function(node, isStatement) { + this.next(); + + // ecma-262 14.6 Class Definitions + // A class definition is always strict mode code. + var oldStrict = this.strict; + this.strict = true; + + this.parseClassId(node, isStatement); + this.parseClassSuper(node); + var classBody = this.startNode(); + var hadConstructor = false; + classBody.body = []; + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + var element = this.parseClassElement(node.superClass !== null); + if (element) { + classBody.body.push(element); + if (element.type === "MethodDefinition" && element.kind === "constructor") { + if (hadConstructor) { this.raise(element.start, "Duplicate constructor in the same class"); } + hadConstructor = true; + } + } + } + node.body = this.finishNode(classBody, "ClassBody"); + this.strict = oldStrict; + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") + }; + + pp$1.parseClassElement = function(constructorAllowsSuper) { + var this$1 = this; + + if (this.eat(types.semi)) { return null } + + var method = this.startNode(); + var tryContextual = function (k, noLineBreak) { + if ( noLineBreak === void 0 ) noLineBreak = false; + + var start = this$1.start, startLoc = this$1.startLoc; + if (!this$1.eatContextual(k)) { return false } + if (this$1.type !== types.parenL && (!noLineBreak || !this$1.canInsertSemicolon())) { return true } + if (method.key) { this$1.unexpected(); } + method.computed = false; + method.key = this$1.startNodeAt(start, startLoc); + method.key.name = k; + this$1.finishNode(method.key, "Identifier"); + return false + }; + + method.kind = "method"; + method.static = tryContextual("static"); + var isGenerator = this.eat(types.star); + var isAsync = false; + if (!isGenerator) { + if (this.options.ecmaVersion >= 8 && tryContextual("async", true)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + } else if (tryContextual("get")) { + method.kind = "get"; + } else if (tryContextual("set")) { + method.kind = "set"; + } + } + if (!method.key) { this.parsePropertyName(method); } + var key = method.key; + var allowsDirectSuper = false; + if (!method.computed && !method.static && (key.type === "Identifier" && key.name === "constructor" || + key.type === "Literal" && key.value === "constructor")) { + if (method.kind !== "method") { this.raise(key.start, "Constructor can't have get/set modifier"); } + if (isGenerator) { this.raise(key.start, "Constructor can't be a generator"); } + if (isAsync) { this.raise(key.start, "Constructor can't be an async method"); } + method.kind = "constructor"; + allowsDirectSuper = constructorAllowsSuper; + } else if (method.static && key.type === "Identifier" && key.name === "prototype") { + this.raise(key.start, "Classes may not have a static property named prototype"); + } + this.parseClassMethod(method, isGenerator, isAsync, allowsDirectSuper); + if (method.kind === "get" && method.value.params.length !== 0) + { this.raiseRecoverable(method.value.start, "getter should have no params"); } + if (method.kind === "set" && method.value.params.length !== 1) + { this.raiseRecoverable(method.value.start, "setter should have exactly one param"); } + if (method.kind === "set" && method.value.params[0].type === "RestElement") + { this.raiseRecoverable(method.value.params[0].start, "Setter cannot use rest params"); } + return method + }; + + pp$1.parseClassMethod = function(method, isGenerator, isAsync, allowsDirectSuper) { + method.value = this.parseMethod(isGenerator, isAsync, allowsDirectSuper); + return this.finishNode(method, "MethodDefinition") + }; + + pp$1.parseClassId = function(node, isStatement) { + if (this.type === types.name) { + node.id = this.parseIdent(); + if (isStatement) + { this.checkLVal(node.id, BIND_LEXICAL, false); } + } else { + if (isStatement === true) + { this.unexpected(); } + node.id = null; + } + }; + + pp$1.parseClassSuper = function(node) { + node.superClass = this.eat(types._extends) ? this.parseExprSubscripts() : null; + }; + + // Parses module export declaration. + + pp$1.parseExport = function(node, exports) { + this.next(); + // export * from '...' + if (this.eat(types.star)) { + this.expectContextual("from"); if (this.type !== types.string) { this.unexpected(); } node.source = this.parseExprAtom(); - } else { - // check for keywords used as local names - for (var i = 0, list = node.specifiers; i < list.length; i += 1) { - var spec = list[i]; - - this$1.checkUnreserved(spec.local); + this.semicolon(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(types._default)) { // export default ... + this.checkExport(exports, "default", this.lastTokStart); + var isAsync; + if (this.type === types._function || (isAsync = this.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, FUNC_STATEMENT | FUNC_NULLABLE_ID, false, isAsync); + } else if (this.type === types._class) { + var cNode = this.startNode(); + node.declaration = this.parseClass(cNode, "nullableID"); + } else { + node.declaration = this.parseMaybeAssign(); + this.semicolon(); } - + return this.finishNode(node, "ExportDefaultDeclaration") + } + // export var|const|let|function|class ... + if (this.shouldParseExportStatement()) { + node.declaration = this.parseStatement(null); + if (node.declaration.type === "VariableDeclaration") + { this.checkVariableExport(exports, node.declaration.declarations); } + else + { this.checkExport(exports, node.declaration.id.name, node.declaration.id.start); } + node.specifiers = []; node.source = null; + } else { // export { x, y as z } [from '...'] + node.declaration = null; + node.specifiers = this.parseExportSpecifiers(exports); + if (this.eatContextual("from")) { + if (this.type !== types.string) { this.unexpected(); } + node.source = this.parseExprAtom(); + } else { + for (var i = 0, list = node.specifiers; i < list.length; i += 1) { + // check for keywords used as local names + var spec = list[i]; + + this.checkUnreserved(spec.local); + // check if export is defined + this.checkLocalExport(spec.local); + } + + node.source = null; + } + this.semicolon(); + } + return this.finishNode(node, "ExportNamedDeclaration") + }; + + pp$1.checkExport = function(exports, name, pos) { + if (!exports) { return } + if (has(exports, name)) + { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } + exports[name] = true; + }; + + pp$1.checkPatternExport = function(exports, pat) { + var type = pat.type; + if (type === "Identifier") + { this.checkExport(exports, pat.name, pat.start); } + else if (type === "ObjectPattern") + { for (var i = 0, list = pat.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.checkPatternExport(exports, prop); + } } + else if (type === "ArrayPattern") + { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { + var elt = list$1[i$1]; + + if (elt) { this.checkPatternExport(exports, elt); } + } } + else if (type === "Property") + { this.checkPatternExport(exports, pat.value); } + else if (type === "AssignmentPattern") + { this.checkPatternExport(exports, pat.left); } + else if (type === "RestElement") + { this.checkPatternExport(exports, pat.argument); } + else if (type === "ParenthesizedExpression") + { this.checkPatternExport(exports, pat.expression); } + }; + + pp$1.checkVariableExport = function(exports, decls) { + if (!exports) { return } + for (var i = 0, list = decls; i < list.length; i += 1) + { + var decl = list[i]; + + this.checkPatternExport(exports, decl.id); + } + }; + + pp$1.shouldParseExportStatement = function() { + return this.type.keyword === "var" || + this.type.keyword === "const" || + this.type.keyword === "class" || + this.type.keyword === "function" || + this.isLet() || + this.isAsyncFunction() + }; + + // Parses a comma-separated list of module exports. + + pp$1.parseExportSpecifiers = function(exports) { + var nodes = [], first = true; + // export { x, y as z } [from '...'] + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var node = this.startNode(); + node.local = this.parseIdent(true); + node.exported = this.eatContextual("as") ? this.parseIdent(true) : node.local; + this.checkExport(exports, node.exported.name, node.exported.start); + nodes.push(this.finishNode(node, "ExportSpecifier")); + } + return nodes + }; + + // Parses import declaration. + + pp$1.parseImport = function(node) { + this.next(); + // import '...' + if (this.type === types.string) { + node.specifiers = empty; + node.source = this.parseExprAtom(); + } else { + node.specifiers = this.parseImportSpecifiers(); + this.expectContextual("from"); + node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); } this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration") -}; + return this.finishNode(node, "ImportDeclaration") + }; -pp$1.checkExport = function(exports, name, pos) { - if (!exports) { return } - if (has(exports, name)) - { this.raiseRecoverable(pos, "Duplicate export '" + name + "'"); } - exports[name] = true; -}; + // Parses a comma-separated list of module imports. -pp$1.checkPatternExport = function(exports, pat) { - var this$1 = this; - - var type = pat.type; - if (type === "Identifier") - { this.checkExport(exports, pat.name, pat.start); } - else if (type === "ObjectPattern") - { for (var i = 0, list = pat.properties; i < list.length; i += 1) - { - var prop = list[i]; - - this$1.checkPatternExport(exports, prop); - } } - else if (type === "ArrayPattern") - { for (var i$1 = 0, list$1 = pat.elements; i$1 < list$1.length; i$1 += 1) { - var elt = list$1[i$1]; - - if (elt) { this$1.checkPatternExport(exports, elt); } - } } - else if (type === "Property") - { this.checkPatternExport(exports, pat.value); } - else if (type === "AssignmentPattern") - { this.checkPatternExport(exports, pat.left); } - else if (type === "RestElement") - { this.checkPatternExport(exports, pat.argument); } - else if (type === "ParenthesizedExpression") - { this.checkPatternExport(exports, pat.expression); } -}; - -pp$1.checkVariableExport = function(exports, decls) { - var this$1 = this; - - if (!exports) { return } - for (var i = 0, list = decls; i < list.length; i += 1) - { - var decl = list[i]; - - this$1.checkPatternExport(exports, decl.id); - } -}; - -pp$1.shouldParseExportStatement = function() { - return this.type.keyword === "var" || - this.type.keyword === "const" || - this.type.keyword === "class" || - this.type.keyword === "function" || - this.isLet() || - this.isAsyncFunction() -}; - -// Parses a comma-separated list of module exports. - -pp$1.parseExportSpecifiers = function(exports) { - var this$1 = this; - - var nodes = [], first = true; - // export { x, y as z } [from '...'] - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node = this$1.startNode(); - node.local = this$1.parseIdent(true); - node.exported = this$1.eatContextual("as") ? this$1.parseIdent(true) : node.local; - this$1.checkExport(exports, node.exported.name, node.exported.start); - nodes.push(this$1.finishNode(node, "ExportSpecifier")); - } - return nodes -}; - -// Parses import declaration. - -pp$1.parseImport = function(node) { - this.next(); - // import '...' - if (this.type === types.string) { - node.specifiers = empty; - node.source = this.parseExprAtom(); - } else { - node.specifiers = this.parseImportSpecifiers(); - this.expectContextual("from"); - node.source = this.type === types.string ? this.parseExprAtom() : this.unexpected(); - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration") -}; - -// Parses a comma-separated list of module imports. - -pp$1.parseImportSpecifiers = function() { - var this$1 = this; - - var nodes = [], first = true; - if (this.type === types.name) { - // import defaultObj, { x, y as z } from '...' - var node = this.startNode(); - node.local = this.parseIdent(); - this.checkLVal(node.local, BIND_LEXICAL); - nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); - if (!this.eat(types.comma)) { return nodes } - } - if (this.type === types.star) { - var node$1 = this.startNode(); - this.next(); - this.expectContextual("as"); - node$1.local = this.parseIdent(); - this.checkLVal(node$1.local, BIND_LEXICAL); - nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); - return nodes - } - this.expect(types.braceL); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var node$2 = this$1.startNode(); - node$2.imported = this$1.parseIdent(true); - if (this$1.eatContextual("as")) { - node$2.local = this$1.parseIdent(); - } else { - this$1.checkUnreserved(node$2.imported); - node$2.local = node$2.imported; + pp$1.parseImportSpecifiers = function() { + var nodes = [], first = true; + if (this.type === types.name) { + // import defaultObj, { x, y as z } from '...' + var node = this.startNode(); + node.local = this.parseIdent(); + this.checkLVal(node.local, BIND_LEXICAL); + nodes.push(this.finishNode(node, "ImportDefaultSpecifier")); + if (!this.eat(types.comma)) { return nodes } } - this$1.checkLVal(node$2.local, BIND_LEXICAL); - nodes.push(this$1.finishNode(node$2, "ImportSpecifier")); - } - return nodes -}; + if (this.type === types.star) { + var node$1 = this.startNode(); + this.next(); + this.expectContextual("as"); + node$1.local = this.parseIdent(); + this.checkLVal(node$1.local, BIND_LEXICAL); + nodes.push(this.finishNode(node$1, "ImportNamespaceSpecifier")); + return nodes + } + this.expect(types.braceL); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } -// Set `ExpressionStatement#directive` property for directive prologues. -pp$1.adaptDirectivePrologue = function(statements) { - for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { - statements[i].directive = statements[i].expression.raw.slice(1, -1); - } -}; -pp$1.isDirectiveCandidate = function(statement) { - return ( - statement.type === "ExpressionStatement" && - statement.expression.type === "Literal" && - typeof statement.expression.value === "string" && - // Reject parenthesized strings. - (this.input[statement.start] === "\"" || this.input[statement.start] === "'") - ) -}; + var node$2 = this.startNode(); + node$2.imported = this.parseIdent(true); + if (this.eatContextual("as")) { + node$2.local = this.parseIdent(); + } else { + this.checkUnreserved(node$2.imported); + node$2.local = node$2.imported; + } + this.checkLVal(node$2.local, BIND_LEXICAL); + nodes.push(this.finishNode(node$2, "ImportSpecifier")); + } + return nodes + }; -var pp$2 = Parser.prototype; + // Set `ExpressionStatement#directive` property for directive prologues. + pp$1.adaptDirectivePrologue = function(statements) { + for (var i = 0; i < statements.length && this.isDirectiveCandidate(statements[i]); ++i) { + statements[i].directive = statements[i].expression.raw.slice(1, -1); + } + }; + pp$1.isDirectiveCandidate = function(statement) { + return ( + statement.type === "ExpressionStatement" && + statement.expression.type === "Literal" && + typeof statement.expression.value === "string" && + // Reject parenthesized strings. + (this.input[statement.start] === "\"" || this.input[statement.start] === "'") + ) + }; -// Convert existing expression atom to assignable pattern -// if possible. + var pp$2 = Parser.prototype; -pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { - var this$1 = this; + // Convert existing expression atom to assignable pattern + // if possible. - if (this.options.ecmaVersion >= 6 && node) { - switch (node.type) { + pp$2.toAssignable = function(node, isBinding, refDestructuringErrors) { + if (this.options.ecmaVersion >= 6 && node) { + switch (node.type) { + case "Identifier": + if (this.inAsync && node.name === "await") + { this.raise(node.start, "Cannot use 'await' as identifier inside an async function"); } + break + + case "ObjectPattern": + case "ArrayPattern": + case "RestElement": + break + + case "ObjectExpression": + node.type = "ObjectPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + for (var i = 0, list = node.properties; i < list.length; i += 1) { + var prop = list[i]; + + this.toAssignable(prop, isBinding); + // Early error: + // AssignmentRestProperty[Yield, Await] : + // `...` DestructuringAssignmentTarget[Yield, Await] + // + // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. + if ( + prop.type === "RestElement" && + (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") + ) { + this.raise(prop.argument.start, "Unexpected token"); + } + } + break + + case "Property": + // AssignmentProperty has type === "Property" + if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } + this.toAssignable(node.value, isBinding); + break + + case "ArrayExpression": + node.type = "ArrayPattern"; + if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + this.toAssignableList(node.elements, isBinding); + break + + case "SpreadElement": + node.type = "RestElement"; + this.toAssignable(node.argument, isBinding); + if (node.argument.type === "AssignmentPattern") + { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + break + + case "AssignmentExpression": + if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } + node.type = "AssignmentPattern"; + delete node.operator; + this.toAssignable(node.left, isBinding); + // falls through to AssignmentPattern + + case "AssignmentPattern": + break + + case "ParenthesizedExpression": + this.toAssignable(node.expression, isBinding, refDestructuringErrors); + break + + case "MemberExpression": + if (!isBinding) { break } + + default: + this.raise(node.start, "Assigning to rvalue"); + } + } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } + return node + }; + + // Convert list of expression atoms to binding list. + + pp$2.toAssignableList = function(exprList, isBinding) { + var end = exprList.length; + for (var i = 0; i < end; i++) { + var elt = exprList[i]; + if (elt) { this.toAssignable(elt, isBinding); } + } + if (end) { + var last = exprList[end - 1]; + if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") + { this.unexpected(last.argument.start); } + } + return exprList + }; + + // Parses spread element. + + pp$2.parseSpread = function(refDestructuringErrors) { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeAssign(false, refDestructuringErrors); + return this.finishNode(node, "SpreadElement") + }; + + pp$2.parseRestBinding = function() { + var node = this.startNode(); + this.next(); + + // RestElement inside of a function parameter must be an identifier + if (this.options.ecmaVersion === 6 && this.type !== types.name) + { this.unexpected(); } + + node.argument = this.parseBindingAtom(); + + return this.finishNode(node, "RestElement") + }; + + // Parses lvalue (assignable) atom. + + pp$2.parseBindingAtom = function() { + if (this.options.ecmaVersion >= 6) { + switch (this.type) { + case types.bracketL: + var node = this.startNode(); + this.next(); + node.elements = this.parseBindingList(types.bracketR, true, true); + return this.finishNode(node, "ArrayPattern") + + case types.braceL: + return this.parseObj(true) + } + } + return this.parseIdent() + }; + + pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { + var elts = [], first = true; + while (!this.eat(close)) { + if (first) { first = false; } + else { this.expect(types.comma); } + if (allowEmpty && this.type === types.comma) { + elts.push(null); + } else if (allowTrailingComma && this.afterTrailingComma(close)) { + break + } else if (this.type === types.ellipsis) { + var rest = this.parseRestBinding(); + this.parseBindingListItem(rest); + elts.push(rest); + if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } + this.expect(close); + break + } else { + var elem = this.parseMaybeDefault(this.start, this.startLoc); + this.parseBindingListItem(elem); + elts.push(elem); + } + } + return elts + }; + + pp$2.parseBindingListItem = function(param) { + return param + }; + + // Parses assignment pattern around given atom if possible. + + pp$2.parseMaybeDefault = function(startPos, startLoc, left) { + left = left || this.parseBindingAtom(); + if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.right = this.parseMaybeAssign(); + return this.finishNode(node, "AssignmentPattern") + }; + + // Verify that a node is an lval — something that can be assigned + // to. + // bindingType can be either: + // 'var' indicating that the lval creates a 'var' binding + // 'let' indicating that the lval creates a lexical ('let' or 'const') binding + // 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references + + pp$2.checkLVal = function(expr, bindingType, checkClashes) { + if ( bindingType === void 0 ) bindingType = BIND_NONE; + + switch (expr.type) { case "Identifier": - if (this.inAsync && node.name === "await") - { this.raise(node.start, "Can not use 'await' as identifier inside an async function"); } + if (bindingType === BIND_LEXICAL && expr.name === "let") + { this.raiseRecoverable(expr.start, "let is disallowed as a lexically bound name"); } + if (this.strict && this.reservedWordsStrictBind.test(expr.name)) + { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } + if (checkClashes) { + if (has(checkClashes, expr.name)) + { this.raiseRecoverable(expr.start, "Argument name clash"); } + checkClashes[expr.name] = true; + } + if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } + break + + case "MemberExpression": + if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } break case "ObjectPattern": - case "ArrayPattern": - case "RestElement": - break + for (var i = 0, list = expr.properties; i < list.length; i += 1) + { + var prop = list[i]; - case "ObjectExpression": - node.type = "ObjectPattern"; - if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - for (var i = 0, list = node.properties; i < list.length; i += 1) { - var prop = list[i]; - - this$1.toAssignable(prop, isBinding); - // Early error: - // AssignmentRestProperty[Yield, Await] : - // `...` DestructuringAssignmentTarget[Yield, Await] - // - // It is a Syntax Error if |DestructuringAssignmentTarget| is an |ArrayLiteral| or an |ObjectLiteral|. - if ( - prop.type === "RestElement" && - (prop.argument.type === "ArrayPattern" || prop.argument.type === "ObjectPattern") - ) { - this$1.raise(prop.argument.start, "Unexpected token"); - } - } + this.checkLVal(prop, bindingType, checkClashes); + } break case "Property": // AssignmentProperty has type === "Property" - if (node.kind !== "init") { this.raise(node.key.start, "Object pattern can't contain getter or setter"); } - this.toAssignable(node.value, isBinding); + this.checkLVal(expr.value, bindingType, checkClashes); break - case "ArrayExpression": - node.type = "ArrayPattern"; - if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - this.toAssignableList(node.elements, isBinding); - break + case "ArrayPattern": + for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { + var elem = list$1[i$1]; - case "SpreadElement": - node.type = "RestElement"; - this.toAssignable(node.argument, isBinding); - if (node.argument.type === "AssignmentPattern") - { this.raise(node.argument.start, "Rest elements cannot have a default value"); } + if (elem) { this.checkLVal(elem, bindingType, checkClashes); } + } break - case "AssignmentExpression": - if (node.operator !== "=") { this.raise(node.left.end, "Only '=' operator can be used for specifying default value."); } - node.type = "AssignmentPattern"; - delete node.operator; - this.toAssignable(node.left, isBinding); - // falls through to AssignmentPattern - case "AssignmentPattern": + this.checkLVal(expr.left, bindingType, checkClashes); + break + + case "RestElement": + this.checkLVal(expr.argument, bindingType, checkClashes); break case "ParenthesizedExpression": - this.toAssignable(node.expression, isBinding); + this.checkLVal(expr.expression, bindingType, checkClashes); break - case "MemberExpression": - if (!isBinding) { break } - default: - this.raise(node.start, "Assigning to rvalue"); + this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); } - } else if (refDestructuringErrors) { this.checkPatternErrors(refDestructuringErrors, true); } - return node -}; + }; -// Convert list of expression atoms to binding list. + // A recursive descent parser operates by defining functions for all -pp$2.toAssignableList = function(exprList, isBinding) { - var this$1 = this; + var pp$3 = Parser.prototype; - var end = exprList.length; - for (var i = 0; i < end; i++) { - var elt = exprList[i]; - if (elt) { this$1.toAssignable(elt, isBinding); } - } - if (end) { - var last = exprList[end - 1]; - if (this.options.ecmaVersion === 6 && isBinding && last && last.type === "RestElement" && last.argument.type !== "Identifier") - { this.unexpected(last.argument.start); } - } - return exprList -}; + // Check if property name clashes with already added. + // Object/class getters and setters are not allowed to clash — + // either with each other or with an init property — and in + // strict mode, init properties are also not allowed to be repeated. -// Parses spread element. - -pp$2.parseSpread = function(refDestructuringErrors) { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeAssign(false, refDestructuringErrors); - return this.finishNode(node, "SpreadElement") -}; - -pp$2.parseRestBinding = function() { - var node = this.startNode(); - this.next(); - - // RestElement inside of a function parameter must be an identifier - if (this.options.ecmaVersion === 6 && this.type !== types.name) - { this.unexpected(); } - - node.argument = this.parseBindingAtom(); - - return this.finishNode(node, "RestElement") -}; - -// Parses lvalue (assignable) atom. - -pp$2.parseBindingAtom = function() { - if (this.options.ecmaVersion >= 6) { - switch (this.type) { - case types.bracketL: - var node = this.startNode(); - this.next(); - node.elements = this.parseBindingList(types.bracketR, true, true); - return this.finishNode(node, "ArrayPattern") - - case types.braceL: - return this.parseObj(true) + pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { + if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") + { return } + if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) + { return } + var key = prop.key; + var name; + switch (key.type) { + case "Identifier": name = key.name; break + case "Literal": name = String(key.value); break + default: return } - } - return this.parseIdent() -}; - -pp$2.parseBindingList = function(close, allowEmpty, allowTrailingComma) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (first) { first = false; } - else { this$1.expect(types.comma); } - if (allowEmpty && this$1.type === types.comma) { - elts.push(null); - } else if (allowTrailingComma && this$1.afterTrailingComma(close)) { - break - } else if (this$1.type === types.ellipsis) { - var rest = this$1.parseRestBinding(); - this$1.parseBindingListItem(rest); - elts.push(rest); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - this$1.expect(close); - break - } else { - var elem = this$1.parseMaybeDefault(this$1.start, this$1.startLoc); - this$1.parseBindingListItem(elem); - elts.push(elem); - } - } - return elts -}; - -pp$2.parseBindingListItem = function(param) { - return param -}; - -// Parses assignment pattern around given atom if possible. - -pp$2.parseMaybeDefault = function(startPos, startLoc, left) { - left = left || this.parseBindingAtom(); - if (this.options.ecmaVersion < 6 || !this.eat(types.eq)) { return left } - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.right = this.parseMaybeAssign(); - return this.finishNode(node, "AssignmentPattern") -}; - -// Verify that a node is an lval — something that can be assigned -// to. -// bindingType can be either: -// 'var' indicating that the lval creates a 'var' binding -// 'let' indicating that the lval creates a lexical ('let' or 'const') binding -// 'none' indicating that the binding should be checked for illegal identifiers, but not for duplicate references - -pp$2.checkLVal = function(expr, bindingType, checkClashes) { - var this$1 = this; - if ( bindingType === void 0 ) bindingType = BIND_NONE; - - switch (expr.type) { - case "Identifier": - if (this.strict && this.reservedWordsStrictBind.test(expr.name)) - { this.raiseRecoverable(expr.start, (bindingType ? "Binding " : "Assigning to ") + expr.name + " in strict mode"); } - if (checkClashes) { - if (has(checkClashes, expr.name)) - { this.raiseRecoverable(expr.start, "Argument name clash"); } - checkClashes[expr.name] = true; - } - if (bindingType !== BIND_NONE && bindingType !== BIND_OUTSIDE) { this.declareName(expr.name, bindingType, expr.start); } - break - - case "MemberExpression": - if (bindingType) { this.raiseRecoverable(expr.start, "Binding member expression"); } - break - - case "ObjectPattern": - for (var i = 0, list = expr.properties; i < list.length; i += 1) - { - var prop = list[i]; - - this$1.checkLVal(prop, bindingType, checkClashes); - } - break - - case "Property": - // AssignmentProperty has type === "Property" - this.checkLVal(expr.value, bindingType, checkClashes); - break - - case "ArrayPattern": - for (var i$1 = 0, list$1 = expr.elements; i$1 < list$1.length; i$1 += 1) { - var elem = list$1[i$1]; - - if (elem) { this$1.checkLVal(elem, bindingType, checkClashes); } - } - break - - case "AssignmentPattern": - this.checkLVal(expr.left, bindingType, checkClashes); - break - - case "RestElement": - this.checkLVal(expr.argument, bindingType, checkClashes); - break - - case "ParenthesizedExpression": - this.checkLVal(expr.expression, bindingType, checkClashes); - break - - default: - this.raise(expr.start, (bindingType ? "Binding" : "Assigning to") + " rvalue"); - } -}; - -// A recursive descent parser operates by defining functions for all -// syntactic elements, and recursively calling those, each function -// advancing the input stream and returning an AST node. Precedence -// of constructs (for example, the fact that `!x[1]` means `!(x[1])` -// instead of `(!x)[1]` is handled by the fact that the parser -// function that parses unary prefix operators is called first, and -// in turn calls the function that parses `[]` subscripts — that -// way, it'll receive the node for `x[1]` already parsed, and wraps -// *that* in the unary operator node. -// -// Acorn uses an [operator precedence parser][opp] to handle binary -// operator precedence, because it is much more compact than using -// the technique outlined above, which uses different, nesting -// functions to specify precedence, for all of the ten binary -// precedence levels that JavaScript defines. -// -// [opp]: http://en.wikipedia.org/wiki/Operator-precedence_parser - -var pp$3 = Parser.prototype; - -// Check if property name clashes with already added. -// Object/class getters and setters are not allowed to clash — -// either with each other or with an init property — and in -// strict mode, init properties are also not allowed to be repeated. - -pp$3.checkPropClash = function(prop, propHash, refDestructuringErrors) { - if (this.options.ecmaVersion >= 9 && prop.type === "SpreadElement") - { return } - if (this.options.ecmaVersion >= 6 && (prop.computed || prop.method || prop.shorthand)) - { return } - var key = prop.key; - var name; - switch (key.type) { - case "Identifier": name = key.name; break - case "Literal": name = String(key.value); break - default: return - } - var kind = prop.kind; - if (this.options.ecmaVersion >= 6) { - if (name === "__proto__" && kind === "init") { - if (propHash.proto) { - if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } - // Backwards-compat kludge. Can be removed in version 6.0 - else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } + var kind = prop.kind; + if (this.options.ecmaVersion >= 6) { + if (name === "__proto__" && kind === "init") { + if (propHash.proto) { + if (refDestructuringErrors && refDestructuringErrors.doubleProto < 0) { refDestructuringErrors.doubleProto = key.start; } + // Backwards-compat kludge. Can be removed in version 6.0 + else { this.raiseRecoverable(key.start, "Redefinition of __proto__ property"); } + } + propHash.proto = true; } - propHash.proto = true; + return } - return - } - name = "$" + name; - var other = propHash[name]; - if (other) { - var redefinition; - if (kind === "init") { - redefinition = this.strict && other.init || other.get || other.set; - } else { - redefinition = other.init || other[kind]; - } - if (redefinition) - { this.raiseRecoverable(key.start, "Redefinition of property"); } - } else { - other = propHash[name] = { - init: false, - get: false, - set: false - }; - } - other[kind] = true; -}; - -// ### Expression parsing - -// These nest, from the most general expression type at the top to -// 'atomic', nondivisible expression types at the bottom. Most of -// the functions will simply let the function(s) below them parse, -// and, *if* the syntactic construct they handle is present, wrap -// the AST node that the inner parser gave them in another node. - -// Parse a full expression. The optional arguments are used to -// forbid the `in` operator (in for loops initalization expressions) -// and provide reference for storing '=' operator inside shorthand -// property assignment in contexts where both object expression -// and object pattern might appear (so it's possible to raise -// delayed syntax error at correct position). - -pp$3.parseExpression = function(noIn, refDestructuringErrors) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); - if (this.type === types.comma) { - var node = this.startNodeAt(startPos, startLoc); - node.expressions = [expr]; - while (this.eat(types.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn, refDestructuringErrors)); } - return this.finishNode(node, "SequenceExpression") - } - return expr -}; - -// Parse an assignment expression. This includes applications of -// operators like `+=`. - -pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { - if (this.isContextual("yield")) { - if (this.inGenerator) { return this.parseYield() } - // The tokenizer will assume an expression is allowed after - // `yield`, but this isn't that kind of yield - else { this.exprAllowed = false; } - } - - var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1; - if (refDestructuringErrors) { - oldParenAssign = refDestructuringErrors.parenthesizedAssign; - oldTrailingComma = refDestructuringErrors.trailingComma; - refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = -1; - } else { - refDestructuringErrors = new DestructuringErrors; - ownDestructuringErrors = true; - } - - var startPos = this.start, startLoc = this.startLoc; - if (this.type === types.parenL || this.type === types.name) - { this.potentialArrowAt = this.start; } - var left = this.parseMaybeConditional(noIn, refDestructuringErrors); - if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } - if (this.type.isAssign) { - var node = this.startNodeAt(startPos, startLoc); - node.operator = this.value; - node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; - if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } - refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly - this.checkLVal(left); - this.next(); - node.right = this.parseMaybeAssign(noIn); - return this.finishNode(node, "AssignmentExpression") - } else { - if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } - } - if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } - if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } - return left -}; - -// Parse a ternary conditional (`?:`) operator. - -pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprOps(noIn, refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - if (this.eat(types.question)) { - var node = this.startNodeAt(startPos, startLoc); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - this.expect(types.colon); - node.alternate = this.parseMaybeAssign(noIn); - return this.finishNode(node, "ConditionalExpression") - } - return expr -}; - -// Start the precedence parser. - -pp$3.parseExprOps = function(noIn, refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseMaybeUnary(refDestructuringErrors, false); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) -}; - -// Parse binary operators with the operator precedence parsing -// algorithm. `left` is the left-hand side of the operator. -// `minPrec` provides context that allows the function to stop and -// defer further parser to one of its callers when it encounters an -// operator that has a lower precedence than the set it is parsing. - -pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { - var prec = this.type.binop; - if (prec != null && (!noIn || this.type !== types._in)) { - if (prec > minPrec) { - var logical = this.type === types.logicalOR || this.type === types.logicalAND; - var op = this.value; - this.next(); - var startPos = this.start, startLoc = this.startLoc; - var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); - var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); - return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) - } - } - return left -}; - -pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { - var node = this.startNodeAt(startPos, startLoc); - node.left = left; - node.operator = op; - node.right = right; - return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") -}; - -// Parse unary operators, both prefix and postfix. - -pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, expr; - if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) { - expr = this.parseAwait(); - sawUnary = true; - } else if (this.type.prefix) { - var node = this.startNode(), update = this.type === types.incDec; - node.operator = this.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(null, true); - this.checkExpressionErrors(refDestructuringErrors, true); - if (update) { this.checkLVal(node.argument); } - else if (this.strict && node.operator === "delete" && - node.argument.type === "Identifier") - { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } - else { sawUnary = true; } - expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } else { - expr = this.parseExprSubscripts(refDestructuringErrors); - if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } - while (this.type.postfix && !this.canInsertSemicolon()) { - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.operator = this$1.value; - node$1.prefix = false; - node$1.argument = expr; - this$1.checkLVal(expr); - this$1.next(); - expr = this$1.finishNode(node$1, "UpdateExpression"); - } - } - - if (!sawUnary && this.eat(types.starstar)) - { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } - else - { return expr } -}; - -// Parse call, dot, and `[]`-subscript expressions. - -pp$3.parseExprSubscripts = function(refDestructuringErrors) { - var startPos = this.start, startLoc = this.startLoc; - var expr = this.parseExprAtom(refDestructuringErrors); - var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; - if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } - var result = this.parseSubscripts(expr, startPos, startLoc); - if (refDestructuringErrors && result.type === "MemberExpression") { - if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } - if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } - } - return result -}; - -pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { - var this$1 = this; - - var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && - this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; - for (var computed = (void 0);;) { - if ((computed = this$1.eat(types.bracketL)) || this$1.eat(types.dot)) { - var node = this$1.startNodeAt(startPos, startLoc); - node.object = base; - node.property = computed ? this$1.parseExpression() : this$1.parseIdent(true); - node.computed = !!computed; - if (computed) { this$1.expect(types.bracketR); } - base = this$1.finishNode(node, "MemberExpression"); - } else if (!noCalls && this$1.eat(types.parenL)) { - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this$1.yieldPos, oldAwaitPos = this$1.awaitPos; - this$1.yieldPos = 0; - this$1.awaitPos = 0; - var exprList = this$1.parseExprList(types.parenR, this$1.options.ecmaVersion >= 8, false, refDestructuringErrors); - if (maybeAsyncArrow && !this$1.canInsertSemicolon() && this$1.eat(types.arrow)) { - this$1.checkPatternErrors(refDestructuringErrors, false); - this$1.checkYieldAwaitInDefaultParams(); - this$1.yieldPos = oldYieldPos; - this$1.awaitPos = oldAwaitPos; - return this$1.parseArrowExpression(this$1.startNodeAt(startPos, startLoc), exprList, true) + name = "$" + name; + var other = propHash[name]; + if (other) { + var redefinition; + if (kind === "init") { + redefinition = this.strict && other.init || other.get || other.set; + } else { + redefinition = other.init || other[kind]; } - this$1.checkExpressionErrors(refDestructuringErrors, true); - this$1.yieldPos = oldYieldPos || this$1.yieldPos; - this$1.awaitPos = oldAwaitPos || this$1.awaitPos; - var node$1 = this$1.startNodeAt(startPos, startLoc); - node$1.callee = base; - node$1.arguments = exprList; - base = this$1.finishNode(node$1, "CallExpression"); - } else if (this$1.type === types.backQuote) { - var node$2 = this$1.startNodeAt(startPos, startLoc); - node$2.tag = base; - node$2.quasi = this$1.parseTemplate({isTagged: true}); - base = this$1.finishNode(node$2, "TaggedTemplateExpression"); + if (redefinition) + { this.raiseRecoverable(key.start, "Redefinition of property"); } } else { - return base + other = propHash[name] = { + init: false, + get: false, + set: false + }; } - } -}; + other[kind] = true; + }; -// Parse an atomic expression — either a single token that is an -// expression, an expression started by a keyword like `function` or -// `new`, or an expression wrapped in punctuation like `()`, `[]`, -// or `{}`. + // ### Expression parsing -pp$3.parseExprAtom = function(refDestructuringErrors) { - var node, canBeArrow = this.potentialArrowAt === this.start; - switch (this.type) { - case types._super: - if (!this.inFunction) - { this.raise(this.start, "'super' outside of function or class"); } - node = this.startNode(); - this.next(); - // The `super` keyword can appear at below: - // SuperProperty: - // super [ Expression ] - // super . IdentifierName - // SuperCall: - // super Arguments - if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) - { this.unexpected(); } - return this.finishNode(node, "Super") + // These nest, from the most general expression type at the top to + // 'atomic', nondivisible expression types at the bottom. Most of + // the functions will simply let the function(s) below them parse, + // and, *if* the syntactic construct they handle is present, wrap + // the AST node that the inner parser gave them in another node. - case types._this: - node = this.startNode(); - this.next(); - return this.finishNode(node, "ThisExpression") + // Parse a full expression. The optional arguments are used to + // forbid the `in` operator (in for loops initalization expressions) + // and provide reference for storing '=' operator inside shorthand + // property assignment in contexts where both object expression + // and object pattern might appear (so it's possible to raise + // delayed syntax error at correct position). - case types.name: - var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; - var id = this.parseIdent(this.type !== types.name); - if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) - { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) } - if (canBeArrow && !this.canInsertSemicolon()) { - if (this.eat(types.arrow)) - { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } - if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { - id = this.parseIdent(); - if (this.canInsertSemicolon() || !this.eat(types.arrow)) - { this.unexpected(); } - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) - } - } - return id - - case types.regexp: - var value = this.value; - node = this.parseLiteral(value.value); - node.regex = {pattern: value.pattern, flags: value.flags}; - return node - - case types.num: case types.string: - return this.parseLiteral(this.value) - - case types._null: case types._true: case types._false: - node = this.startNode(); - node.value = this.type === types._null ? null : this.type === types._true; - node.raw = this.type.keyword; - this.next(); - return this.finishNode(node, "Literal") - - case types.parenL: - var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); - if (refDestructuringErrors) { - if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) - { refDestructuringErrors.parenthesizedAssign = start; } - if (refDestructuringErrors.parenthesizedBind < 0) - { refDestructuringErrors.parenthesizedBind = start; } + pp$3.parseExpression = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeAssign(noIn, refDestructuringErrors); + if (this.type === types.comma) { + var node = this.startNodeAt(startPos, startLoc); + node.expressions = [expr]; + while (this.eat(types.comma)) { node.expressions.push(this.parseMaybeAssign(noIn, refDestructuringErrors)); } + return this.finishNode(node, "SequenceExpression") } return expr + }; - case types.bracketL: - node = this.startNode(); + // Parse an assignment expression. This includes applications of + // operators like `+=`. + + pp$3.parseMaybeAssign = function(noIn, refDestructuringErrors, afterLeftParse) { + if (this.isContextual("yield")) { + if (this.inGenerator) { return this.parseYield(noIn) } + // The tokenizer will assume an expression is allowed after + // `yield`, but this isn't that kind of yield + else { this.exprAllowed = false; } + } + + var ownDestructuringErrors = false, oldParenAssign = -1, oldTrailingComma = -1, oldShorthandAssign = -1; + if (refDestructuringErrors) { + oldParenAssign = refDestructuringErrors.parenthesizedAssign; + oldTrailingComma = refDestructuringErrors.trailingComma; + oldShorthandAssign = refDestructuringErrors.shorthandAssign; + refDestructuringErrors.parenthesizedAssign = refDestructuringErrors.trailingComma = refDestructuringErrors.shorthandAssign = -1; + } else { + refDestructuringErrors = new DestructuringErrors; + ownDestructuringErrors = true; + } + + var startPos = this.start, startLoc = this.startLoc; + if (this.type === types.parenL || this.type === types.name) + { this.potentialArrowAt = this.start; } + var left = this.parseMaybeConditional(noIn, refDestructuringErrors); + if (afterLeftParse) { left = afterLeftParse.call(this, left, startPos, startLoc); } + if (this.type.isAssign) { + var node = this.startNodeAt(startPos, startLoc); + node.operator = this.value; + node.left = this.type === types.eq ? this.toAssignable(left, false, refDestructuringErrors) : left; + if (!ownDestructuringErrors) { DestructuringErrors.call(refDestructuringErrors); } + refDestructuringErrors.shorthandAssign = -1; // reset because shorthand default was used correctly + this.checkLVal(left); + this.next(); + node.right = this.parseMaybeAssign(noIn); + return this.finishNode(node, "AssignmentExpression") + } else { + if (ownDestructuringErrors) { this.checkExpressionErrors(refDestructuringErrors, true); } + } + if (oldParenAssign > -1) { refDestructuringErrors.parenthesizedAssign = oldParenAssign; } + if (oldTrailingComma > -1) { refDestructuringErrors.trailingComma = oldTrailingComma; } + if (oldShorthandAssign > -1) { refDestructuringErrors.shorthandAssign = oldShorthandAssign; } + return left + }; + + // Parse a ternary conditional (`?:`) operator. + + pp$3.parseMaybeConditional = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprOps(noIn, refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + if (this.eat(types.question)) { + var node = this.startNodeAt(startPos, startLoc); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + this.expect(types.colon); + node.alternate = this.parseMaybeAssign(noIn); + return this.finishNode(node, "ConditionalExpression") + } + return expr + }; + + // Start the precedence parser. + + pp$3.parseExprOps = function(noIn, refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseMaybeUnary(refDestructuringErrors, false); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + return expr.start === startPos && expr.type === "ArrowFunctionExpression" ? expr : this.parseExprOp(expr, startPos, startLoc, -1, noIn) + }; + + // Parse binary operators with the operator precedence parsing + // algorithm. `left` is the left-hand side of the operator. + // `minPrec` provides context that allows the function to stop and + // defer further parser to one of its callers when it encounters an + // operator that has a lower precedence than the set it is parsing. + + pp$3.parseExprOp = function(left, leftStartPos, leftStartLoc, minPrec, noIn) { + var prec = this.type.binop; + if (prec != null && (!noIn || this.type !== types._in)) { + if (prec > minPrec) { + var logical = this.type === types.logicalOR || this.type === types.logicalAND; + var op = this.value; + this.next(); + var startPos = this.start, startLoc = this.startLoc; + var right = this.parseExprOp(this.parseMaybeUnary(null, false), startPos, startLoc, prec, noIn); + var node = this.buildBinary(leftStartPos, leftStartLoc, left, right, op, logical); + return this.parseExprOp(node, leftStartPos, leftStartLoc, minPrec, noIn) + } + } + return left + }; + + pp$3.buildBinary = function(startPos, startLoc, left, right, op, logical) { + var node = this.startNodeAt(startPos, startLoc); + node.left = left; + node.operator = op; + node.right = right; + return this.finishNode(node, logical ? "LogicalExpression" : "BinaryExpression") + }; + + // Parse unary operators, both prefix and postfix. + + pp$3.parseMaybeUnary = function(refDestructuringErrors, sawUnary) { + var startPos = this.start, startLoc = this.startLoc, expr; + if (this.isContextual("await") && (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction))) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.type.prefix) { + var node = this.startNode(), update = this.type === types.incDec; + node.operator = this.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(null, true); + this.checkExpressionErrors(refDestructuringErrors, true); + if (update) { this.checkLVal(node.argument); } + else if (this.strict && node.operator === "delete" && + node.argument.type === "Identifier") + { this.raiseRecoverable(node.start, "Deleting local variable in strict mode"); } + else { sawUnary = true; } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else { + expr = this.parseExprSubscripts(refDestructuringErrors); + if (this.checkExpressionErrors(refDestructuringErrors)) { return expr } + while (this.type.postfix && !this.canInsertSemicolon()) { + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.operator = this.value; + node$1.prefix = false; + node$1.argument = expr; + this.checkLVal(expr); + this.next(); + expr = this.finishNode(node$1, "UpdateExpression"); + } + } + + if (!sawUnary && this.eat(types.starstar)) + { return this.buildBinary(startPos, startLoc, expr, this.parseMaybeUnary(null, false), "**", false) } + else + { return expr } + }; + + // Parse call, dot, and `[]`-subscript expressions. + + pp$3.parseExprSubscripts = function(refDestructuringErrors) { + var startPos = this.start, startLoc = this.startLoc; + var expr = this.parseExprAtom(refDestructuringErrors); + var skipArrowSubscripts = expr.type === "ArrowFunctionExpression" && this.input.slice(this.lastTokStart, this.lastTokEnd) !== ")"; + if (this.checkExpressionErrors(refDestructuringErrors) || skipArrowSubscripts) { return expr } + var result = this.parseSubscripts(expr, startPos, startLoc); + if (refDestructuringErrors && result.type === "MemberExpression") { + if (refDestructuringErrors.parenthesizedAssign >= result.start) { refDestructuringErrors.parenthesizedAssign = -1; } + if (refDestructuringErrors.parenthesizedBind >= result.start) { refDestructuringErrors.parenthesizedBind = -1; } + } + return result + }; + + pp$3.parseSubscripts = function(base, startPos, startLoc, noCalls) { + var maybeAsyncArrow = this.options.ecmaVersion >= 8 && base.type === "Identifier" && base.name === "async" && + this.lastTokEnd === base.end && !this.canInsertSemicolon() && this.input.slice(base.start, base.end) === "async"; + while (true) { + var element = this.parseSubscript(base, startPos, startLoc, noCalls, maybeAsyncArrow); + if (element === base || element.type === "ArrowFunctionExpression") { return element } + base = element; + } + }; + + pp$3.parseSubscript = function(base, startPos, startLoc, noCalls, maybeAsyncArrow) { + var computed = this.eat(types.bracketL); + if (computed || this.eat(types.dot)) { + var node = this.startNodeAt(startPos, startLoc); + node.object = base; + node.property = computed ? this.parseExpression() : this.parseIdent(this.options.allowReserved !== "never"); + node.computed = !!computed; + if (computed) { this.expect(types.bracketR); } + base = this.finishNode(node, "MemberExpression"); + } else if (!noCalls && this.eat(types.parenL)) { + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + var exprList = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false, refDestructuringErrors); + if (maybeAsyncArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + if (this.awaitIdentPos > 0) + { this.raise(this.awaitIdentPos, "Cannot use 'await' as identifier inside an async function"); } + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList, true) + } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + this.awaitIdentPos = oldAwaitIdentPos || this.awaitIdentPos; + var node$1 = this.startNodeAt(startPos, startLoc); + node$1.callee = base; + node$1.arguments = exprList; + base = this.finishNode(node$1, "CallExpression"); + } else if (this.type === types.backQuote) { + var node$2 = this.startNodeAt(startPos, startLoc); + node$2.tag = base; + node$2.quasi = this.parseTemplate({isTagged: true}); + base = this.finishNode(node$2, "TaggedTemplateExpression"); + } + return base + }; + + // Parse an atomic expression — either a single token that is an + // expression, an expression started by a keyword like `function` or + // `new`, or an expression wrapped in punctuation like `()`, `[]`, + // or `{}`. + + pp$3.parseExprAtom = function(refDestructuringErrors) { + // If a division operator appears in an expression position, the + // tokenizer got confused, and we force it to read a regexp instead. + if (this.type === types.slash) { this.readRegexp(); } + + var node, canBeArrow = this.potentialArrowAt === this.start; + switch (this.type) { + case types._super: + if (!this.allowSuper) + { this.raise(this.start, "'super' keyword outside a method"); } + node = this.startNode(); + this.next(); + if (this.type === types.parenL && !this.allowDirectSuper) + { this.raise(node.start, "super() call outside constructor of a subclass"); } + // The `super` keyword can appear at below: + // SuperProperty: + // super [ Expression ] + // super . IdentifierName + // SuperCall: + // super ( Arguments ) + if (this.type !== types.dot && this.type !== types.bracketL && this.type !== types.parenL) + { this.unexpected(); } + return this.finishNode(node, "Super") + + case types._this: + node = this.startNode(); + this.next(); + return this.finishNode(node, "ThisExpression") + + case types.name: + var startPos = this.start, startLoc = this.startLoc, containsEsc = this.containsEsc; + var id = this.parseIdent(false); + if (this.options.ecmaVersion >= 8 && !containsEsc && id.name === "async" && !this.canInsertSemicolon() && this.eat(types._function)) + { return this.parseFunction(this.startNodeAt(startPos, startLoc), 0, false, true) } + if (canBeArrow && !this.canInsertSemicolon()) { + if (this.eat(types.arrow)) + { return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], false) } + if (this.options.ecmaVersion >= 8 && id.name === "async" && this.type === types.name && !containsEsc) { + id = this.parseIdent(false); + if (this.canInsertSemicolon() || !this.eat(types.arrow)) + { this.unexpected(); } + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), [id], true) + } + } + return id + + case types.regexp: + var value = this.value; + node = this.parseLiteral(value.value); + node.regex = {pattern: value.pattern, flags: value.flags}; + return node + + case types.num: case types.string: + return this.parseLiteral(this.value) + + case types._null: case types._true: case types._false: + node = this.startNode(); + node.value = this.type === types._null ? null : this.type === types._true; + node.raw = this.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case types.parenL: + var start = this.start, expr = this.parseParenAndDistinguishExpression(canBeArrow); + if (refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0 && !this.isSimpleAssignTarget(expr)) + { refDestructuringErrors.parenthesizedAssign = start; } + if (refDestructuringErrors.parenthesizedBind < 0) + { refDestructuringErrors.parenthesizedBind = start; } + } + return expr + + case types.bracketL: + node = this.startNode(); + this.next(); + node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); + return this.finishNode(node, "ArrayExpression") + + case types.braceL: + return this.parseObj(false, refDestructuringErrors) + + case types._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, 0) + + case types._class: + return this.parseClass(this.startNode(), false) + + case types._new: + return this.parseNew() + + case types.backQuote: + return this.parseTemplate() + + case types._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.unexpected() + } + + default: + this.unexpected(); + } + }; + + pp$3.parseExprImport = function() { + var node = this.startNode(); + this.next(); // skip `import` + switch (this.type) { + case types.parenL: + return this.parseDynamicImport(node) + default: + this.unexpected(); + } + }; + + pp$3.parseDynamicImport = function(node) { + this.next(); // skip `(` + + // Parse node.source. + node.source = this.parseMaybeAssign(); + + // Verify ending. + if (!this.eat(types.parenR)) { + var errorPos = this.start; + if (this.eat(types.comma) && this.eat(types.parenR)) { + this.raiseRecoverable(errorPos, "Trailing comma is not allowed in import()"); + } else { + this.unexpected(errorPos); + } + } + + return this.finishNode(node, "ImportExpression") + }; + + pp$3.parseLiteral = function(value) { + var node = this.startNode(); + node.value = value; + node.raw = this.input.slice(this.start, this.end); + if (node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); } this.next(); - node.elements = this.parseExprList(types.bracketR, true, true, refDestructuringErrors); - return this.finishNode(node, "ArrayExpression") + return this.finishNode(node, "Literal") + }; - case types.braceL: - return this.parseObj(false, refDestructuringErrors) + pp$3.parseParenExpression = function() { + this.expect(types.parenL); + var val = this.parseExpression(); + this.expect(types.parenR); + return val + }; - case types._function: - node = this.startNode(); + pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { + var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; + if (this.options.ecmaVersion >= 6) { + this.next(); + + var innerStartPos = this.start, innerStartLoc = this.startLoc; + var exprList = [], first = true, lastIsComma = false; + var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + this.yieldPos = 0; + this.awaitPos = 0; + // Do not save awaitIdentPos to allow checking awaits nested in parameters + while (this.type !== types.parenR) { + first ? first = false : this.expect(types.comma); + if (allowTrailingComma && this.afterTrailingComma(types.parenR, true)) { + lastIsComma = true; + break + } else if (this.type === types.ellipsis) { + spreadStart = this.start; + exprList.push(this.parseParenItem(this.parseRestBinding())); + if (this.type === types.comma) { this.raise(this.start, "Comma is not permitted after the rest element"); } + break + } else { + exprList.push(this.parseMaybeAssign(false, refDestructuringErrors, this.parseParenItem)); + } + } + var innerEndPos = this.start, innerEndLoc = this.startLoc; + this.expect(types.parenR); + + if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { + this.checkPatternErrors(refDestructuringErrors, false); + this.checkYieldAwaitInDefaultParams(); + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + return this.parseParenArrowList(startPos, startLoc, exprList) + } + + if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } + if (spreadStart) { this.unexpected(spreadStart); } + this.checkExpressionErrors(refDestructuringErrors, true); + this.yieldPos = oldYieldPos || this.yieldPos; + this.awaitPos = oldAwaitPos || this.awaitPos; + + if (exprList.length > 1) { + val = this.startNodeAt(innerStartPos, innerStartLoc); + val.expressions = exprList; + this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); + } else { + val = exprList[0]; + } + } else { + val = this.parseParenExpression(); + } + + if (this.options.preserveParens) { + var par = this.startNodeAt(startPos, startLoc); + par.expression = val; + return this.finishNode(par, "ParenthesizedExpression") + } else { + return val + } + }; + + pp$3.parseParenItem = function(item) { + return item + }; + + pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { + return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) + }; + + // New's precedence is slightly tricky. It must allow its argument to + // be a `[]` or dot subscript expression, but not a call — at least, + // not without wrapping it in parentheses. Thus, it uses the noCalls + // argument to parseSubscripts to prevent it from consuming the + // argument list. + + var empty$1 = []; + + pp$3.parseNew = function() { + var node = this.startNode(); + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { + node.meta = meta; + var containsEsc = this.containsEsc; + node.property = this.parseIdent(true); + if (node.property.name !== "target" || containsEsc) + { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } + if (!this.inNonArrowFunction()) + { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } + return this.finishNode(node, "MetaProperty") + } + var startPos = this.start, startLoc = this.startLoc, isImport = this.type === types._import; + node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); + if (isImport && node.callee.type === "ImportExpression") { + this.raise(startPos, "Cannot use new with import()"); + } + if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } + else { node.arguments = empty$1; } + return this.finishNode(node, "NewExpression") + }; + + // Parse template expression. + + pp$3.parseTemplateElement = function(ref) { + var isTagged = ref.isTagged; + + var elem = this.startNode(); + if (this.type === types.invalidTemplate) { + if (!isTagged) { + this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); + } + elem.value = { + raw: this.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), + cooked: this.value + }; + } this.next(); - return this.parseFunction(node, 0) + elem.tail = this.type === types.backQuote; + return this.finishNode(elem, "TemplateElement") + }; - case types._class: - return this.parseClass(this.startNode(), false) + pp$3.parseTemplate = function(ref) { + if ( ref === void 0 ) ref = {}; + var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; - case types._new: - return this.parseNew() - - case types.backQuote: - return this.parseTemplate() - - default: - this.unexpected(); - } -}; - -pp$3.parseLiteral = function(value) { - var node = this.startNode(); - node.value = value; - node.raw = this.input.slice(this.start, this.end); - this.next(); - return this.finishNode(node, "Literal") -}; - -pp$3.parseParenExpression = function() { - this.expect(types.parenL); - var val = this.parseExpression(); - this.expect(types.parenR); - return val -}; - -pp$3.parseParenAndDistinguishExpression = function(canBeArrow) { - var this$1 = this; - - var startPos = this.start, startLoc = this.startLoc, val, allowTrailingComma = this.options.ecmaVersion >= 8; - if (this.options.ecmaVersion >= 6) { + var node = this.startNode(); this.next(); + node.expressions = []; + var curElt = this.parseTemplateElement({isTagged: isTagged}); + node.quasis = [curElt]; + while (!curElt.tail) { + if (this.type === types.eof) { this.raise(this.pos, "Unterminated template literal"); } + this.expect(types.dollarBraceL); + node.expressions.push(this.parseExpression()); + this.expect(types.braceR); + node.quasis.push(curElt = this.parseTemplateElement({isTagged: isTagged})); + } + this.next(); + return this.finishNode(node, "TemplateLiteral") + }; - var innerStartPos = this.start, innerStartLoc = this.startLoc; - var exprList = [], first = true, lastIsComma = false; - var refDestructuringErrors = new DestructuringErrors, oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, spreadStart; + pp$3.isAsyncProp = function(prop) { + return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && + (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && + !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) + }; + + // Parse an object literal or binding pattern. + + pp$3.parseObj = function(isPattern, refDestructuringErrors) { + var node = this.startNode(), first = true, propHash = {}; + node.properties = []; + this.next(); + while (!this.eat(types.braceR)) { + if (!first) { + this.expect(types.comma); + if (this.options.ecmaVersion >= 5 && this.afterTrailingComma(types.braceR)) { break } + } else { first = false; } + + var prop = this.parseProperty(isPattern, refDestructuringErrors); + if (!isPattern) { this.checkPropClash(prop, propHash, refDestructuringErrors); } + node.properties.push(prop); + } + return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") + }; + + pp$3.parseProperty = function(isPattern, refDestructuringErrors) { + var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; + if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { + if (isPattern) { + prop.argument = this.parseIdent(false); + if (this.type === types.comma) { + this.raise(this.start, "Comma is not permitted after the rest element"); + } + return this.finishNode(prop, "RestElement") + } + // To disallow parenthesized identifier via `this.toAssignable()`. + if (this.type === types.parenL && refDestructuringErrors) { + if (refDestructuringErrors.parenthesizedAssign < 0) { + refDestructuringErrors.parenthesizedAssign = this.start; + } + if (refDestructuringErrors.parenthesizedBind < 0) { + refDestructuringErrors.parenthesizedBind = this.start; + } + } + // Parse argument. + prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); + // To disallow trailing comma via `this.toAssignable()`. + if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { + refDestructuringErrors.trailingComma = this.start; + } + // Finish + return this.finishNode(prop, "SpreadElement") + } + if (this.options.ecmaVersion >= 6) { + prop.method = false; + prop.shorthand = false; + if (isPattern || refDestructuringErrors) { + startPos = this.start; + startLoc = this.startLoc; + } + if (!isPattern) + { isGenerator = this.eat(types.star); } + } + var containsEsc = this.containsEsc; + this.parsePropertyName(prop); + if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); + this.parsePropertyName(prop, refDestructuringErrors); + } else { + isAsync = false; + } + this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); + return this.finishNode(prop, "Property") + }; + + pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { + if ((isGenerator || isAsync) && this.type === types.colon) + { this.unexpected(); } + + if (this.eat(types.colon)) { + prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); + prop.kind = "init"; + } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { + if (isPattern) { this.unexpected(); } + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (!isPattern && !containsEsc && + this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && + (prop.key.name === "get" || prop.key.name === "set") && + (this.type !== types.comma && this.type !== types.braceR)) { + if (isGenerator || isAsync) { this.unexpected(); } + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + var paramCount = prop.kind === "get" ? 0 : 1; + if (prop.value.params.length !== paramCount) { + var start = prop.value.start; + if (prop.kind === "get") + { this.raiseRecoverable(start, "getter should have no params"); } + else + { this.raiseRecoverable(start, "setter should have exactly one param"); } + } else { + if (prop.kind === "set" && prop.value.params[0].type === "RestElement") + { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } + } + } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { + if (isGenerator || isAsync) { this.unexpected(); } + this.checkUnreserved(prop.key); + if (prop.key.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = startPos; } + prop.kind = "init"; + if (isPattern) { + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else if (this.type === types.eq && refDestructuringErrors) { + if (refDestructuringErrors.shorthandAssign < 0) + { refDestructuringErrors.shorthandAssign = this.start; } + prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); + } else { + prop.value = prop.key; + } + prop.shorthand = true; + } else { this.unexpected(); } + }; + + pp$3.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(types.bracketL)) { + prop.computed = true; + prop.key = this.parseMaybeAssign(); + this.expect(types.bracketR); + return prop.key + } else { + prop.computed = false; + } + } + return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(this.options.allowReserved !== "never") + }; + + // Initialize empty function node. + + pp$3.initFunction = function(node) { + node.id = null; + if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } + if (this.options.ecmaVersion >= 8) { node.async = false; } + }; + + // Parse object or class method. + + pp$3.parseMethod = function(isGenerator, isAsync, allowDirectSuper) { + var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.yieldPos = 0; this.awaitPos = 0; - while (this.type !== types.parenR) { - first ? first = false : this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(types.parenR, true)) { - lastIsComma = true; - break - } else if (this$1.type === types.ellipsis) { - spreadStart = this$1.start; - exprList.push(this$1.parseParenItem(this$1.parseRestBinding())); - if (this$1.type === types.comma) { this$1.raise(this$1.start, "Comma is not permitted after the rest element"); } - break - } else { - exprList.push(this$1.parseMaybeAssign(false, refDestructuringErrors, this$1.parseParenItem)); + this.awaitIdentPos = 0; + this.enterScope(functionFlags(isAsync, node.generator) | SCOPE_SUPER | (allowDirectSuper ? SCOPE_DIRECT_SUPER : 0)); + + this.expect(types.parenL); + node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); + this.checkYieldAwaitInDefaultParams(); + this.parseFunctionBody(node, false, true); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "FunctionExpression") + }; + + // Parse arrow function expression with given parameters. + + pp$3.parseArrowExpression = function(node, params, isAsync) { + var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos, oldAwaitIdentPos = this.awaitIdentPos; + + this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); + this.initFunction(node); + if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } + + this.yieldPos = 0; + this.awaitPos = 0; + this.awaitIdentPos = 0; + + node.params = this.toAssignableList(params, true); + this.parseFunctionBody(node, true, false); + + this.yieldPos = oldYieldPos; + this.awaitPos = oldAwaitPos; + this.awaitIdentPos = oldAwaitIdentPos; + return this.finishNode(node, "ArrowFunctionExpression") + }; + + // Parse function body and check parameters. + + pp$3.parseFunctionBody = function(node, isArrowFunction, isMethod) { + var isExpression = isArrowFunction && this.type !== types.braceL; + var oldStrict = this.strict, useStrict = false; + + if (isExpression) { + node.body = this.parseMaybeAssign(); + node.expression = true; + this.checkParams(node, false); + } else { + var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); + if (!oldStrict || nonSimple) { + useStrict = this.strictDirective(this.end); + // If this is a strict mode function, verify that argument names + // are not repeated, and it does not try to bind the words `eval` + // or `arguments`. + if (useStrict && nonSimple) + { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } } + // Start a new scope with regard to labels and the `inFunction` + // flag (restore them to their old value afterwards). + var oldLabels = this.labels; + this.labels = []; + if (useStrict) { this.strict = true; } + + // Add the params to varDeclaredNames to ensure that an error is thrown + // if a let/const declaration in the function clashes with one of the params. + this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && !isMethod && this.isSimpleParamList(node.params)); + node.body = this.parseBlock(false); + node.expression = false; + this.adaptDirectivePrologue(node.body.body); + this.labels = oldLabels; } - var innerEndPos = this.start, innerEndLoc = this.startLoc; - this.expect(types.parenR); + this.exitScope(); - if (canBeArrow && !this.canInsertSemicolon() && this.eat(types.arrow)) { - this.checkPatternErrors(refDestructuringErrors, false); - this.checkYieldAwaitInDefaultParams(); - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.parseParenArrowList(startPos, startLoc, exprList) - } + // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' + if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); } + this.strict = oldStrict; + }; - if (!exprList.length || lastIsComma) { this.unexpected(this.lastTokStart); } - if (spreadStart) { this.unexpected(spreadStart); } - this.checkExpressionErrors(refDestructuringErrors, true); - this.yieldPos = oldYieldPos || this.yieldPos; - this.awaitPos = oldAwaitPos || this.awaitPos; + pp$3.isSimpleParamList = function(params) { + for (var i = 0, list = params; i < list.length; i += 1) + { + var param = list[i]; - if (exprList.length > 1) { - val = this.startNodeAt(innerStartPos, innerStartLoc); - val.expressions = exprList; - this.finishNodeAt(val, "SequenceExpression", innerEndPos, innerEndLoc); - } else { - val = exprList[0]; - } - } else { - val = this.parseParenExpression(); - } - - if (this.options.preserveParens) { - var par = this.startNodeAt(startPos, startLoc); - par.expression = val; - return this.finishNode(par, "ParenthesizedExpression") - } else { - return val - } -}; - -pp$3.parseParenItem = function(item) { - return item -}; - -pp$3.parseParenArrowList = function(startPos, startLoc, exprList) { - return this.parseArrowExpression(this.startNodeAt(startPos, startLoc), exprList) -}; - -// New's precedence is slightly tricky. It must allow its argument to -// be a `[]` or dot subscript expression, but not a call — at least, -// not without wrapping it in parentheses. Thus, it uses the noCalls -// argument to parseSubscripts to prevent it from consuming the -// argument list. - -var empty$1 = []; - -pp$3.parseNew = function() { - var node = this.startNode(); - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(types.dot)) { - node.meta = meta; - var containsEsc = this.containsEsc; - node.property = this.parseIdent(true); - if (node.property.name !== "target" || containsEsc) - { this.raiseRecoverable(node.property.start, "The only valid meta property for new is new.target"); } - if (!this.inNonArrowFunction()) - { this.raiseRecoverable(node.start, "new.target can only be used in functions"); } - return this.finishNode(node, "MetaProperty") - } - var startPos = this.start, startLoc = this.startLoc; - node.callee = this.parseSubscripts(this.parseExprAtom(), startPos, startLoc, true); - if (this.eat(types.parenL)) { node.arguments = this.parseExprList(types.parenR, this.options.ecmaVersion >= 8, false); } - else { node.arguments = empty$1; } - return this.finishNode(node, "NewExpression") -}; - -// Parse template expression. - -pp$3.parseTemplateElement = function(ref) { - var isTagged = ref.isTagged; - - var elem = this.startNode(); - if (this.type === types.invalidTemplate) { - if (!isTagged) { - this.raiseRecoverable(this.start, "Bad escape sequence in untagged template literal"); - } - elem.value = { - raw: this.value, - cooked: null - }; - } else { - elem.value = { - raw: this.input.slice(this.start, this.end).replace(/\r\n?/g, "\n"), - cooked: this.value - }; - } - this.next(); - elem.tail = this.type === types.backQuote; - return this.finishNode(elem, "TemplateElement") -}; - -pp$3.parseTemplate = function(ref) { - var this$1 = this; - if ( ref === void 0 ) ref = {}; - var isTagged = ref.isTagged; if ( isTagged === void 0 ) isTagged = false; - - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement({isTagged: isTagged}); - node.quasis = [curElt]; - while (!curElt.tail) { - if (this$1.type === types.eof) { this$1.raise(this$1.pos, "Unterminated template literal"); } - this$1.expect(types.dollarBraceL); - node.expressions.push(this$1.parseExpression()); - this$1.expect(types.braceR); - node.quasis.push(curElt = this$1.parseTemplateElement({isTagged: isTagged})); - } - this.next(); - return this.finishNode(node, "TemplateLiteral") -}; - -pp$3.isAsyncProp = function(prop) { - return !prop.computed && prop.key.type === "Identifier" && prop.key.name === "async" && - (this.type === types.name || this.type === types.num || this.type === types.string || this.type === types.bracketL || this.type.keyword || (this.options.ecmaVersion >= 9 && this.type === types.star)) && - !lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) -}; - -// Parse an object literal or binding pattern. - -pp$3.parseObj = function(isPattern, refDestructuringErrors) { - var this$1 = this; - - var node = this.startNode(), first = true, propHash = {}; - node.properties = []; - this.next(); - while (!this.eat(types.braceR)) { - if (!first) { - this$1.expect(types.comma); - if (this$1.afterTrailingComma(types.braceR)) { break } - } else { first = false; } - - var prop = this$1.parseProperty(isPattern, refDestructuringErrors); - if (!isPattern) { this$1.checkPropClash(prop, propHash, refDestructuringErrors); } - node.properties.push(prop); - } - return this.finishNode(node, isPattern ? "ObjectPattern" : "ObjectExpression") -}; - -pp$3.parseProperty = function(isPattern, refDestructuringErrors) { - var prop = this.startNode(), isGenerator, isAsync, startPos, startLoc; - if (this.options.ecmaVersion >= 9 && this.eat(types.ellipsis)) { - if (isPattern) { - prop.argument = this.parseIdent(false); - if (this.type === types.comma) { - this.raise(this.start, "Comma is not permitted after the rest element"); - } - return this.finishNode(prop, "RestElement") - } - // To disallow parenthesized identifier via `this.toAssignable()`. - if (this.type === types.parenL && refDestructuringErrors) { - if (refDestructuringErrors.parenthesizedAssign < 0) { - refDestructuringErrors.parenthesizedAssign = this.start; - } - if (refDestructuringErrors.parenthesizedBind < 0) { - refDestructuringErrors.parenthesizedBind = this.start; - } - } - // Parse argument. - prop.argument = this.parseMaybeAssign(false, refDestructuringErrors); - // To disallow trailing comma via `this.toAssignable()`. - if (this.type === types.comma && refDestructuringErrors && refDestructuringErrors.trailingComma < 0) { - refDestructuringErrors.trailingComma = this.start; - } - // Finish - return this.finishNode(prop, "SpreadElement") - } - if (this.options.ecmaVersion >= 6) { - prop.method = false; - prop.shorthand = false; - if (isPattern || refDestructuringErrors) { - startPos = this.start; - startLoc = this.startLoc; - } - if (!isPattern) - { isGenerator = this.eat(types.star); } - } - var containsEsc = this.containsEsc; - this.parsePropertyName(prop); - if (!isPattern && !containsEsc && this.options.ecmaVersion >= 8 && !isGenerator && this.isAsyncProp(prop)) { - isAsync = true; - isGenerator = this.options.ecmaVersion >= 9 && this.eat(types.star); - this.parsePropertyName(prop, refDestructuringErrors); - } else { - isAsync = false; - } - this.parsePropertyValue(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc); - return this.finishNode(prop, "Property") -}; - -pp$3.parsePropertyValue = function(prop, isPattern, isGenerator, isAsync, startPos, startLoc, refDestructuringErrors, containsEsc) { - if ((isGenerator || isAsync) && this.type === types.colon) - { this.unexpected(); } - - if (this.eat(types.colon)) { - prop.value = isPattern ? this.parseMaybeDefault(this.start, this.startLoc) : this.parseMaybeAssign(false, refDestructuringErrors); - prop.kind = "init"; - } else if (this.options.ecmaVersion >= 6 && this.type === types.parenL) { - if (isPattern) { this.unexpected(); } - prop.kind = "init"; - prop.method = true; - prop.value = this.parseMethod(isGenerator, isAsync); - } else if (!isPattern && !containsEsc && - this.options.ecmaVersion >= 5 && !prop.computed && prop.key.type === "Identifier" && - (prop.key.name === "get" || prop.key.name === "set") && - (this.type !== types.comma && this.type !== types.braceR)) { - if (isGenerator || isAsync) { this.unexpected(); } - prop.kind = prop.key.name; - this.parsePropertyName(prop); - prop.value = this.parseMethod(false); - var paramCount = prop.kind === "get" ? 0 : 1; - if (prop.value.params.length !== paramCount) { - var start = prop.value.start; - if (prop.kind === "get") - { this.raiseRecoverable(start, "getter should have no params"); } - else - { this.raiseRecoverable(start, "setter should have exactly one param"); } - } else { - if (prop.kind === "set" && prop.value.params[0].type === "RestElement") - { this.raiseRecoverable(prop.value.params[0].start, "Setter cannot use rest params"); } - } - } else if (this.options.ecmaVersion >= 6 && !prop.computed && prop.key.type === "Identifier") { - this.checkUnreserved(prop.key); - prop.kind = "init"; - if (isPattern) { - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else if (this.type === types.eq && refDestructuringErrors) { - if (refDestructuringErrors.shorthandAssign < 0) - { refDestructuringErrors.shorthandAssign = this.start; } - prop.value = this.parseMaybeDefault(startPos, startLoc, prop.key); - } else { - prop.value = prop.key; - } - prop.shorthand = true; - } else { this.unexpected(); } -}; - -pp$3.parsePropertyName = function(prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(types.bracketL)) { - prop.computed = true; - prop.key = this.parseMaybeAssign(); - this.expect(types.bracketR); - return prop.key - } else { - prop.computed = false; - } - } - return prop.key = this.type === types.num || this.type === types.string ? this.parseExprAtom() : this.parseIdent(true) -}; - -// Initialize empty function node. - -pp$3.initFunction = function(node) { - node.id = null; - if (this.options.ecmaVersion >= 6) { node.generator = node.expression = false; } - if (this.options.ecmaVersion >= 8) { node.async = false; } -}; - -// Parse object or class method. - -pp$3.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos; - - this.initFunction(node); - if (this.options.ecmaVersion >= 6) - { node.generator = isGenerator; } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - - this.yieldPos = 0; - this.awaitPos = 0; - this.enterScope(functionFlags(isAsync, node.generator)); - - this.expect(types.parenL); - node.params = this.parseBindingList(types.parenR, false, this.options.ecmaVersion >= 8); - this.checkYieldAwaitInDefaultParams(); - this.parseFunctionBody(node, false); - - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.finishNode(node, "FunctionExpression") -}; - -// Parse arrow function expression with given parameters. - -pp$3.parseArrowExpression = function(node, params, isAsync) { - var oldYieldPos = this.yieldPos, oldAwaitPos = this.awaitPos; - - this.enterScope(functionFlags(isAsync, false) | SCOPE_ARROW); - this.initFunction(node); - if (this.options.ecmaVersion >= 8) { node.async = !!isAsync; } - - this.yieldPos = 0; - this.awaitPos = 0; - - node.params = this.toAssignableList(params, true); - this.parseFunctionBody(node, true); - - this.yieldPos = oldYieldPos; - this.awaitPos = oldAwaitPos; - return this.finishNode(node, "ArrowFunctionExpression") -}; - -// Parse function body and check parameters. - -pp$3.parseFunctionBody = function(node, isArrowFunction) { - var isExpression = isArrowFunction && this.type !== types.braceL; - var oldStrict = this.strict, useStrict = false; - - if (isExpression) { - node.body = this.parseMaybeAssign(); - node.expression = true; - this.checkParams(node, false); - } else { - var nonSimple = this.options.ecmaVersion >= 7 && !this.isSimpleParamList(node.params); - if (!oldStrict || nonSimple) { - useStrict = this.strictDirective(this.end); - // If this is a strict mode function, verify that argument names - // are not repeated, and it does not try to bind the words `eval` - // or `arguments`. - if (useStrict && nonSimple) - { this.raiseRecoverable(node.start, "Illegal 'use strict' directive in function with non-simple parameter list"); } - } - // Start a new scope with regard to labels and the `inFunction` - // flag (restore them to their old value afterwards). - var oldLabels = this.labels; - this.labels = []; - if (useStrict) { this.strict = true; } - - // Add the params to varDeclaredNames to ensure that an error is thrown - // if a let/const declaration in the function clashes with one of the params. - this.checkParams(node, !oldStrict && !useStrict && !isArrowFunction && this.isSimpleParamList(node.params)); - node.body = this.parseBlock(false); - node.expression = false; - this.adaptDirectivePrologue(node.body.body); - this.labels = oldLabels; - } - this.exitScope(); - - // Ensure the function name isn't a forbidden identifier in strict mode, e.g. 'eval' - if (this.strict && node.id) { this.checkLVal(node.id, BIND_OUTSIDE); } - this.strict = oldStrict; -}; - -pp$3.isSimpleParamList = function(params) { - for (var i = 0, list = params; i < list.length; i += 1) - { - var param = list[i]; - - if (param.type !== "Identifier") { return false - } } - return true -}; - -// Checks function params for various disallowed patterns such as using "eval" -// or "arguments" and duplicate parameters. - -pp$3.checkParams = function(node, allowDuplicates) { - var this$1 = this; - - var nameHash = {}; - for (var i = 0, list = node.params; i < list.length; i += 1) - { - var param = list[i]; - - this$1.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash); - } -}; - -// Parses a comma-separated list of expressions, and returns them as -// an array. `close` is the token type that ends the list, and -// `allowEmpty` can be turned on to allow subsequent commas with -// nothing in between them to be parsed as `null` (which is needed -// for array literals). - -pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { - var this$1 = this; - - var elts = [], first = true; - while (!this.eat(close)) { - if (!first) { - this$1.expect(types.comma); - if (allowTrailingComma && this$1.afterTrailingComma(close)) { break } - } else { first = false; } - - var elt = (void 0); - if (allowEmpty && this$1.type === types.comma) - { elt = null; } - else if (this$1.type === types.ellipsis) { - elt = this$1.parseSpread(refDestructuringErrors); - if (refDestructuringErrors && this$1.type === types.comma && refDestructuringErrors.trailingComma < 0) - { refDestructuringErrors.trailingComma = this$1.start; } - } else { - elt = this$1.parseMaybeAssign(false, refDestructuringErrors); - } - elts.push(elt); - } - return elts -}; - -pp$3.checkUnreserved = function(ref) { - var start = ref.start; - var end = ref.end; - var name = ref.name; - - if (this.inGenerator && name === "yield") - { this.raiseRecoverable(start, "Can not use 'yield' as identifier inside a generator"); } - if (this.inAsync && name === "await") - { this.raiseRecoverable(start, "Can not use 'await' as identifier inside an async function"); } - if (this.keywords.test(name)) - { this.raise(start, ("Unexpected keyword '" + name + "'")); } - if (this.options.ecmaVersion < 6 && - this.input.slice(start, end).indexOf("\\") !== -1) { return } - var re = this.strict ? this.reservedWordsStrict : this.reservedWords; - if (re.test(name)) { - if (!this.inAsync && name === "await") - { this.raiseRecoverable(start, "Can not use keyword 'await' outside an async function"); } - this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); - } -}; - -// Parse the next token as an identifier. If `liberal` is true (used -// when parsing properties), it will also convert keywords into -// identifiers. - -pp$3.parseIdent = function(liberal, isBinding) { - var node = this.startNode(); - if (liberal && this.options.allowReserved === "never") { liberal = false; } - if (this.type === types.name) { - node.name = this.value; - } else if (this.type.keyword) { - node.name = this.type.keyword; - - // To fix https://github.com/acornjs/acorn/issues/575 - // `class` and `function` keywords push new context into this.context. - // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. - // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword - if ((node.name === "class" || node.name === "function") && - (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { - this.context.pop(); - } - } else { - this.unexpected(); - } - this.next(); - this.finishNode(node, "Identifier"); - if (!liberal) { this.checkUnreserved(node); } - return node -}; - -// Parses yield expression inside generator. - -pp$3.parseYield = function() { - if (!this.yieldPos) { this.yieldPos = this.start; } - - var node = this.startNode(); - this.next(); - if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(types.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression") -}; - -pp$3.parseAwait = function() { - if (!this.awaitPos) { this.awaitPos = this.start; } - - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeUnary(null, true); - return this.finishNode(node, "AwaitExpression") -}; - -var pp$4 = Parser.prototype; - -// This function is used to raise exceptions on parse errors. It -// takes an offset integer (into the current `input`) to indicate -// the location of the error, attaches the position to the end -// of the error message, and then raises a `SyntaxError` with that -// message. - -pp$4.raise = function(pos, message) { - var loc = getLineInfo(this.input, pos); - message += " (" + loc.line + ":" + loc.column + ")"; - var err = new SyntaxError(message); - err.pos = pos; err.loc = loc; err.raisedAt = this.pos; - throw err -}; - -pp$4.raiseRecoverable = pp$4.raise; - -pp$4.curPosition = function() { - if (this.options.locations) { - return new Position(this.curLine, this.pos - this.lineStart) - } -}; - -var pp$5 = Parser.prototype; - -var Scope = function Scope(flags) { - this.flags = flags; - // A list of var-declared names in the current lexical scope - this.var = []; - // A list of lexically-declared names in the current lexical scope - this.lexical = []; -}; - -// The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. - -pp$5.enterScope = function(flags) { - this.scopeStack.push(new Scope(flags)); -}; - -pp$5.exitScope = function() { - this.scopeStack.pop(); -}; - -pp$5.declareName = function(name, bindingType, pos) { - var this$1 = this; - - var redeclared = false; - if (bindingType === BIND_LEXICAL) { - var scope = this.currentScope(); - redeclared = scope.lexical.indexOf(name) > -1 || scope.var.indexOf(name) > -1; - scope.lexical.push(name); - } else if (bindingType === BIND_SIMPLE_CATCH) { - var scope$1 = this.currentScope(); - scope$1.lexical.push(name); - } else if (bindingType === BIND_FUNCTION) { - var scope$2 = this.currentScope(); - redeclared = scope$2.lexical.indexOf(name) > -1; - scope$2.var.push(name); - } else { - for (var i = this.scopeStack.length - 1; i >= 0; --i) { - var scope$3 = this$1.scopeStack[i]; - if (scope$3.lexical.indexOf(name) > -1 && !(scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) { redeclared = true; } - scope$3.var.push(name); - if (scope$3.flags & SCOPE_VAR) { break } - } - } - if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } -}; - -pp$5.currentScope = function() { - return this.scopeStack[this.scopeStack.length - 1] -}; - -pp$5.currentVarScope = function() { - var this$1 = this; - - for (var i = this.scopeStack.length - 1;; i--) { - var scope = this$1.scopeStack[i]; - if (scope.flags & SCOPE_VAR) { return scope } - } -}; - -pp$5.inNonArrowFunction = function() { - var this$1 = this; - - for (var i = this.scopeStack.length - 1; i >= 0; i--) - { if (this$1.scopeStack[i].flags & SCOPE_FUNCTION && !(this$1.scopeStack[i].flags & SCOPE_ARROW)) { return true } } - return false -}; - -var Node = function Node(parser, pos, loc) { - this.type = ""; - this.start = pos; - this.end = 0; - if (parser.options.locations) - { this.loc = new SourceLocation(parser, loc); } - if (parser.options.directSourceFile) - { this.sourceFile = parser.options.directSourceFile; } - if (parser.options.ranges) - { this.range = [pos, 0]; } -}; - -// Start an AST node, attaching a start offset. - -var pp$6 = Parser.prototype; - -pp$6.startNode = function() { - return new Node(this, this.start, this.startLoc) -}; - -pp$6.startNodeAt = function(pos, loc) { - return new Node(this, pos, loc) -}; - -// Finish an AST node, adding `type` and `end` properties. - -function finishNodeAt(node, type, pos, loc) { - node.type = type; - node.end = pos; - if (this.options.locations) - { node.loc.end = loc; } - if (this.options.ranges) - { node.range[1] = pos; } - return node -} - -pp$6.finishNode = function(node, type) { - return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) -}; - -// Finish node at given position - -pp$6.finishNodeAt = function(node, type, pos, loc) { - return finishNodeAt.call(this, node, type, pos, loc) -}; - -// The algorithm used to determine whether a regexp can appear at a -// given point in the program is loosely based on sweet.js' approach. -// See https://github.com/mozilla/sweet.js/wiki/design - -var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { - this.token = token; - this.isExpr = !!isExpr; - this.preserveSpace = !!preserveSpace; - this.override = override; - this.generator = !!generator; -}; - -var types$1 = { - b_stat: new TokContext("{", false), - b_expr: new TokContext("{", true), - b_tmpl: new TokContext("${", false), - p_stat: new TokContext("(", false), - p_expr: new TokContext("(", true), - q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), - f_stat: new TokContext("function", false), - f_expr: new TokContext("function", true), - f_expr_gen: new TokContext("function", true, false, null, true), - f_gen: new TokContext("function", false, false, null, true) -}; - -var pp$7 = Parser.prototype; - -pp$7.initialContext = function() { - return [types$1.b_stat] -}; - -pp$7.braceIsBlock = function(prevType) { - var parent = this.curContext(); - if (parent === types$1.f_expr || parent === types$1.f_stat) - { return true } - if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) - { return !parent.isExpr } - - // The check for `tt.name && exprAllowed` detects whether we are - // after a `yield` or `of` construct. See the `updateContext` for - // `tt.name`. - if (prevType === types._return || prevType === types.name && this.exprAllowed) - { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } - if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow) - { return true } - if (prevType === types.braceL) - { return parent === types$1.b_stat } - if (prevType === types._var || prevType === types.name) - { return false } - return !this.exprAllowed -}; - -pp$7.inGeneratorContext = function() { - var this$1 = this; - - for (var i = this.context.length - 1; i >= 1; i--) { - var context = this$1.context[i]; - if (context.token === "function") - { return context.generator } - } - return false -}; - -pp$7.updateContext = function(prevType) { - var update, type = this.type; - if (type.keyword && prevType === types.dot) - { this.exprAllowed = false; } - else if (update = type.updateContext) - { update.call(this, prevType); } - else - { this.exprAllowed = type.beforeExpr; } -}; - -// Token-specific context update code - -types.parenR.updateContext = types.braceR.updateContext = function() { - if (this.context.length === 1) { - this.exprAllowed = true; - return - } - var out = this.context.pop(); - if (out === types$1.b_stat && this.curContext().token === "function") { - out = this.context.pop(); - } - this.exprAllowed = !out.isExpr; -}; - -types.braceL.updateContext = function(prevType) { - this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); - this.exprAllowed = true; -}; - -types.dollarBraceL.updateContext = function() { - this.context.push(types$1.b_tmpl); - this.exprAllowed = true; -}; - -types.parenL.updateContext = function(prevType) { - var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; - this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); - this.exprAllowed = true; -}; - -types.incDec.updateContext = function() { - // tokExprAllowed stays unchanged -}; - -types._function.updateContext = types._class.updateContext = function(prevType) { - if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && - !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) - { this.context.push(types$1.f_expr); } - else - { this.context.push(types$1.f_stat); } - this.exprAllowed = false; -}; - -types.backQuote.updateContext = function() { - if (this.curContext() === types$1.q_tmpl) - { this.context.pop(); } - else - { this.context.push(types$1.q_tmpl); } - this.exprAllowed = false; -}; - -types.star.updateContext = function(prevType) { - if (prevType === types._function) { - var index = this.context.length - 1; - if (this.context[index] === types$1.f_expr) - { this.context[index] = types$1.f_expr_gen; } - else - { this.context[index] = types$1.f_gen; } - } - this.exprAllowed = true; -}; - -types.name.updateContext = function(prevType) { - var allowed = false; - if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { - if (this.value === "of" && !this.exprAllowed || - this.value === "yield" && this.inGeneratorContext()) - { allowed = true; } - } - this.exprAllowed = allowed; -}; - -var data = { - "$LONE": [ - "ASCII", - "ASCII_Hex_Digit", - "AHex", - "Alphabetic", - "Alpha", - "Any", - "Assigned", - "Bidi_Control", - "Bidi_C", - "Bidi_Mirrored", - "Bidi_M", - "Case_Ignorable", - "CI", - "Cased", - "Changes_When_Casefolded", - "CWCF", - "Changes_When_Casemapped", - "CWCM", - "Changes_When_Lowercased", - "CWL", - "Changes_When_NFKC_Casefolded", - "CWKCF", - "Changes_When_Titlecased", - "CWT", - "Changes_When_Uppercased", - "CWU", - "Dash", - "Default_Ignorable_Code_Point", - "DI", - "Deprecated", - "Dep", - "Diacritic", - "Dia", - "Emoji", - "Emoji_Component", - "Emoji_Modifier", - "Emoji_Modifier_Base", - "Emoji_Presentation", - "Extender", - "Ext", - "Grapheme_Base", - "Gr_Base", - "Grapheme_Extend", - "Gr_Ext", - "Hex_Digit", - "Hex", - "IDS_Binary_Operator", - "IDSB", - "IDS_Trinary_Operator", - "IDST", - "ID_Continue", - "IDC", - "ID_Start", - "IDS", - "Ideographic", - "Ideo", - "Join_Control", - "Join_C", - "Logical_Order_Exception", - "LOE", - "Lowercase", - "Lower", - "Math", - "Noncharacter_Code_Point", - "NChar", - "Pattern_Syntax", - "Pat_Syn", - "Pattern_White_Space", - "Pat_WS", - "Quotation_Mark", - "QMark", - "Radical", - "Regional_Indicator", - "RI", - "Sentence_Terminal", - "STerm", - "Soft_Dotted", - "SD", - "Terminal_Punctuation", - "Term", - "Unified_Ideograph", - "UIdeo", - "Uppercase", - "Upper", - "Variation_Selector", - "VS", - "White_Space", - "space", - "XID_Continue", - "XIDC", - "XID_Start", - "XIDS" - ], - "General_Category": [ - "Cased_Letter", - "LC", - "Close_Punctuation", - "Pe", - "Connector_Punctuation", - "Pc", - "Control", - "Cc", - "cntrl", - "Currency_Symbol", - "Sc", - "Dash_Punctuation", - "Pd", - "Decimal_Number", - "Nd", - "digit", - "Enclosing_Mark", - "Me", - "Final_Punctuation", - "Pf", - "Format", - "Cf", - "Initial_Punctuation", - "Pi", - "Letter", - "L", - "Letter_Number", - "Nl", - "Line_Separator", - "Zl", - "Lowercase_Letter", - "Ll", - "Mark", - "M", - "Combining_Mark", - "Math_Symbol", - "Sm", - "Modifier_Letter", - "Lm", - "Modifier_Symbol", - "Sk", - "Nonspacing_Mark", - "Mn", - "Number", - "N", - "Open_Punctuation", - "Ps", - "Other", - "C", - "Other_Letter", - "Lo", - "Other_Number", - "No", - "Other_Punctuation", - "Po", - "Other_Symbol", - "So", - "Paragraph_Separator", - "Zp", - "Private_Use", - "Co", - "Punctuation", - "P", - "punct", - "Separator", - "Z", - "Space_Separator", - "Zs", - "Spacing_Mark", - "Mc", - "Surrogate", - "Cs", - "Symbol", - "S", - "Titlecase_Letter", - "Lt", - "Unassigned", - "Cn", - "Uppercase_Letter", - "Lu" - ], - "Script": [ - "Adlam", - "Adlm", - "Ahom", - "Anatolian_Hieroglyphs", - "Hluw", - "Arabic", - "Arab", - "Armenian", - "Armn", - "Avestan", - "Avst", - "Balinese", - "Bali", - "Bamum", - "Bamu", - "Bassa_Vah", - "Bass", - "Batak", - "Batk", - "Bengali", - "Beng", - "Bhaiksuki", - "Bhks", - "Bopomofo", - "Bopo", - "Brahmi", - "Brah", - "Braille", - "Brai", - "Buginese", - "Bugi", - "Buhid", - "Buhd", - "Canadian_Aboriginal", - "Cans", - "Carian", - "Cari", - "Caucasian_Albanian", - "Aghb", - "Chakma", - "Cakm", - "Cham", - "Cherokee", - "Cher", - "Common", - "Zyyy", - "Coptic", - "Copt", - "Qaac", - "Cuneiform", - "Xsux", - "Cypriot", - "Cprt", - "Cyrillic", - "Cyrl", - "Deseret", - "Dsrt", - "Devanagari", - "Deva", - "Duployan", - "Dupl", - "Egyptian_Hieroglyphs", - "Egyp", - "Elbasan", - "Elba", - "Ethiopic", - "Ethi", - "Georgian", - "Geor", - "Glagolitic", - "Glag", - "Gothic", - "Goth", - "Grantha", - "Gran", - "Greek", - "Grek", - "Gujarati", - "Gujr", - "Gurmukhi", - "Guru", - "Han", - "Hani", - "Hangul", - "Hang", - "Hanunoo", - "Hano", - "Hatran", - "Hatr", - "Hebrew", - "Hebr", - "Hiragana", - "Hira", - "Imperial_Aramaic", - "Armi", - "Inherited", - "Zinh", - "Qaai", - "Inscriptional_Pahlavi", - "Phli", - "Inscriptional_Parthian", - "Prti", - "Javanese", - "Java", - "Kaithi", - "Kthi", - "Kannada", - "Knda", - "Katakana", - "Kana", - "Kayah_Li", - "Kali", - "Kharoshthi", - "Khar", - "Khmer", - "Khmr", - "Khojki", - "Khoj", - "Khudawadi", - "Sind", - "Lao", - "Laoo", - "Latin", - "Latn", - "Lepcha", - "Lepc", - "Limbu", - "Limb", - "Linear_A", - "Lina", - "Linear_B", - "Linb", - "Lisu", - "Lycian", - "Lyci", - "Lydian", - "Lydi", - "Mahajani", - "Mahj", - "Malayalam", - "Mlym", - "Mandaic", - "Mand", - "Manichaean", - "Mani", - "Marchen", - "Marc", - "Masaram_Gondi", - "Gonm", - "Meetei_Mayek", - "Mtei", - "Mende_Kikakui", - "Mend", - "Meroitic_Cursive", - "Merc", - "Meroitic_Hieroglyphs", - "Mero", - "Miao", - "Plrd", - "Modi", - "Mongolian", - "Mong", - "Mro", - "Mroo", - "Multani", - "Mult", - "Myanmar", - "Mymr", - "Nabataean", - "Nbat", - "New_Tai_Lue", - "Talu", - "Newa", - "Nko", - "Nkoo", - "Nushu", - "Nshu", - "Ogham", - "Ogam", - "Ol_Chiki", - "Olck", - "Old_Hungarian", - "Hung", - "Old_Italic", - "Ital", - "Old_North_Arabian", - "Narb", - "Old_Permic", - "Perm", - "Old_Persian", - "Xpeo", - "Old_South_Arabian", - "Sarb", - "Old_Turkic", - "Orkh", - "Oriya", - "Orya", - "Osage", - "Osge", - "Osmanya", - "Osma", - "Pahawh_Hmong", - "Hmng", - "Palmyrene", - "Palm", - "Pau_Cin_Hau", - "Pauc", - "Phags_Pa", - "Phag", - "Phoenician", - "Phnx", - "Psalter_Pahlavi", - "Phlp", - "Rejang", - "Rjng", - "Runic", - "Runr", - "Samaritan", - "Samr", - "Saurashtra", - "Saur", - "Sharada", - "Shrd", - "Shavian", - "Shaw", - "Siddham", - "Sidd", - "SignWriting", - "Sgnw", - "Sinhala", - "Sinh", - "Sora_Sompeng", - "Sora", - "Soyombo", - "Soyo", - "Sundanese", - "Sund", - "Syloti_Nagri", - "Sylo", - "Syriac", - "Syrc", - "Tagalog", - "Tglg", - "Tagbanwa", - "Tagb", - "Tai_Le", - "Tale", - "Tai_Tham", - "Lana", - "Tai_Viet", - "Tavt", - "Takri", - "Takr", - "Tamil", - "Taml", - "Tangut", - "Tang", - "Telugu", - "Telu", - "Thaana", - "Thaa", - "Thai", - "Tibetan", - "Tibt", - "Tifinagh", - "Tfng", - "Tirhuta", - "Tirh", - "Ugaritic", - "Ugar", - "Vai", - "Vaii", - "Warang_Citi", - "Wara", - "Yi", - "Yiii", - "Zanabazar_Square", - "Zanb" - ] -}; -Array.prototype.push.apply(data.$LONE, data.General_Category); -data.gc = data.General_Category; -data.sc = data.Script_Extensions = data.scx = data.Script; - -var pp$9 = Parser.prototype; - -var RegExpValidationState = function RegExpValidationState(parser) { - this.parser = parser; - this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : ""); - this.source = ""; - this.flags = ""; - this.start = 0; - this.switchU = false; - this.switchN = false; - this.pos = 0; - this.lastIntValue = 0; - this.lastStringValue = ""; - this.lastAssertionIsQuantifiable = false; - this.numCapturingParens = 0; - this.maxBackReference = 0; - this.groupNames = []; - this.backReferenceNames = []; -}; - -RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { - var unicode = flags.indexOf("u") !== -1; - this.start = start | 0; - this.source = pattern + ""; - this.flags = flags; - this.switchU = unicode && this.parser.options.ecmaVersion >= 6; - this.switchN = unicode && this.parser.options.ecmaVersion >= 9; -}; - -RegExpValidationState.prototype.raise = function raise (message) { - this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); -}; - -// If u flag is given, this returns the code point at the index (it combines a surrogate pair). -// Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). -RegExpValidationState.prototype.at = function at (i) { - var s = this.source; - var l = s.length; - if (i >= l) { - return -1 - } - var c = s.charCodeAt(i); - if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { - return c - } - return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 -}; - -RegExpValidationState.prototype.nextIndex = function nextIndex (i) { - var s = this.source; - var l = s.length; - if (i >= l) { - return l - } - var c = s.charCodeAt(i); - if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { - return i + 1 - } - return i + 2 -}; - -RegExpValidationState.prototype.current = function current () { - return this.at(this.pos) -}; - -RegExpValidationState.prototype.lookahead = function lookahead () { - return this.at(this.nextIndex(this.pos)) -}; - -RegExpValidationState.prototype.advance = function advance () { - this.pos = this.nextIndex(this.pos); -}; - -RegExpValidationState.prototype.eat = function eat (ch) { - if (this.current() === ch) { - this.advance(); + if (param.type !== "Identifier") { return false + } } return true - } - return false -}; + }; -function codePointToString$1(ch) { - if (ch <= 0xFFFF) { return String.fromCharCode(ch) } - ch -= 0x10000; - return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) -} + // Checks function params for various disallowed patterns such as using "eval" + // or "arguments" and duplicate parameters. -/** - * Validate the flags part of a given RegExpLiteral. - * - * @param {RegExpValidationState} state The state to validate RegExp. - * @returns {void} - */ -pp$9.validateRegExpFlags = function(state) { - var this$1 = this; + pp$3.checkParams = function(node, allowDuplicates) { + var nameHash = {}; + for (var i = 0, list = node.params; i < list.length; i += 1) + { + var param = list[i]; - var validFlags = state.validFlags; - var flags = state.flags; - - for (var i = 0; i < flags.length; i++) { - var flag = flags.charAt(i); - if (validFlags.indexOf(flag) === -1) { - this$1.raise(state.start, "Invalid regular expression flag"); + this.checkLVal(param, BIND_VAR, allowDuplicates ? null : nameHash); } - if (flags.indexOf(flag, i + 1) > -1) { - this$1.raise(state.start, "Duplicate regular expression flag"); + }; + + // Parses a comma-separated list of expressions, and returns them as + // an array. `close` is the token type that ends the list, and + // `allowEmpty` can be turned on to allow subsequent commas with + // nothing in between them to be parsed as `null` (which is needed + // for array literals). + + pp$3.parseExprList = function(close, allowTrailingComma, allowEmpty, refDestructuringErrors) { + var elts = [], first = true; + while (!this.eat(close)) { + if (!first) { + this.expect(types.comma); + if (allowTrailingComma && this.afterTrailingComma(close)) { break } + } else { first = false; } + + var elt = (void 0); + if (allowEmpty && this.type === types.comma) + { elt = null; } + else if (this.type === types.ellipsis) { + elt = this.parseSpread(refDestructuringErrors); + if (refDestructuringErrors && this.type === types.comma && refDestructuringErrors.trailingComma < 0) + { refDestructuringErrors.trailingComma = this.start; } + } else { + elt = this.parseMaybeAssign(false, refDestructuringErrors); + } + elts.push(elt); } + return elts + }; + + pp$3.checkUnreserved = function(ref) { + var start = ref.start; + var end = ref.end; + var name = ref.name; + + if (this.inGenerator && name === "yield") + { this.raiseRecoverable(start, "Cannot use 'yield' as identifier inside a generator"); } + if (this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use 'await' as identifier inside an async function"); } + if (this.keywords.test(name)) + { this.raise(start, ("Unexpected keyword '" + name + "'")); } + if (this.options.ecmaVersion < 6 && + this.input.slice(start, end).indexOf("\\") !== -1) { return } + var re = this.strict ? this.reservedWordsStrict : this.reservedWords; + if (re.test(name)) { + if (!this.inAsync && name === "await") + { this.raiseRecoverable(start, "Cannot use keyword 'await' outside an async function"); } + this.raiseRecoverable(start, ("The keyword '" + name + "' is reserved")); + } + }; + + // Parse the next token as an identifier. If `liberal` is true (used + // when parsing properties), it will also convert keywords into + // identifiers. + + pp$3.parseIdent = function(liberal, isBinding) { + var node = this.startNode(); + if (this.type === types.name) { + node.name = this.value; + } else if (this.type.keyword) { + node.name = this.type.keyword; + + // To fix https://github.com/acornjs/acorn/issues/575 + // `class` and `function` keywords push new context into this.context. + // But there is no chance to pop the context if the keyword is consumed as an identifier such as a property name. + // If the previous token is a dot, this does not apply because the context-managing code already ignored the keyword + if ((node.name === "class" || node.name === "function") && + (this.lastTokEnd !== this.lastTokStart + 1 || this.input.charCodeAt(this.lastTokStart) !== 46)) { + this.context.pop(); + } + } else { + this.unexpected(); + } + this.next(); + this.finishNode(node, "Identifier"); + if (!liberal) { + this.checkUnreserved(node); + if (node.name === "await" && !this.awaitIdentPos) + { this.awaitIdentPos = node.start; } + } + return node + }; + + // Parses yield expression inside generator. + + pp$3.parseYield = function(noIn) { + if (!this.yieldPos) { this.yieldPos = this.start; } + + var node = this.startNode(); + this.next(); + if (this.type === types.semi || this.canInsertSemicolon() || (this.type !== types.star && !this.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(types.star); + node.argument = this.parseMaybeAssign(noIn); + } + return this.finishNode(node, "YieldExpression") + }; + + pp$3.parseAwait = function() { + if (!this.awaitPos) { this.awaitPos = this.start; } + + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(null, true); + return this.finishNode(node, "AwaitExpression") + }; + + var pp$4 = Parser.prototype; + + // This function is used to raise exceptions on parse errors. It + // takes an offset integer (into the current `input`) to indicate + // the location of the error, attaches the position to the end + // of the error message, and then raises a `SyntaxError` with that + // message. + + pp$4.raise = function(pos, message) { + var loc = getLineInfo(this.input, pos); + message += " (" + loc.line + ":" + loc.column + ")"; + var err = new SyntaxError(message); + err.pos = pos; err.loc = loc; err.raisedAt = this.pos; + throw err + }; + + pp$4.raiseRecoverable = pp$4.raise; + + pp$4.curPosition = function() { + if (this.options.locations) { + return new Position(this.curLine, this.pos - this.lineStart) + } + }; + + var pp$5 = Parser.prototype; + + var Scope = function Scope(flags) { + this.flags = flags; + // A list of var-declared names in the current lexical scope + this.var = []; + // A list of lexically-declared names in the current lexical scope + this.lexical = []; + // A list of lexically-declared FunctionDeclaration names in the current lexical scope + this.functions = []; + }; + + // The functions in this module keep track of declared variables in the current scope in order to detect duplicate variable names. + + pp$5.enterScope = function(flags) { + this.scopeStack.push(new Scope(flags)); + }; + + pp$5.exitScope = function() { + this.scopeStack.pop(); + }; + + // The spec says: + // > At the top level of a function, or script, function declarations are + // > treated like var declarations rather than like lexical declarations. + pp$5.treatFunctionsAsVarInScope = function(scope) { + return (scope.flags & SCOPE_FUNCTION) || !this.inModule && (scope.flags & SCOPE_TOP) + }; + + pp$5.declareName = function(name, bindingType, pos) { + var redeclared = false; + if (bindingType === BIND_LEXICAL) { + var scope = this.currentScope(); + redeclared = scope.lexical.indexOf(name) > -1 || scope.functions.indexOf(name) > -1 || scope.var.indexOf(name) > -1; + scope.lexical.push(name); + if (this.inModule && (scope.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + } else if (bindingType === BIND_SIMPLE_CATCH) { + var scope$1 = this.currentScope(); + scope$1.lexical.push(name); + } else if (bindingType === BIND_FUNCTION) { + var scope$2 = this.currentScope(); + if (this.treatFunctionsAsVar) + { redeclared = scope$2.lexical.indexOf(name) > -1; } + else + { redeclared = scope$2.lexical.indexOf(name) > -1 || scope$2.var.indexOf(name) > -1; } + scope$2.functions.push(name); + } else { + for (var i = this.scopeStack.length - 1; i >= 0; --i) { + var scope$3 = this.scopeStack[i]; + if (scope$3.lexical.indexOf(name) > -1 && !((scope$3.flags & SCOPE_SIMPLE_CATCH) && scope$3.lexical[0] === name) || + !this.treatFunctionsAsVarInScope(scope$3) && scope$3.functions.indexOf(name) > -1) { + redeclared = true; + break + } + scope$3.var.push(name); + if (this.inModule && (scope$3.flags & SCOPE_TOP)) + { delete this.undefinedExports[name]; } + if (scope$3.flags & SCOPE_VAR) { break } + } + } + if (redeclared) { this.raiseRecoverable(pos, ("Identifier '" + name + "' has already been declared")); } + }; + + pp$5.checkLocalExport = function(id) { + // scope.functions must be empty as Module code is always strict. + if (this.scopeStack[0].lexical.indexOf(id.name) === -1 && + this.scopeStack[0].var.indexOf(id.name) === -1) { + this.undefinedExports[id.name] = id; + } + }; + + pp$5.currentScope = function() { + return this.scopeStack[this.scopeStack.length - 1] + }; + + pp$5.currentVarScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & SCOPE_VAR) { return scope } + } + }; + + // Could be useful for `this`, `new.target`, `super()`, `super.property`, and `super[property]`. + pp$5.currentThisScope = function() { + for (var i = this.scopeStack.length - 1;; i--) { + var scope = this.scopeStack[i]; + if (scope.flags & SCOPE_VAR && !(scope.flags & SCOPE_ARROW)) { return scope } + } + }; + + var Node = function Node(parser, pos, loc) { + this.type = ""; + this.start = pos; + this.end = 0; + if (parser.options.locations) + { this.loc = new SourceLocation(parser, loc); } + if (parser.options.directSourceFile) + { this.sourceFile = parser.options.directSourceFile; } + if (parser.options.ranges) + { this.range = [pos, 0]; } + }; + + // Start an AST node, attaching a start offset. + + var pp$6 = Parser.prototype; + + pp$6.startNode = function() { + return new Node(this, this.start, this.startLoc) + }; + + pp$6.startNodeAt = function(pos, loc) { + return new Node(this, pos, loc) + }; + + // Finish an AST node, adding `type` and `end` properties. + + function finishNodeAt(node, type, pos, loc) { + node.type = type; + node.end = pos; + if (this.options.locations) + { node.loc.end = loc; } + if (this.options.ranges) + { node.range[1] = pos; } + return node } -}; -/** - * Validate the pattern part of a given RegExpLiteral. - * - * @param {RegExpValidationState} state The state to validate RegExp. - * @returns {void} - */ -pp$9.validateRegExpPattern = function(state) { - this.regexp_pattern(state); + pp$6.finishNode = function(node, type) { + return finishNodeAt.call(this, node, type, this.lastTokEnd, this.lastTokEndLoc) + }; - // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of - // parsing contains a |GroupName|, reparse with the goal symbol - // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* - // exception if _P_ did not conform to the grammar, if any elements of _P_ - // were not matched by the parse, or if any Early Error conditions exist. - if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { - state.switchN = true; + // Finish node at given position + + pp$6.finishNodeAt = function(node, type, pos, loc) { + return finishNodeAt.call(this, node, type, pos, loc) + }; + + // The algorithm used to determine whether a regexp can appear at a + + var TokContext = function TokContext(token, isExpr, preserveSpace, override, generator) { + this.token = token; + this.isExpr = !!isExpr; + this.preserveSpace = !!preserveSpace; + this.override = override; + this.generator = !!generator; + }; + + var types$1 = { + b_stat: new TokContext("{", false), + b_expr: new TokContext("{", true), + b_tmpl: new TokContext("${", false), + p_stat: new TokContext("(", false), + p_expr: new TokContext("(", true), + q_tmpl: new TokContext("`", true, true, function (p) { return p.tryReadTemplateToken(); }), + f_stat: new TokContext("function", false), + f_expr: new TokContext("function", true), + f_expr_gen: new TokContext("function", true, false, null, true), + f_gen: new TokContext("function", false, false, null, true) + }; + + var pp$7 = Parser.prototype; + + pp$7.initialContext = function() { + return [types$1.b_stat] + }; + + pp$7.braceIsBlock = function(prevType) { + var parent = this.curContext(); + if (parent === types$1.f_expr || parent === types$1.f_stat) + { return true } + if (prevType === types.colon && (parent === types$1.b_stat || parent === types$1.b_expr)) + { return !parent.isExpr } + + // The check for `tt.name && exprAllowed` detects whether we are + // after a `yield` or `of` construct. See the `updateContext` for + // `tt.name`. + if (prevType === types._return || prevType === types.name && this.exprAllowed) + { return lineBreak.test(this.input.slice(this.lastTokEnd, this.start)) } + if (prevType === types._else || prevType === types.semi || prevType === types.eof || prevType === types.parenR || prevType === types.arrow) + { return true } + if (prevType === types.braceL) + { return parent === types$1.b_stat } + if (prevType === types._var || prevType === types._const || prevType === types.name) + { return false } + return !this.exprAllowed + }; + + pp$7.inGeneratorContext = function() { + for (var i = this.context.length - 1; i >= 1; i--) { + var context = this.context[i]; + if (context.token === "function") + { return context.generator } + } + return false + }; + + pp$7.updateContext = function(prevType) { + var update, type = this.type; + if (type.keyword && prevType === types.dot) + { this.exprAllowed = false; } + else if (update = type.updateContext) + { update.call(this, prevType); } + else + { this.exprAllowed = type.beforeExpr; } + }; + + // Token-specific context update code + + types.parenR.updateContext = types.braceR.updateContext = function() { + if (this.context.length === 1) { + this.exprAllowed = true; + return + } + var out = this.context.pop(); + if (out === types$1.b_stat && this.curContext().token === "function") { + out = this.context.pop(); + } + this.exprAllowed = !out.isExpr; + }; + + types.braceL.updateContext = function(prevType) { + this.context.push(this.braceIsBlock(prevType) ? types$1.b_stat : types$1.b_expr); + this.exprAllowed = true; + }; + + types.dollarBraceL.updateContext = function() { + this.context.push(types$1.b_tmpl); + this.exprAllowed = true; + }; + + types.parenL.updateContext = function(prevType) { + var statementParens = prevType === types._if || prevType === types._for || prevType === types._with || prevType === types._while; + this.context.push(statementParens ? types$1.p_stat : types$1.p_expr); + this.exprAllowed = true; + }; + + types.incDec.updateContext = function() { + // tokExprAllowed stays unchanged + }; + + types._function.updateContext = types._class.updateContext = function(prevType) { + if (prevType.beforeExpr && prevType !== types.semi && prevType !== types._else && + !(prevType === types._return && lineBreak.test(this.input.slice(this.lastTokEnd, this.start))) && + !((prevType === types.colon || prevType === types.braceL) && this.curContext() === types$1.b_stat)) + { this.context.push(types$1.f_expr); } + else + { this.context.push(types$1.f_stat); } + this.exprAllowed = false; + }; + + types.backQuote.updateContext = function() { + if (this.curContext() === types$1.q_tmpl) + { this.context.pop(); } + else + { this.context.push(types$1.q_tmpl); } + this.exprAllowed = false; + }; + + types.star.updateContext = function(prevType) { + if (prevType === types._function) { + var index = this.context.length - 1; + if (this.context[index] === types$1.f_expr) + { this.context[index] = types$1.f_expr_gen; } + else + { this.context[index] = types$1.f_gen; } + } + this.exprAllowed = true; + }; + + types.name.updateContext = function(prevType) { + var allowed = false; + if (this.options.ecmaVersion >= 6 && prevType !== types.dot) { + if (this.value === "of" && !this.exprAllowed || + this.value === "yield" && this.inGeneratorContext()) + { allowed = true; } + } + this.exprAllowed = allowed; + }; + + // This file contains Unicode properties extracted from the ECMAScript + // specification. The lists are extracted like so: + // $$('#table-binary-unicode-properties > figure > table > tbody > tr > td:nth-child(1) code').map(el => el.innerText) + + // #table-binary-unicode-properties + var ecma9BinaryProperties = "ASCII ASCII_Hex_Digit AHex Alphabetic Alpha Any Assigned Bidi_Control Bidi_C Bidi_Mirrored Bidi_M Case_Ignorable CI Cased Changes_When_Casefolded CWCF Changes_When_Casemapped CWCM Changes_When_Lowercased CWL Changes_When_NFKC_Casefolded CWKCF Changes_When_Titlecased CWT Changes_When_Uppercased CWU Dash Default_Ignorable_Code_Point DI Deprecated Dep Diacritic Dia Emoji Emoji_Component Emoji_Modifier Emoji_Modifier_Base Emoji_Presentation Extender Ext Grapheme_Base Gr_Base Grapheme_Extend Gr_Ext Hex_Digit Hex IDS_Binary_Operator IDSB IDS_Trinary_Operator IDST ID_Continue IDC ID_Start IDS Ideographic Ideo Join_Control Join_C Logical_Order_Exception LOE Lowercase Lower Math Noncharacter_Code_Point NChar Pattern_Syntax Pat_Syn Pattern_White_Space Pat_WS Quotation_Mark QMark Radical Regional_Indicator RI Sentence_Terminal STerm Soft_Dotted SD Terminal_Punctuation Term Unified_Ideograph UIdeo Uppercase Upper Variation_Selector VS White_Space space XID_Continue XIDC XID_Start XIDS"; + var ecma10BinaryProperties = ecma9BinaryProperties + " Extended_Pictographic"; + var ecma11BinaryProperties = ecma10BinaryProperties; + var unicodeBinaryProperties = { + 9: ecma9BinaryProperties, + 10: ecma10BinaryProperties, + 11: ecma11BinaryProperties + }; + + // #table-unicode-general-category-values + var unicodeGeneralCategoryValues = "Cased_Letter LC Close_Punctuation Pe Connector_Punctuation Pc Control Cc cntrl Currency_Symbol Sc Dash_Punctuation Pd Decimal_Number Nd digit Enclosing_Mark Me Final_Punctuation Pf Format Cf Initial_Punctuation Pi Letter L Letter_Number Nl Line_Separator Zl Lowercase_Letter Ll Mark M Combining_Mark Math_Symbol Sm Modifier_Letter Lm Modifier_Symbol Sk Nonspacing_Mark Mn Number N Open_Punctuation Ps Other C Other_Letter Lo Other_Number No Other_Punctuation Po Other_Symbol So Paragraph_Separator Zp Private_Use Co Punctuation P punct Separator Z Space_Separator Zs Spacing_Mark Mc Surrogate Cs Symbol S Titlecase_Letter Lt Unassigned Cn Uppercase_Letter Lu"; + + // #table-unicode-script-values + var ecma9ScriptValues = "Adlam Adlm Ahom Ahom Anatolian_Hieroglyphs Hluw Arabic Arab Armenian Armn Avestan Avst Balinese Bali Bamum Bamu Bassa_Vah Bass Batak Batk Bengali Beng Bhaiksuki Bhks Bopomofo Bopo Brahmi Brah Braille Brai Buginese Bugi Buhid Buhd Canadian_Aboriginal Cans Carian Cari Caucasian_Albanian Aghb Chakma Cakm Cham Cham Cherokee Cher Common Zyyy Coptic Copt Qaac Cuneiform Xsux Cypriot Cprt Cyrillic Cyrl Deseret Dsrt Devanagari Deva Duployan Dupl Egyptian_Hieroglyphs Egyp Elbasan Elba Ethiopic Ethi Georgian Geor Glagolitic Glag Gothic Goth Grantha Gran Greek Grek Gujarati Gujr Gurmukhi Guru Han Hani Hangul Hang Hanunoo Hano Hatran Hatr Hebrew Hebr Hiragana Hira Imperial_Aramaic Armi Inherited Zinh Qaai Inscriptional_Pahlavi Phli Inscriptional_Parthian Prti Javanese Java Kaithi Kthi Kannada Knda Katakana Kana Kayah_Li Kali Kharoshthi Khar Khmer Khmr Khojki Khoj Khudawadi Sind Lao Laoo Latin Latn Lepcha Lepc Limbu Limb Linear_A Lina Linear_B Linb Lisu Lisu Lycian Lyci Lydian Lydi Mahajani Mahj Malayalam Mlym Mandaic Mand Manichaean Mani Marchen Marc Masaram_Gondi Gonm Meetei_Mayek Mtei Mende_Kikakui Mend Meroitic_Cursive Merc Meroitic_Hieroglyphs Mero Miao Plrd Modi Modi Mongolian Mong Mro Mroo Multani Mult Myanmar Mymr Nabataean Nbat New_Tai_Lue Talu Newa Newa Nko Nkoo Nushu Nshu Ogham Ogam Ol_Chiki Olck Old_Hungarian Hung Old_Italic Ital Old_North_Arabian Narb Old_Permic Perm Old_Persian Xpeo Old_South_Arabian Sarb Old_Turkic Orkh Oriya Orya Osage Osge Osmanya Osma Pahawh_Hmong Hmng Palmyrene Palm Pau_Cin_Hau Pauc Phags_Pa Phag Phoenician Phnx Psalter_Pahlavi Phlp Rejang Rjng Runic Runr Samaritan Samr Saurashtra Saur Sharada Shrd Shavian Shaw Siddham Sidd SignWriting Sgnw Sinhala Sinh Sora_Sompeng Sora Soyombo Soyo Sundanese Sund Syloti_Nagri Sylo Syriac Syrc Tagalog Tglg Tagbanwa Tagb Tai_Le Tale Tai_Tham Lana Tai_Viet Tavt Takri Takr Tamil Taml Tangut Tang Telugu Telu Thaana Thaa Thai Thai Tibetan Tibt Tifinagh Tfng Tirhuta Tirh Ugaritic Ugar Vai Vaii Warang_Citi Wara Yi Yiii Zanabazar_Square Zanb"; + var ecma10ScriptValues = ecma9ScriptValues + " Dogra Dogr Gunjala_Gondi Gong Hanifi_Rohingya Rohg Makasar Maka Medefaidrin Medf Old_Sogdian Sogo Sogdian Sogd"; + var ecma11ScriptValues = ecma10ScriptValues + " Elymaic Elym Nandinagari Nand Nyiakeng_Puachue_Hmong Hmnp Wancho Wcho"; + var unicodeScriptValues = { + 9: ecma9ScriptValues, + 10: ecma10ScriptValues, + 11: ecma11ScriptValues + }; + + var data = {}; + function buildUnicodeData(ecmaVersion) { + var d = data[ecmaVersion] = { + binary: wordsRegexp(unicodeBinaryProperties[ecmaVersion] + " " + unicodeGeneralCategoryValues), + nonBinary: { + General_Category: wordsRegexp(unicodeGeneralCategoryValues), + Script: wordsRegexp(unicodeScriptValues[ecmaVersion]) + } + }; + d.nonBinary.Script_Extensions = d.nonBinary.Script; + + d.nonBinary.gc = d.nonBinary.General_Category; + d.nonBinary.sc = d.nonBinary.Script; + d.nonBinary.scx = d.nonBinary.Script_Extensions; + } + buildUnicodeData(9); + buildUnicodeData(10); + buildUnicodeData(11); + + var pp$8 = Parser.prototype; + + var RegExpValidationState = function RegExpValidationState(parser) { + this.parser = parser; + this.validFlags = "gim" + (parser.options.ecmaVersion >= 6 ? "uy" : "") + (parser.options.ecmaVersion >= 9 ? "s" : ""); + this.unicodeProperties = data[parser.options.ecmaVersion >= 11 ? 11 : parser.options.ecmaVersion]; + this.source = ""; + this.flags = ""; + this.start = 0; + this.switchU = false; + this.switchN = false; + this.pos = 0; + this.lastIntValue = 0; + this.lastStringValue = ""; + this.lastAssertionIsQuantifiable = false; + this.numCapturingParens = 0; + this.maxBackReference = 0; + this.groupNames = []; + this.backReferenceNames = []; + }; + + RegExpValidationState.prototype.reset = function reset (start, pattern, flags) { + var unicode = flags.indexOf("u") !== -1; + this.start = start | 0; + this.source = pattern + ""; + this.flags = flags; + this.switchU = unicode && this.parser.options.ecmaVersion >= 6; + this.switchN = unicode && this.parser.options.ecmaVersion >= 9; + }; + + RegExpValidationState.prototype.raise = function raise (message) { + this.parser.raiseRecoverable(this.start, ("Invalid regular expression: /" + (this.source) + "/: " + message)); + }; + + // If u flag is given, this returns the code point at the index (it combines a surrogate pair). + // Otherwise, this returns the code unit of the index (can be a part of a surrogate pair). + RegExpValidationState.prototype.at = function at (i) { + var s = this.source; + var l = s.length; + if (i >= l) { + return -1 + } + var c = s.charCodeAt(i); + if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return c + } + return (c << 10) + s.charCodeAt(i + 1) - 0x35FDC00 + }; + + RegExpValidationState.prototype.nextIndex = function nextIndex (i) { + var s = this.source; + var l = s.length; + if (i >= l) { + return l + } + var c = s.charCodeAt(i); + if (!this.switchU || c <= 0xD7FF || c >= 0xE000 || i + 1 >= l) { + return i + 1 + } + return i + 2 + }; + + RegExpValidationState.prototype.current = function current () { + return this.at(this.pos) + }; + + RegExpValidationState.prototype.lookahead = function lookahead () { + return this.at(this.nextIndex(this.pos)) + }; + + RegExpValidationState.prototype.advance = function advance () { + this.pos = this.nextIndex(this.pos); + }; + + RegExpValidationState.prototype.eat = function eat (ch) { + if (this.current() === ch) { + this.advance(); + return true + } + return false + }; + + function codePointToString(ch) { + if (ch <= 0xFFFF) { return String.fromCharCode(ch) } + ch -= 0x10000; + return String.fromCharCode((ch >> 10) + 0xD800, (ch & 0x03FF) + 0xDC00) + } + + /** + * Validate the flags part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$8.validateRegExpFlags = function(state) { + var validFlags = state.validFlags; + var flags = state.flags; + + for (var i = 0; i < flags.length; i++) { + var flag = flags.charAt(i); + if (validFlags.indexOf(flag) === -1) { + this.raise(state.start, "Invalid regular expression flag"); + } + if (flags.indexOf(flag, i + 1) > -1) { + this.raise(state.start, "Duplicate regular expression flag"); + } + } + }; + + /** + * Validate the pattern part of a given RegExpLiteral. + * + * @param {RegExpValidationState} state The state to validate RegExp. + * @returns {void} + */ + pp$8.validateRegExpPattern = function(state) { this.regexp_pattern(state); - } -}; -// https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern -pp$9.regexp_pattern = function(state) { - state.pos = 0; - state.lastIntValue = 0; - state.lastStringValue = ""; - state.lastAssertionIsQuantifiable = false; - state.numCapturingParens = 0; - state.maxBackReference = 0; - state.groupNames.length = 0; - state.backReferenceNames.length = 0; - - this.regexp_disjunction(state); - - if (state.pos !== state.source.length) { - // Make the same messages as V8. - if (state.eat(0x29 /* ) */)) { - state.raise("Unmatched ')'"); + // The goal symbol for the parse is |Pattern[~U, ~N]|. If the result of + // parsing contains a |GroupName|, reparse with the goal symbol + // |Pattern[~U, +N]| and use this result instead. Throw a *SyntaxError* + // exception if _P_ did not conform to the grammar, if any elements of _P_ + // were not matched by the parse, or if any Early Error conditions exist. + if (!state.switchN && this.options.ecmaVersion >= 9 && state.groupNames.length > 0) { + state.switchN = true; + this.regexp_pattern(state); } - if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) { + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Pattern + pp$8.regexp_pattern = function(state) { + state.pos = 0; + state.lastIntValue = 0; + state.lastStringValue = ""; + state.lastAssertionIsQuantifiable = false; + state.numCapturingParens = 0; + state.maxBackReference = 0; + state.groupNames.length = 0; + state.backReferenceNames.length = 0; + + this.regexp_disjunction(state); + + if (state.pos !== state.source.length) { + // Make the same messages as V8. + if (state.eat(0x29 /* ) */)) { + state.raise("Unmatched ')'"); + } + if (state.eat(0x5D /* [ */) || state.eat(0x7D /* } */)) { + state.raise("Lone quantifier brackets"); + } + } + if (state.maxBackReference > state.numCapturingParens) { + state.raise("Invalid escape"); + } + for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { + var name = list[i]; + + if (state.groupNames.indexOf(name) === -1) { + state.raise("Invalid named capture referenced"); + } + } + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction + pp$8.regexp_disjunction = function(state) { + this.regexp_alternative(state); + while (state.eat(0x7C /* | */)) { + this.regexp_alternative(state); + } + + // Make the same message as V8. + if (this.regexp_eatQuantifier(state, true)) { + state.raise("Nothing to repeat"); + } + if (state.eat(0x7B /* { */)) { state.raise("Lone quantifier brackets"); } - } - if (state.maxBackReference > state.numCapturingParens) { - state.raise("Invalid escape"); - } - for (var i = 0, list = state.backReferenceNames; i < list.length; i += 1) { - var name = list[i]; + }; - if (state.groupNames.indexOf(name) === -1) { - state.raise("Invalid named capture referenced"); - } - } -}; + // https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative + pp$8.regexp_alternative = function(state) { + while (state.pos < state.source.length && this.regexp_eatTerm(state)) + { } + }; -// https://www.ecma-international.org/ecma-262/8.0/#prod-Disjunction -pp$9.regexp_disjunction = function(state) { - var this$1 = this; - - this.regexp_alternative(state); - while (state.eat(0x7C /* | */)) { - this$1.regexp_alternative(state); - } - - // Make the same message as V8. - if (this.regexp_eatQuantifier(state, true)) { - state.raise("Nothing to repeat"); - } - if (state.eat(0x7B /* { */)) { - state.raise("Lone quantifier brackets"); - } -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-Alternative -pp$9.regexp_alternative = function(state) { - while (state.pos < state.source.length && this.regexp_eatTerm(state)) - { } -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term -pp$9.regexp_eatTerm = function(state) { - if (this.regexp_eatAssertion(state)) { - // Handle `QuantifiableAssertion Quantifier` alternative. - // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion - // is a QuantifiableAssertion. - if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { - // Make the same message as V8. - if (state.switchU) { - state.raise("Invalid quantifier"); - } - } - return true - } - - if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { - this.regexp_eatQuantifier(state); - return true - } - - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion -pp$9.regexp_eatAssertion = function(state) { - var start = state.pos; - state.lastAssertionIsQuantifiable = false; - - // ^, $ - if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { - return true - } - - // \b \B - if (state.eat(0x5C /* \ */)) { - if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { - return true - } - state.pos = start; - } - - // Lookahead / Lookbehind - if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { - var lookbehind = false; - if (this.options.ecmaVersion >= 9) { - lookbehind = state.eat(0x3C /* < */); - } - if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { - this.regexp_disjunction(state); - if (!state.eat(0x29 /* ) */)) { - state.raise("Unterminated group"); - } - state.lastAssertionIsQuantifiable = !lookbehind; - return true - } - } - - state.pos = start; - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier -pp$9.regexp_eatQuantifier = function(state, noError) { - if ( noError === void 0 ) noError = false; - - if (this.regexp_eatQuantifierPrefix(state, noError)) { - state.eat(0x3F /* ? */); - return true - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix -pp$9.regexp_eatQuantifierPrefix = function(state, noError) { - return ( - state.eat(0x2A /* * */) || - state.eat(0x2B /* + */) || - state.eat(0x3F /* ? */) || - this.regexp_eatBracedQuantifier(state, noError) - ) -}; -pp$9.regexp_eatBracedQuantifier = function(state, noError) { - var start = state.pos; - if (state.eat(0x7B /* { */)) { - var min = 0, max = -1; - if (this.regexp_eatDecimalDigits(state)) { - min = state.lastIntValue; - if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { - max = state.lastIntValue; - } - if (state.eat(0x7D /* } */)) { - // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term - if (max !== -1 && max < min && !noError) { - state.raise("numbers out of order in {} quantifier"); + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Term + pp$8.regexp_eatTerm = function(state) { + if (this.regexp_eatAssertion(state)) { + // Handle `QuantifiableAssertion Quantifier` alternative. + // `state.lastAssertionIsQuantifiable` is true if the last eaten Assertion + // is a QuantifiableAssertion. + if (state.lastAssertionIsQuantifiable && this.regexp_eatQuantifier(state)) { + // Make the same message as V8. + if (state.switchU) { + state.raise("Invalid quantifier"); } + } + return true + } + + if (state.switchU ? this.regexp_eatAtom(state) : this.regexp_eatExtendedAtom(state)) { + this.regexp_eatQuantifier(state); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-Assertion + pp$8.regexp_eatAssertion = function(state) { + var start = state.pos; + state.lastAssertionIsQuantifiable = false; + + // ^, $ + if (state.eat(0x5E /* ^ */) || state.eat(0x24 /* $ */)) { + return true + } + + // \b \B + if (state.eat(0x5C /* \ */)) { + if (state.eat(0x42 /* B */) || state.eat(0x62 /* b */)) { + return true + } + state.pos = start; + } + + // Lookahead / Lookbehind + if (state.eat(0x28 /* ( */) && state.eat(0x3F /* ? */)) { + var lookbehind = false; + if (this.options.ecmaVersion >= 9) { + lookbehind = state.eat(0x3C /* < */); + } + if (state.eat(0x3D /* = */) || state.eat(0x21 /* ! */)) { + this.regexp_disjunction(state); + if (!state.eat(0x29 /* ) */)) { + state.raise("Unterminated group"); + } + state.lastAssertionIsQuantifiable = !lookbehind; return true } } - if (state.switchU && !noError) { - state.raise("Incomplete quantifier"); - } - state.pos = start; - } - return false -}; -// https://www.ecma-international.org/ecma-262/8.0/#prod-Atom -pp$9.regexp_eatAtom = function(state) { - return ( - this.regexp_eatPatternCharacters(state) || - state.eat(0x2E /* . */) || - this.regexp_eatReverseSolidusAtomEscape(state) || - this.regexp_eatCharacterClass(state) || - this.regexp_eatUncapturingGroup(state) || - this.regexp_eatCapturingGroup(state) - ) -}; -pp$9.regexp_eatReverseSolidusAtomEscape = function(state) { - var start = state.pos; - if (state.eat(0x5C /* \ */)) { - if (this.regexp_eatAtomEscape(state)) { + state.pos = start; + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Quantifier + pp$8.regexp_eatQuantifier = function(state, noError) { + if ( noError === void 0 ) noError = false; + + if (this.regexp_eatQuantifierPrefix(state, noError)) { + state.eat(0x3F /* ? */); return true } - state.pos = start; - } - return false -}; -pp$9.regexp_eatUncapturingGroup = function(state) { - var start = state.pos; - if (state.eat(0x28 /* ( */)) { - if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-QuantifierPrefix + pp$8.regexp_eatQuantifierPrefix = function(state, noError) { + return ( + state.eat(0x2A /* * */) || + state.eat(0x2B /* + */) || + state.eat(0x3F /* ? */) || + this.regexp_eatBracedQuantifier(state, noError) + ) + }; + pp$8.regexp_eatBracedQuantifier = function(state, noError) { + var start = state.pos; + if (state.eat(0x7B /* { */)) { + var min = 0, max = -1; + if (this.regexp_eatDecimalDigits(state)) { + min = state.lastIntValue; + if (state.eat(0x2C /* , */) && this.regexp_eatDecimalDigits(state)) { + max = state.lastIntValue; + } + if (state.eat(0x7D /* } */)) { + // SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-term + if (max !== -1 && max < min && !noError) { + state.raise("numbers out of order in {} quantifier"); + } + return true + } + } + if (state.switchU && !noError) { + state.raise("Incomplete quantifier"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Atom + pp$8.regexp_eatAtom = function(state) { + return ( + this.regexp_eatPatternCharacters(state) || + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) + ) + }; + pp$8.regexp_eatReverseSolidusAtomEscape = function(state) { + var start = state.pos; + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatAtomEscape(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatUncapturingGroup = function(state) { + var start = state.pos; + if (state.eat(0x28 /* ( */)) { + if (state.eat(0x3F /* ? */) && state.eat(0x3A /* : */)) { + this.regexp_disjunction(state); + if (state.eat(0x29 /* ) */)) { + return true + } + state.raise("Unterminated group"); + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatCapturingGroup = function(state) { + if (state.eat(0x28 /* ( */)) { + if (this.options.ecmaVersion >= 9) { + this.regexp_groupSpecifier(state); + } else if (state.current() === 0x3F /* ? */) { + state.raise("Invalid group"); + } this.regexp_disjunction(state); if (state.eat(0x29 /* ) */)) { + state.numCapturingParens += 1; return true } state.raise("Unterminated group"); } - state.pos = start; - } - return false -}; -pp$9.regexp_eatCapturingGroup = function(state) { - if (state.eat(0x28 /* ( */)) { - if (this.options.ecmaVersion >= 9) { - this.regexp_groupSpecifier(state); - } else if (state.current() === 0x3F /* ? */) { - state.raise("Invalid group"); + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom + pp$8.regexp_eatExtendedAtom = function(state) { + return ( + state.eat(0x2E /* . */) || + this.regexp_eatReverseSolidusAtomEscape(state) || + this.regexp_eatCharacterClass(state) || + this.regexp_eatUncapturingGroup(state) || + this.regexp_eatCapturingGroup(state) || + this.regexp_eatInvalidBracedQuantifier(state) || + this.regexp_eatExtendedPatternCharacter(state) + ) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier + pp$8.regexp_eatInvalidBracedQuantifier = function(state) { + if (this.regexp_eatBracedQuantifier(state, true)) { + state.raise("Nothing to repeat"); } - this.regexp_disjunction(state); - if (state.eat(0x29 /* ) */)) { - state.numCapturingParens += 1; - return true - } - state.raise("Unterminated group"); - } - return false -}; + return false + }; -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedAtom -pp$9.regexp_eatExtendedAtom = function(state) { - return ( - state.eat(0x2E /* . */) || - this.regexp_eatReverseSolidusAtomEscape(state) || - this.regexp_eatCharacterClass(state) || - this.regexp_eatUncapturingGroup(state) || - this.regexp_eatCapturingGroup(state) || - this.regexp_eatInvalidBracedQuantifier(state) || - this.regexp_eatExtendedPatternCharacter(state) - ) -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-InvalidBracedQuantifier -pp$9.regexp_eatInvalidBracedQuantifier = function(state) { - if (this.regexp_eatBracedQuantifier(state, true)) { - state.raise("Nothing to repeat"); - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter -pp$9.regexp_eatSyntaxCharacter = function(state) { - var ch = state.current(); - if (isSyntaxCharacter(ch)) { - state.lastIntValue = ch; - state.advance(); - return true - } - return false -}; -function isSyntaxCharacter(ch) { - return ( - ch === 0x24 /* $ */ || - ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || - ch === 0x2E /* . */ || - ch === 0x3F /* ? */ || - ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || - ch >= 0x7B /* { */ && ch <= 0x7D /* } */ - ) -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter -// But eat eager. -pp$9.regexp_eatPatternCharacters = function(state) { - var start = state.pos; - var ch = 0; - while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { - state.advance(); - } - return state.pos !== start -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter -pp$9.regexp_eatExtendedPatternCharacter = function(state) { - var ch = state.current(); - if ( - ch !== -1 && - ch !== 0x24 /* $ */ && - !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && - ch !== 0x2E /* . */ && - ch !== 0x3F /* ? */ && - ch !== 0x5B /* [ */ && - ch !== 0x5E /* ^ */ && - ch !== 0x7C /* | */ - ) { - state.advance(); - return true - } - return false -}; - -// GroupSpecifier[U] :: -// [empty] -// `?` GroupName[?U] -pp$9.regexp_groupSpecifier = function(state) { - if (state.eat(0x3F /* ? */)) { - if (this.regexp_eatGroupName(state)) { - if (state.groupNames.indexOf(state.lastStringValue) !== -1) { - state.raise("Duplicate capture group name"); - } - state.groupNames.push(state.lastStringValue); - return - } - state.raise("Invalid group"); - } -}; - -// GroupName[U] :: -// `<` RegExpIdentifierName[?U] `>` -// Note: this updates `state.lastStringValue` property with the eaten name. -pp$9.regexp_eatGroupName = function(state) { - state.lastStringValue = ""; - if (state.eat(0x3C /* < */)) { - if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { - return true - } - state.raise("Invalid capture group name"); - } - return false -}; - -// RegExpIdentifierName[U] :: -// RegExpIdentifierStart[?U] -// RegExpIdentifierName[?U] RegExpIdentifierPart[?U] -// Note: this updates `state.lastStringValue` property with the eaten name. -pp$9.regexp_eatRegExpIdentifierName = function(state) { - state.lastStringValue = ""; - if (this.regexp_eatRegExpIdentifierStart(state)) { - state.lastStringValue += codePointToString$1(state.lastIntValue); - while (this.regexp_eatRegExpIdentifierPart(state)) { - state.lastStringValue += codePointToString$1(state.lastIntValue); - } - return true - } - return false -}; - -// RegExpIdentifierStart[U] :: -// UnicodeIDStart -// `$` -// `_` -// `\` RegExpUnicodeEscapeSequence[?U] -pp$9.regexp_eatRegExpIdentifierStart = function(state) { - var start = state.pos; - var ch = state.current(); - state.advance(); - - if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { - ch = state.lastIntValue; - } - if (isRegExpIdentifierStart(ch)) { - state.lastIntValue = ch; - return true - } - - state.pos = start; - return false -}; -function isRegExpIdentifierStart(ch) { - return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ -} - -// RegExpIdentifierPart[U] :: -// UnicodeIDContinue -// `$` -// `_` -// `\` RegExpUnicodeEscapeSequence[?U] -// <ZWNJ> -// <ZWJ> -pp$9.regexp_eatRegExpIdentifierPart = function(state) { - var start = state.pos; - var ch = state.current(); - state.advance(); - - if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { - ch = state.lastIntValue; - } - if (isRegExpIdentifierPart(ch)) { - state.lastIntValue = ch; - return true - } - - state.pos = start; - return false -}; -function isRegExpIdentifierPart(ch) { - return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape -pp$9.regexp_eatAtomEscape = function(state) { - if ( - this.regexp_eatBackReference(state) || - this.regexp_eatCharacterClassEscape(state) || - this.regexp_eatCharacterEscape(state) || - (state.switchN && this.regexp_eatKGroupName(state)) - ) { - return true - } - if (state.switchU) { - // Make the same message as V8. - if (state.current() === 0x63 /* c */) { - state.raise("Invalid unicode escape"); - } - state.raise("Invalid escape"); - } - return false -}; -pp$9.regexp_eatBackReference = function(state) { - var start = state.pos; - if (this.regexp_eatDecimalEscape(state)) { - var n = state.lastIntValue; - if (state.switchU) { - // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape - if (n > state.maxBackReference) { - state.maxBackReference = n; - } - return true - } - if (n <= state.numCapturingParens) { - return true - } - state.pos = start; - } - return false -}; -pp$9.regexp_eatKGroupName = function(state) { - if (state.eat(0x6B /* k */)) { - if (this.regexp_eatGroupName(state)) { - state.backReferenceNames.push(state.lastStringValue); - return true - } - state.raise("Invalid named reference"); - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape -pp$9.regexp_eatCharacterEscape = function(state) { - return ( - this.regexp_eatControlEscape(state) || - this.regexp_eatCControlLetter(state) || - this.regexp_eatZero(state) || - this.regexp_eatHexEscapeSequence(state) || - this.regexp_eatRegExpUnicodeEscapeSequence(state) || - (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || - this.regexp_eatIdentityEscape(state) - ) -}; -pp$9.regexp_eatCControlLetter = function(state) { - var start = state.pos; - if (state.eat(0x63 /* c */)) { - if (this.regexp_eatControlLetter(state)) { - return true - } - state.pos = start; - } - return false -}; -pp$9.regexp_eatZero = function(state) { - if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { - state.lastIntValue = 0; - state.advance(); - return true - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape -pp$9.regexp_eatControlEscape = function(state) { - var ch = state.current(); - if (ch === 0x74 /* t */) { - state.lastIntValue = 0x09; /* \t */ - state.advance(); - return true - } - if (ch === 0x6E /* n */) { - state.lastIntValue = 0x0A; /* \n */ - state.advance(); - return true - } - if (ch === 0x76 /* v */) { - state.lastIntValue = 0x0B; /* \v */ - state.advance(); - return true - } - if (ch === 0x66 /* f */) { - state.lastIntValue = 0x0C; /* \f */ - state.advance(); - return true - } - if (ch === 0x72 /* r */) { - state.lastIntValue = 0x0D; /* \r */ - state.advance(); - return true - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter -pp$9.regexp_eatControlLetter = function(state) { - var ch = state.current(); - if (isControlLetter(ch)) { - state.lastIntValue = ch % 0x20; - state.advance(); - return true - } - return false -}; -function isControlLetter(ch) { - return ( - (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || - (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) - ) -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence -pp$9.regexp_eatRegExpUnicodeEscapeSequence = function(state) { - var start = state.pos; - - if (state.eat(0x75 /* u */)) { - if (this.regexp_eatFixedHexDigits(state, 4)) { - var lead = state.lastIntValue; - if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) { - var leadSurrogateEnd = state.pos; - if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { - var trail = state.lastIntValue; - if (trail >= 0xDC00 && trail <= 0xDFFF) { - state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; - return true - } - } - state.pos = leadSurrogateEnd; - state.lastIntValue = lead; - } - return true - } - if ( - state.switchU && - state.eat(0x7B /* { */) && - this.regexp_eatHexDigits(state) && - state.eat(0x7D /* } */) && - isValidUnicode(state.lastIntValue) - ) { - return true - } - if (state.switchU) { - state.raise("Invalid unicode escape"); - } - state.pos = start; - } - - return false -}; -function isValidUnicode(ch) { - return ch >= 0 && ch <= 0x10FFFF -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape -pp$9.regexp_eatIdentityEscape = function(state) { - if (state.switchU) { - if (this.regexp_eatSyntaxCharacter(state)) { - return true - } - if (state.eat(0x2F /* / */)) { - state.lastIntValue = 0x2F; /* / */ + // https://www.ecma-international.org/ecma-262/8.0/#prod-SyntaxCharacter + pp$8.regexp_eatSyntaxCharacter = function(state) { + var ch = state.current(); + if (isSyntaxCharacter(ch)) { + state.lastIntValue = ch; + state.advance(); return true } return false + }; + function isSyntaxCharacter(ch) { + return ( + ch === 0x24 /* $ */ || + ch >= 0x28 /* ( */ && ch <= 0x2B /* + */ || + ch === 0x2E /* . */ || + ch === 0x3F /* ? */ || + ch >= 0x5B /* [ */ && ch <= 0x5E /* ^ */ || + ch >= 0x7B /* { */ && ch <= 0x7D /* } */ + ) } - var ch = state.current(); - if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { - state.lastIntValue = ch; - state.advance(); - return true - } - - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape -pp$9.regexp_eatDecimalEscape = function(state) { - state.lastIntValue = 0; - var ch = state.current(); - if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { - do { - state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + // https://www.ecma-international.org/ecma-262/8.0/#prod-PatternCharacter + // But eat eager. + pp$8.regexp_eatPatternCharacters = function(state) { + var start = state.pos; + var ch = 0; + while ((ch = state.current()) !== -1 && !isSyntaxCharacter(ch)) { state.advance(); - } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) - return true - } - return false -}; + } + return state.pos !== start + }; -// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape -pp$9.regexp_eatCharacterClassEscape = function(state) { - var ch = state.current(); - - if (isCharacterClassEscape(ch)) { - state.lastIntValue = -1; - state.advance(); - return true - } - - if ( - state.switchU && - this.options.ecmaVersion >= 9 && - (ch === 0x50 /* P */ || ch === 0x70 /* p */) - ) { - state.lastIntValue = -1; - state.advance(); + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ExtendedPatternCharacter + pp$8.regexp_eatExtendedPatternCharacter = function(state) { + var ch = state.current(); if ( - state.eat(0x7B /* { */) && - this.regexp_eatUnicodePropertyValueExpression(state) && - state.eat(0x7D /* } */) + ch !== -1 && + ch !== 0x24 /* $ */ && + !(ch >= 0x28 /* ( */ && ch <= 0x2B /* + */) && + ch !== 0x2E /* . */ && + ch !== 0x3F /* ? */ && + ch !== 0x5B /* [ */ && + ch !== 0x5E /* ^ */ && + ch !== 0x7C /* | */ ) { + state.advance(); return true } - state.raise("Invalid property name"); - } + return false + }; - return false -}; -function isCharacterClassEscape(ch) { - return ( - ch === 0x64 /* d */ || - ch === 0x44 /* D */ || - ch === 0x73 /* s */ || - ch === 0x53 /* S */ || - ch === 0x77 /* w */ || - ch === 0x57 /* W */ - ) -} - -// UnicodePropertyValueExpression :: -// UnicodePropertyName `=` UnicodePropertyValue -// LoneUnicodePropertyNameOrValue -pp$9.regexp_eatUnicodePropertyValueExpression = function(state) { - var start = state.pos; - - // UnicodePropertyName `=` UnicodePropertyValue - if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { - var name = state.lastStringValue; - if (this.regexp_eatUnicodePropertyValue(state)) { - var value = state.lastStringValue; - this.regexp_validateUnicodePropertyNameAndValue(state, name, value); - return true - } - } - state.pos = start; - - // LoneUnicodePropertyNameOrValue - if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { - var nameOrValue = state.lastStringValue; - this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); - return true - } - return false -}; -pp$9.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { - if (!data.hasOwnProperty(name) || data[name].indexOf(value) === -1) { - state.raise("Invalid property name"); - } -}; -pp$9.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { - if (data.$LONE.indexOf(nameOrValue) === -1) { - state.raise("Invalid property name"); - } -}; - -// UnicodePropertyName :: -// UnicodePropertyNameCharacters -pp$9.regexp_eatUnicodePropertyName = function(state) { - var ch = 0; - state.lastStringValue = ""; - while (isUnicodePropertyNameCharacter(ch = state.current())) { - state.lastStringValue += codePointToString$1(ch); - state.advance(); - } - return state.lastStringValue !== "" -}; -function isUnicodePropertyNameCharacter(ch) { - return isControlLetter(ch) || ch === 0x5F /* _ */ -} - -// UnicodePropertyValue :: -// UnicodePropertyValueCharacters -pp$9.regexp_eatUnicodePropertyValue = function(state) { - var ch = 0; - state.lastStringValue = ""; - while (isUnicodePropertyValueCharacter(ch = state.current())) { - state.lastStringValue += codePointToString$1(ch); - state.advance(); - } - return state.lastStringValue !== "" -}; -function isUnicodePropertyValueCharacter(ch) { - return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) -} - -// LoneUnicodePropertyNameOrValue :: -// UnicodePropertyValueCharacters -pp$9.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { - return this.regexp_eatUnicodePropertyValue(state) -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass -pp$9.regexp_eatCharacterClass = function(state) { - if (state.eat(0x5B /* [ */)) { - state.eat(0x5E /* ^ */); - this.regexp_classRanges(state); - if (state.eat(0x5D /* [ */)) { - return true - } - // Unreachable since it threw "unterminated regular expression" error before. - state.raise("Unterminated character class"); - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges -// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges -// https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash -pp$9.regexp_classRanges = function(state) { - var this$1 = this; - - while (this.regexp_eatClassAtom(state)) { - var left = state.lastIntValue; - if (state.eat(0x2D /* - */) && this$1.regexp_eatClassAtom(state)) { - var right = state.lastIntValue; - if (state.switchU && (left === -1 || right === -1)) { - state.raise("Invalid character class"); + // GroupSpecifier[U] :: + // [empty] + // `?` GroupName[?U] + pp$8.regexp_groupSpecifier = function(state) { + if (state.eat(0x3F /* ? */)) { + if (this.regexp_eatGroupName(state)) { + if (state.groupNames.indexOf(state.lastStringValue) !== -1) { + state.raise("Duplicate capture group name"); + } + state.groupNames.push(state.lastStringValue); + return } - if (left !== -1 && right !== -1 && left > right) { - state.raise("Range out of order in character class"); - } + state.raise("Invalid group"); } + }; + + // GroupName[U] :: + // `<` RegExpIdentifierName[?U] `>` + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$8.regexp_eatGroupName = function(state) { + state.lastStringValue = ""; + if (state.eat(0x3C /* < */)) { + if (this.regexp_eatRegExpIdentifierName(state) && state.eat(0x3E /* > */)) { + return true + } + state.raise("Invalid capture group name"); + } + return false + }; + + // RegExpIdentifierName[U] :: + // RegExpIdentifierStart[?U] + // RegExpIdentifierName[?U] RegExpIdentifierPart[?U] + // Note: this updates `state.lastStringValue` property with the eaten name. + pp$8.regexp_eatRegExpIdentifierName = function(state) { + state.lastStringValue = ""; + if (this.regexp_eatRegExpIdentifierStart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + while (this.regexp_eatRegExpIdentifierPart(state)) { + state.lastStringValue += codePointToString(state.lastIntValue); + } + return true + } + return false + }; + + // RegExpIdentifierStart[U] :: + // UnicodeIDStart + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[?U] + pp$8.regexp_eatRegExpIdentifierStart = function(state) { + var start = state.pos; + var ch = state.current(); + state.advance(); + + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierStart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierStart(ch) { + return isIdentifierStart(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ } -}; -// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom -// https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash -pp$9.regexp_eatClassAtom = function(state) { - var start = state.pos; + // RegExpIdentifierPart[U] :: + // UnicodeIDContinue + // `$` + // `_` + // `\` RegExpUnicodeEscapeSequence[?U] + // <ZWNJ> + // <ZWJ> + pp$8.regexp_eatRegExpIdentifierPart = function(state) { + var start = state.pos; + var ch = state.current(); + state.advance(); - if (state.eat(0x5C /* \ */)) { - if (this.regexp_eatClassEscape(state)) { + if (ch === 0x5C /* \ */ && this.regexp_eatRegExpUnicodeEscapeSequence(state)) { + ch = state.lastIntValue; + } + if (isRegExpIdentifierPart(ch)) { + state.lastIntValue = ch; + return true + } + + state.pos = start; + return false + }; + function isRegExpIdentifierPart(ch) { + return isIdentifierChar(ch, true) || ch === 0x24 /* $ */ || ch === 0x5F /* _ */ || ch === 0x200C /* <ZWNJ> */ || ch === 0x200D /* <ZWJ> */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-AtomEscape + pp$8.regexp_eatAtomEscape = function(state) { + if ( + this.regexp_eatBackReference(state) || + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) || + (state.switchN && this.regexp_eatKGroupName(state)) + ) { return true } if (state.switchU) { // Make the same message as V8. - var ch$1 = state.current(); - if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { - state.raise("Invalid class escape"); + if (state.current() === 0x63 /* c */) { + state.raise("Invalid unicode escape"); } state.raise("Invalid escape"); } - state.pos = start; - } - - var ch = state.current(); - if (ch !== 0x5D /* [ */) { - state.lastIntValue = ch; - state.advance(); - return true - } - - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape -pp$9.regexp_eatClassEscape = function(state) { - var start = state.pos; - - if (state.eat(0x62 /* b */)) { - state.lastIntValue = 0x08; /* <BS> */ - return true - } - - if (state.switchU && state.eat(0x2D /* - */)) { - state.lastIntValue = 0x2D; /* - */ - return true - } - - if (!state.switchU && state.eat(0x63 /* c */)) { - if (this.regexp_eatClassControlLetter(state)) { - return true - } - state.pos = start; - } - - return ( - this.regexp_eatCharacterClassEscape(state) || - this.regexp_eatCharacterEscape(state) - ) -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter -pp$9.regexp_eatClassControlLetter = function(state) { - var ch = state.current(); - if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { - state.lastIntValue = ch % 0x20; - state.advance(); - return true - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence -pp$9.regexp_eatHexEscapeSequence = function(state) { - var start = state.pos; - if (state.eat(0x78 /* x */)) { - if (this.regexp_eatFixedHexDigits(state, 2)) { - return true - } - if (state.switchU) { - state.raise("Invalid escape"); - } - state.pos = start; - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits -pp$9.regexp_eatDecimalDigits = function(state) { - var start = state.pos; - var ch = 0; - state.lastIntValue = 0; - while (isDecimalDigit(ch = state.current())) { - state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); - state.advance(); - } - return state.pos !== start -}; -function isDecimalDigit(ch) { - return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits -pp$9.regexp_eatHexDigits = function(state) { - var start = state.pos; - var ch = 0; - state.lastIntValue = 0; - while (isHexDigit(ch = state.current())) { - state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); - state.advance(); - } - return state.pos !== start -}; -function isHexDigit(ch) { - return ( - (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || - (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || - (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) - ) -} -function hexToInt(ch) { - if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { - return 10 + (ch - 0x41 /* A */) - } - if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { - return 10 + (ch - 0x61 /* a */) - } - return ch - 0x30 /* 0 */ -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence -// Allows only 0-377(octal) i.e. 0-255(decimal). -pp$9.regexp_eatLegacyOctalEscapeSequence = function(state) { - if (this.regexp_eatOctalDigit(state)) { - var n1 = state.lastIntValue; - if (this.regexp_eatOctalDigit(state)) { - var n2 = state.lastIntValue; - if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { - state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; - } else { - state.lastIntValue = n1 * 8 + n2; + return false + }; + pp$8.regexp_eatBackReference = function(state) { + var start = state.pos; + if (this.regexp_eatDecimalEscape(state)) { + var n = state.lastIntValue; + if (state.switchU) { + // For SyntaxError in https://www.ecma-international.org/ecma-262/8.0/#sec-atomescape + if (n > state.maxBackReference) { + state.maxBackReference = n; + } + return true } - } else { - state.lastIntValue = n1; - } - return true - } - return false -}; - -// https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit -pp$9.regexp_eatOctalDigit = function(state) { - var ch = state.current(); - if (isOctalDigit(ch)) { - state.lastIntValue = ch - 0x30; /* 0 */ - state.advance(); - return true - } - state.lastIntValue = 0; - return false -}; -function isOctalDigit(ch) { - return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ -} - -// https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits -// https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit -// And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence -pp$9.regexp_eatFixedHexDigits = function(state, length) { - var start = state.pos; - state.lastIntValue = 0; - for (var i = 0; i < length; ++i) { - var ch = state.current(); - if (!isHexDigit(ch)) { + if (n <= state.numCapturingParens) { + return true + } state.pos = start; + } + return false + }; + pp$8.regexp_eatKGroupName = function(state) { + if (state.eat(0x6B /* k */)) { + if (this.regexp_eatGroupName(state)) { + state.backReferenceNames.push(state.lastStringValue); + return true + } + state.raise("Invalid named reference"); + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-CharacterEscape + pp$8.regexp_eatCharacterEscape = function(state) { + return ( + this.regexp_eatControlEscape(state) || + this.regexp_eatCControlLetter(state) || + this.regexp_eatZero(state) || + this.regexp_eatHexEscapeSequence(state) || + this.regexp_eatRegExpUnicodeEscapeSequence(state) || + (!state.switchU && this.regexp_eatLegacyOctalEscapeSequence(state)) || + this.regexp_eatIdentityEscape(state) + ) + }; + pp$8.regexp_eatCControlLetter = function(state) { + var start = state.pos; + if (state.eat(0x63 /* c */)) { + if (this.regexp_eatControlLetter(state)) { + return true + } + state.pos = start; + } + return false + }; + pp$8.regexp_eatZero = function(state) { + if (state.current() === 0x30 /* 0 */ && !isDecimalDigit(state.lookahead())) { + state.lastIntValue = 0; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlEscape + pp$8.regexp_eatControlEscape = function(state) { + var ch = state.current(); + if (ch === 0x74 /* t */) { + state.lastIntValue = 0x09; /* \t */ + state.advance(); + return true + } + if (ch === 0x6E /* n */) { + state.lastIntValue = 0x0A; /* \n */ + state.advance(); + return true + } + if (ch === 0x76 /* v */) { + state.lastIntValue = 0x0B; /* \v */ + state.advance(); + return true + } + if (ch === 0x66 /* f */) { + state.lastIntValue = 0x0C; /* \f */ + state.advance(); + return true + } + if (ch === 0x72 /* r */) { + state.lastIntValue = 0x0D; /* \r */ + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-ControlLetter + pp$8.regexp_eatControlLetter = function(state) { + var ch = state.current(); + if (isControlLetter(ch)) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + function isControlLetter(ch) { + return ( + (ch >= 0x41 /* A */ && ch <= 0x5A /* Z */) || + (ch >= 0x61 /* a */ && ch <= 0x7A /* z */) + ) + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-RegExpUnicodeEscapeSequence + pp$8.regexp_eatRegExpUnicodeEscapeSequence = function(state) { + var start = state.pos; + + if (state.eat(0x75 /* u */)) { + if (this.regexp_eatFixedHexDigits(state, 4)) { + var lead = state.lastIntValue; + if (state.switchU && lead >= 0xD800 && lead <= 0xDBFF) { + var leadSurrogateEnd = state.pos; + if (state.eat(0x5C /* \ */) && state.eat(0x75 /* u */) && this.regexp_eatFixedHexDigits(state, 4)) { + var trail = state.lastIntValue; + if (trail >= 0xDC00 && trail <= 0xDFFF) { + state.lastIntValue = (lead - 0xD800) * 0x400 + (trail - 0xDC00) + 0x10000; + return true + } + } + state.pos = leadSurrogateEnd; + state.lastIntValue = lead; + } + return true + } + if ( + state.switchU && + state.eat(0x7B /* { */) && + this.regexp_eatHexDigits(state) && + state.eat(0x7D /* } */) && + isValidUnicode(state.lastIntValue) + ) { + return true + } + if (state.switchU) { + state.raise("Invalid unicode escape"); + } + state.pos = start; + } + + return false + }; + function isValidUnicode(ch) { + return ch >= 0 && ch <= 0x10FFFF + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-IdentityEscape + pp$8.regexp_eatIdentityEscape = function(state) { + if (state.switchU) { + if (this.regexp_eatSyntaxCharacter(state)) { + return true + } + if (state.eat(0x2F /* / */)) { + state.lastIntValue = 0x2F; /* / */ + return true + } return false } - state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); - state.advance(); + + var ch = state.current(); + if (ch !== 0x63 /* c */ && (!state.switchN || ch !== 0x6B /* k */)) { + state.lastIntValue = ch; + state.advance(); + return true + } + + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalEscape + pp$8.regexp_eatDecimalEscape = function(state) { + state.lastIntValue = 0; + var ch = state.current(); + if (ch >= 0x31 /* 1 */ && ch <= 0x39 /* 9 */) { + do { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } while ((ch = state.current()) >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClassEscape + pp$8.regexp_eatCharacterClassEscape = function(state) { + var ch = state.current(); + + if (isCharacterClassEscape(ch)) { + state.lastIntValue = -1; + state.advance(); + return true + } + + if ( + state.switchU && + this.options.ecmaVersion >= 9 && + (ch === 0x50 /* P */ || ch === 0x70 /* p */) + ) { + state.lastIntValue = -1; + state.advance(); + if ( + state.eat(0x7B /* { */) && + this.regexp_eatUnicodePropertyValueExpression(state) && + state.eat(0x7D /* } */) + ) { + return true + } + state.raise("Invalid property name"); + } + + return false + }; + function isCharacterClassEscape(ch) { + return ( + ch === 0x64 /* d */ || + ch === 0x44 /* D */ || + ch === 0x73 /* s */ || + ch === 0x53 /* S */ || + ch === 0x77 /* w */ || + ch === 0x57 /* W */ + ) } - return true -}; -// Object type used to represent tokens. Note that normally, tokens -// simply exist as properties on the parser object. This is only -// used for the onToken callback and the external tokenizer. + // UnicodePropertyValueExpression :: + // UnicodePropertyName `=` UnicodePropertyValue + // LoneUnicodePropertyNameOrValue + pp$8.regexp_eatUnicodePropertyValueExpression = function(state) { + var start = state.pos; -var Token = function Token(p) { - this.type = p.type; - this.value = p.value; - this.start = p.start; - this.end = p.end; - if (p.options.locations) - { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } - if (p.options.ranges) - { this.range = [p.start, p.end]; } -}; + // UnicodePropertyName `=` UnicodePropertyValue + if (this.regexp_eatUnicodePropertyName(state) && state.eat(0x3D /* = */)) { + var name = state.lastStringValue; + if (this.regexp_eatUnicodePropertyValue(state)) { + var value = state.lastStringValue; + this.regexp_validateUnicodePropertyNameAndValue(state, name, value); + return true + } + } + state.pos = start; -// ## Tokenizer + // LoneUnicodePropertyNameOrValue + if (this.regexp_eatLoneUnicodePropertyNameOrValue(state)) { + var nameOrValue = state.lastStringValue; + this.regexp_validateUnicodePropertyNameOrValue(state, nameOrValue); + return true + } + return false + }; + pp$8.regexp_validateUnicodePropertyNameAndValue = function(state, name, value) { + if (!has(state.unicodeProperties.nonBinary, name)) + { state.raise("Invalid property name"); } + if (!state.unicodeProperties.nonBinary[name].test(value)) + { state.raise("Invalid property value"); } + }; + pp$8.regexp_validateUnicodePropertyNameOrValue = function(state, nameOrValue) { + if (!state.unicodeProperties.binary.test(nameOrValue)) + { state.raise("Invalid property name"); } + }; -var pp$8 = Parser.prototype; + // UnicodePropertyName :: + // UnicodePropertyNameCharacters + pp$8.regexp_eatUnicodePropertyName = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyNameCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + function isUnicodePropertyNameCharacter(ch) { + return isControlLetter(ch) || ch === 0x5F /* _ */ + } -// Move to the next token + // UnicodePropertyValue :: + // UnicodePropertyValueCharacters + pp$8.regexp_eatUnicodePropertyValue = function(state) { + var ch = 0; + state.lastStringValue = ""; + while (isUnicodePropertyValueCharacter(ch = state.current())) { + state.lastStringValue += codePointToString(ch); + state.advance(); + } + return state.lastStringValue !== "" + }; + function isUnicodePropertyValueCharacter(ch) { + return isUnicodePropertyNameCharacter(ch) || isDecimalDigit(ch) + } -pp$8.next = function() { - if (this.options.onToken) - { this.options.onToken(new Token(this)); } + // LoneUnicodePropertyNameOrValue :: + // UnicodePropertyValueCharacters + pp$8.regexp_eatLoneUnicodePropertyNameOrValue = function(state) { + return this.regexp_eatUnicodePropertyValue(state) + }; - this.lastTokEnd = this.end; - this.lastTokStart = this.start; - this.lastTokEndLoc = this.endLoc; - this.lastTokStartLoc = this.startLoc; - this.nextToken(); -}; + // https://www.ecma-international.org/ecma-262/8.0/#prod-CharacterClass + pp$8.regexp_eatCharacterClass = function(state) { + if (state.eat(0x5B /* [ */)) { + state.eat(0x5E /* ^ */); + this.regexp_classRanges(state); + if (state.eat(0x5D /* [ */)) { + return true + } + // Unreachable since it threw "unterminated regular expression" error before. + state.raise("Unterminated character class"); + } + return false + }; -pp$8.getToken = function() { - this.next(); - return new Token(this) -}; - -// If we're in an ES6 environment, make parsers iterable -if (typeof Symbol !== "undefined") - { pp$8[Symbol.iterator] = function() { - var this$1 = this; - - return { - next: function () { - var token = this$1.getToken(); - return { - done: token.type === types.eof, - value: token + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRanges + // https://www.ecma-international.org/ecma-262/8.0/#prod-NonemptyClassRangesNoDash + pp$8.regexp_classRanges = function(state) { + while (this.regexp_eatClassAtom(state)) { + var left = state.lastIntValue; + if (state.eat(0x2D /* - */) && this.regexp_eatClassAtom(state)) { + var right = state.lastIntValue; + if (state.switchU && (left === -1 || right === -1)) { + state.raise("Invalid character class"); + } + if (left !== -1 && right !== -1 && left > right) { + state.raise("Range out of order in character class"); } } } - }; } + }; -// Toggle strict mode. Re-reads the next number or string to please -// pedantic tests (`"use strict"; 010;` should fail). + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtom + // https://www.ecma-international.org/ecma-262/8.0/#prod-ClassAtomNoDash + pp$8.regexp_eatClassAtom = function(state) { + var start = state.pos; -pp$8.curContext = function() { - return this.context[this.context.length - 1] -}; - -// Read a single token, updating the parser object's token-related -// properties. - -pp$8.nextToken = function() { - var curContext = this.curContext(); - if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } - - this.start = this.pos; - if (this.options.locations) { this.startLoc = this.curPosition(); } - if (this.pos >= this.input.length) { return this.finishToken(types.eof) } - - if (curContext.override) { return curContext.override(this) } - else { this.readToken(this.fullCharCodeAtPos()); } -}; - -pp$8.readToken = function(code) { - // Identifier or keyword. '\uXXXX' sequences are allowed in - // identifiers, so '\' also dispatches to that. - if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) - { return this.readWord() } - - return this.getTokenFromCode(code) -}; - -pp$8.fullCharCodeAtPos = function() { - var code = this.input.charCodeAt(this.pos); - if (code <= 0xd7ff || code >= 0xe000) { return code } - var next = this.input.charCodeAt(this.pos + 1); - return (code << 10) + next - 0x35fdc00 -}; - -pp$8.skipBlockComment = function() { - var this$1 = this; - - var startLoc = this.options.onComment && this.curPosition(); - var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); - if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } - this.pos = end + 2; - if (this.options.locations) { - lineBreakG.lastIndex = start; - var match; - while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { - ++this$1.curLine; - this$1.lineStart = match.index + match[0].length; + if (state.eat(0x5C /* \ */)) { + if (this.regexp_eatClassEscape(state)) { + return true + } + if (state.switchU) { + // Make the same message as V8. + var ch$1 = state.current(); + if (ch$1 === 0x63 /* c */ || isOctalDigit(ch$1)) { + state.raise("Invalid class escape"); + } + state.raise("Invalid escape"); + } + state.pos = start; } - } - if (this.options.onComment) - { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, - startLoc, this.curPosition()); } -}; -pp$8.skipLineComment = function(startSkip) { - var this$1 = this; + var ch = state.current(); + if (ch !== 0x5D /* [ */) { + state.lastIntValue = ch; + state.advance(); + return true + } - var start = this.pos; - var startLoc = this.options.onComment && this.curPosition(); - var ch = this.input.charCodeAt(this.pos += startSkip); - while (this.pos < this.input.length && !isNewLine(ch)) { - ch = this$1.input.charCodeAt(++this$1.pos); - } - if (this.options.onComment) - { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, - startLoc, this.curPosition()); } -}; + return false + }; -// Called at the start of the parse and after every token. Skips -// whitespace and comments, and. + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassEscape + pp$8.regexp_eatClassEscape = function(state) { + var start = state.pos; -pp$8.skipSpace = function() { - var this$1 = this; + if (state.eat(0x62 /* b */)) { + state.lastIntValue = 0x08; /* <BS> */ + return true + } - loop: while (this.pos < this.input.length) { - var ch = this$1.input.charCodeAt(this$1.pos); - switch (ch) { - case 32: case 160: // ' ' - ++this$1.pos; - break - case 13: - if (this$1.input.charCodeAt(this$1.pos + 1) === 10) { - ++this$1.pos; + if (state.switchU && state.eat(0x2D /* - */)) { + state.lastIntValue = 0x2D; /* - */ + return true + } + + if (!state.switchU && state.eat(0x63 /* c */)) { + if (this.regexp_eatClassControlLetter(state)) { + return true } - case 10: case 8232: case 8233: - ++this$1.pos; - if (this$1.options.locations) { - ++this$1.curLine; - this$1.lineStart = this$1.pos; + state.pos = start; + } + + return ( + this.regexp_eatCharacterClassEscape(state) || + this.regexp_eatCharacterEscape(state) + ) + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-ClassControlLetter + pp$8.regexp_eatClassControlLetter = function(state) { + var ch = state.current(); + if (isDecimalDigit(ch) || ch === 0x5F /* _ */) { + state.lastIntValue = ch % 0x20; + state.advance(); + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$8.regexp_eatHexEscapeSequence = function(state) { + var start = state.pos; + if (state.eat(0x78 /* x */)) { + if (this.regexp_eatFixedHexDigits(state, 2)) { + return true } - break - case 47: // '/' - switch (this$1.input.charCodeAt(this$1.pos + 1)) { - case 42: // '*' - this$1.skipBlockComment(); + if (state.switchU) { + state.raise("Invalid escape"); + } + state.pos = start; + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-DecimalDigits + pp$8.regexp_eatDecimalDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isDecimalDigit(ch = state.current())) { + state.lastIntValue = 10 * state.lastIntValue + (ch - 0x30 /* 0 */); + state.advance(); + } + return state.pos !== start + }; + function isDecimalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigits + pp$8.regexp_eatHexDigits = function(state) { + var start = state.pos; + var ch = 0; + state.lastIntValue = 0; + while (isHexDigit(ch = state.current())) { + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return state.pos !== start + }; + function isHexDigit(ch) { + return ( + (ch >= 0x30 /* 0 */ && ch <= 0x39 /* 9 */) || + (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) || + (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) + ) + } + function hexToInt(ch) { + if (ch >= 0x41 /* A */ && ch <= 0x46 /* F */) { + return 10 + (ch - 0x41 /* A */) + } + if (ch >= 0x61 /* a */ && ch <= 0x66 /* f */) { + return 10 + (ch - 0x61 /* a */) + } + return ch - 0x30 /* 0 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-annexB-LegacyOctalEscapeSequence + // Allows only 0-377(octal) i.e. 0-255(decimal). + pp$8.regexp_eatLegacyOctalEscapeSequence = function(state) { + if (this.regexp_eatOctalDigit(state)) { + var n1 = state.lastIntValue; + if (this.regexp_eatOctalDigit(state)) { + var n2 = state.lastIntValue; + if (n1 <= 3 && this.regexp_eatOctalDigit(state)) { + state.lastIntValue = n1 * 64 + n2 * 8 + state.lastIntValue; + } else { + state.lastIntValue = n1 * 8 + n2; + } + } else { + state.lastIntValue = n1; + } + return true + } + return false + }; + + // https://www.ecma-international.org/ecma-262/8.0/#prod-OctalDigit + pp$8.regexp_eatOctalDigit = function(state) { + var ch = state.current(); + if (isOctalDigit(ch)) { + state.lastIntValue = ch - 0x30; /* 0 */ + state.advance(); + return true + } + state.lastIntValue = 0; + return false + }; + function isOctalDigit(ch) { + return ch >= 0x30 /* 0 */ && ch <= 0x37 /* 7 */ + } + + // https://www.ecma-international.org/ecma-262/8.0/#prod-Hex4Digits + // https://www.ecma-international.org/ecma-262/8.0/#prod-HexDigit + // And HexDigit HexDigit in https://www.ecma-international.org/ecma-262/8.0/#prod-HexEscapeSequence + pp$8.regexp_eatFixedHexDigits = function(state, length) { + var start = state.pos; + state.lastIntValue = 0; + for (var i = 0; i < length; ++i) { + var ch = state.current(); + if (!isHexDigit(ch)) { + state.pos = start; + return false + } + state.lastIntValue = 16 * state.lastIntValue + hexToInt(ch); + state.advance(); + } + return true + }; + + // Object type used to represent tokens. Note that normally, tokens + // simply exist as properties on the parser object. This is only + // used for the onToken callback and the external tokenizer. + + var Token = function Token(p) { + this.type = p.type; + this.value = p.value; + this.start = p.start; + this.end = p.end; + if (p.options.locations) + { this.loc = new SourceLocation(p, p.startLoc, p.endLoc); } + if (p.options.ranges) + { this.range = [p.start, p.end]; } + }; + + // ## Tokenizer + + var pp$9 = Parser.prototype; + + // Move to the next token + + pp$9.next = function() { + if (this.options.onToken) + { this.options.onToken(new Token(this)); } + + this.lastTokEnd = this.end; + this.lastTokStart = this.start; + this.lastTokEndLoc = this.endLoc; + this.lastTokStartLoc = this.startLoc; + this.nextToken(); + }; + + pp$9.getToken = function() { + this.next(); + return new Token(this) + }; + + // If we're in an ES6 environment, make parsers iterable + if (typeof Symbol !== "undefined") + { pp$9[Symbol.iterator] = function() { + var this$1 = this; + + return { + next: function () { + var token = this$1.getToken(); + return { + done: token.type === types.eof, + value: token + } + } + } + }; } + + // Toggle strict mode. Re-reads the next number or string to please + // pedantic tests (`"use strict"; 010;` should fail). + + pp$9.curContext = function() { + return this.context[this.context.length - 1] + }; + + // Read a single token, updating the parser object's token-related + // properties. + + pp$9.nextToken = function() { + var curContext = this.curContext(); + if (!curContext || !curContext.preserveSpace) { this.skipSpace(); } + + this.start = this.pos; + if (this.options.locations) { this.startLoc = this.curPosition(); } + if (this.pos >= this.input.length) { return this.finishToken(types.eof) } + + if (curContext.override) { return curContext.override(this) } + else { this.readToken(this.fullCharCodeAtPos()); } + }; + + pp$9.readToken = function(code) { + // Identifier or keyword. '\uXXXX' sequences are allowed in + // identifiers, so '\' also dispatches to that. + if (isIdentifierStart(code, this.options.ecmaVersion >= 6) || code === 92 /* '\' */) + { return this.readWord() } + + return this.getTokenFromCode(code) + }; + + pp$9.fullCharCodeAtPos = function() { + var code = this.input.charCodeAt(this.pos); + if (code <= 0xd7ff || code >= 0xe000) { return code } + var next = this.input.charCodeAt(this.pos + 1); + return (code << 10) + next - 0x35fdc00 + }; + + pp$9.skipBlockComment = function() { + var startLoc = this.options.onComment && this.curPosition(); + var start = this.pos, end = this.input.indexOf("*/", this.pos += 2); + if (end === -1) { this.raise(this.pos - 2, "Unterminated comment"); } + this.pos = end + 2; + if (this.options.locations) { + lineBreakG.lastIndex = start; + var match; + while ((match = lineBreakG.exec(this.input)) && match.index < this.pos) { + ++this.curLine; + this.lineStart = match.index + match[0].length; + } + } + if (this.options.onComment) + { this.options.onComment(true, this.input.slice(start + 2, end), start, this.pos, + startLoc, this.curPosition()); } + }; + + pp$9.skipLineComment = function(startSkip) { + var start = this.pos; + var startLoc = this.options.onComment && this.curPosition(); + var ch = this.input.charCodeAt(this.pos += startSkip); + while (this.pos < this.input.length && !isNewLine(ch)) { + ch = this.input.charCodeAt(++this.pos); + } + if (this.options.onComment) + { this.options.onComment(false, this.input.slice(start + startSkip, this.pos), start, this.pos, + startLoc, this.curPosition()); } + }; + + // Called at the start of the parse and after every token. Skips + // whitespace and comments, and. + + pp$9.skipSpace = function() { + loop: while (this.pos < this.input.length) { + var ch = this.input.charCodeAt(this.pos); + switch (ch) { + case 32: case 160: // ' ' + ++this.pos; break - case 47: - this$1.skipLineComment(2); + case 13: + if (this.input.charCodeAt(this.pos + 1) === 10) { + ++this.pos; + } + case 10: case 8232: case 8233: + ++this.pos; + if (this.options.locations) { + ++this.curLine; + this.lineStart = this.pos; + } + break + case 47: // '/' + switch (this.input.charCodeAt(this.pos + 1)) { + case 42: // '*' + this.skipBlockComment(); + break + case 47: + this.skipLineComment(2); + break + default: + break loop + } break default: - break loop - } - break - default: - if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { - ++this$1.pos; - } else { - break loop + if (ch > 8 && ch < 14 || ch >= 5760 && nonASCIIwhitespace.test(String.fromCharCode(ch))) { + ++this.pos; + } else { + break loop + } } } - } -}; + }; -// Called at the end of every token. Sets `end`, `val`, and -// maintains `context` and `exprAllowed`, and skips the space after -// the token, so that the next one's `start` will point at the -// right position. + // Called at the end of every token. Sets `end`, `val`, and + // maintains `context` and `exprAllowed`, and skips the space after + // the token, so that the next one's `start` will point at the + // right position. -pp$8.finishToken = function(type, val) { - this.end = this.pos; - if (this.options.locations) { this.endLoc = this.curPosition(); } - var prevType = this.type; - this.type = type; - this.value = val; + pp$9.finishToken = function(type, val) { + this.end = this.pos; + if (this.options.locations) { this.endLoc = this.curPosition(); } + var prevType = this.type; + this.type = type; + this.value = val; - this.updateContext(prevType); -}; + this.updateContext(prevType); + }; -// ### Token reading + // ### Token reading -// This is the function that is called to fetch the next token. It -// is somewhat obscure, because it works in character codes rather -// than characters, and because operator parsing has been inlined -// into it. -// -// All in the name of speed. -// -pp$8.readToken_dot = function() { - var next = this.input.charCodeAt(this.pos + 1); - if (next >= 48 && next <= 57) { return this.readNumber(true) } - var next2 = this.input.charCodeAt(this.pos + 2); - if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' - this.pos += 3; - return this.finishToken(types.ellipsis) - } else { - ++this.pos; - return this.finishToken(types.dot) - } -}; + // This is the function that is called to fetch the next token. It + // is somewhat obscure, because it works in character codes rather + // than characters, and because operator parsing has been inlined + // into it. + // + // All in the name of speed. + // + pp$9.readToken_dot = function() { + var next = this.input.charCodeAt(this.pos + 1); + if (next >= 48 && next <= 57) { return this.readNumber(true) } + var next2 = this.input.charCodeAt(this.pos + 2); + if (this.options.ecmaVersion >= 6 && next === 46 && next2 === 46) { // 46 = dot '.' + this.pos += 3; + return this.finishToken(types.ellipsis) + } else { + ++this.pos; + return this.finishToken(types.dot) + } + }; -pp$8.readToken_slash = function() { // '/' - var next = this.input.charCodeAt(this.pos + 1); - if (this.exprAllowed) { ++this.pos; return this.readRegexp() } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.slash, 1) -}; + pp$9.readToken_slash = function() { // '/' + var next = this.input.charCodeAt(this.pos + 1); + if (this.exprAllowed) { ++this.pos; return this.readRegexp() } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.slash, 1) + }; -pp$8.readToken_mult_modulo_exp = function(code) { // '%*' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - var tokentype = code === 42 ? types.star : types.modulo; + pp$9.readToken_mult_modulo_exp = function(code) { // '%*' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + var tokentype = code === 42 ? types.star : types.modulo; - // exponentiation operator ** and **= - if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { - ++size; - tokentype = types.starstar; - next = this.input.charCodeAt(this.pos + 2); - } + // exponentiation operator ** and **= + if (this.options.ecmaVersion >= 7 && code === 42 && next === 42) { + ++size; + tokentype = types.starstar; + next = this.input.charCodeAt(this.pos + 2); + } - if (next === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(tokentype, size) -}; + if (next === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(tokentype, size) + }; -pp$8.readToken_pipe_amp = function(code) { // '|&' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) -}; + pp$9.readToken_pipe_amp = function(code) { // '|&' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { return this.finishOp(code === 124 ? types.logicalOR : types.logicalAND, 2) } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(code === 124 ? types.bitwiseOR : types.bitwiseAND, 1) + }; -pp$8.readToken_caret = function() { // '^' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.bitwiseXOR, 1) -}; + pp$9.readToken_caret = function() { // '^' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.bitwiseXOR, 1) + }; -pp$8.readToken_plus_min = function(code) { // '+-' - var next = this.input.charCodeAt(this.pos + 1); - if (next === code) { - if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && - (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { - // A `-->` line comment - this.skipLineComment(3); + pp$9.readToken_plus_min = function(code) { // '+-' + var next = this.input.charCodeAt(this.pos + 1); + if (next === code) { + if (next === 45 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 62 && + (this.lastTokEnd === 0 || lineBreak.test(this.input.slice(this.lastTokEnd, this.pos)))) { + // A `-->` line comment + this.skipLineComment(3); + this.skipSpace(); + return this.nextToken() + } + return this.finishOp(types.incDec, 2) + } + if (next === 61) { return this.finishOp(types.assign, 2) } + return this.finishOp(types.plusMin, 1) + }; + + pp$9.readToken_lt_gt = function(code) { // '<>' + var next = this.input.charCodeAt(this.pos + 1); + var size = 1; + if (next === code) { + size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; + if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } + return this.finishOp(types.bitShift, size) + } + if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && + this.input.charCodeAt(this.pos + 3) === 45) { + // `<!--`, an XML-style comment that should be interpreted as a line comment + this.skipLineComment(4); this.skipSpace(); return this.nextToken() } - return this.finishOp(types.incDec, 2) - } - if (next === 61) { return this.finishOp(types.assign, 2) } - return this.finishOp(types.plusMin, 1) -}; + if (next === 61) { size = 2; } + return this.finishOp(types.relational, size) + }; -pp$8.readToken_lt_gt = function(code) { // '<>' - var next = this.input.charCodeAt(this.pos + 1); - var size = 1; - if (next === code) { - size = code === 62 && this.input.charCodeAt(this.pos + 2) === 62 ? 3 : 2; - if (this.input.charCodeAt(this.pos + size) === 61) { return this.finishOp(types.assign, size + 1) } - return this.finishOp(types.bitShift, size) - } - if (next === 33 && code === 60 && !this.inModule && this.input.charCodeAt(this.pos + 2) === 45 && - this.input.charCodeAt(this.pos + 3) === 45) { - // `<!--`, an XML-style comment that should be interpreted as a line comment - this.skipLineComment(4); - this.skipSpace(); - return this.nextToken() - } - if (next === 61) { size = 2; } - return this.finishOp(types.relational, size) -}; - -pp$8.readToken_eq_excl = function(code) { // '=!' - var next = this.input.charCodeAt(this.pos + 1); - if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } - if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' - this.pos += 2; - return this.finishToken(types.arrow) - } - return this.finishOp(code === 61 ? types.eq : types.prefix, 1) -}; - -pp$8.getTokenFromCode = function(code) { - switch (code) { - // The interpretation of a dot depends on whether it is followed - // by a digit or another two dots. - case 46: // '.' - return this.readToken_dot() - - // Punctuation tokens. - case 40: ++this.pos; return this.finishToken(types.parenL) - case 41: ++this.pos; return this.finishToken(types.parenR) - case 59: ++this.pos; return this.finishToken(types.semi) - case 44: ++this.pos; return this.finishToken(types.comma) - case 91: ++this.pos; return this.finishToken(types.bracketL) - case 93: ++this.pos; return this.finishToken(types.bracketR) - case 123: ++this.pos; return this.finishToken(types.braceL) - case 125: ++this.pos; return this.finishToken(types.braceR) - case 58: ++this.pos; return this.finishToken(types.colon) - case 63: ++this.pos; return this.finishToken(types.question) - - case 96: // '`' - if (this.options.ecmaVersion < 6) { break } - ++this.pos; - return this.finishToken(types.backQuote) - - case 48: // '0' + pp$9.readToken_eq_excl = function(code) { // '=!' var next = this.input.charCodeAt(this.pos + 1); - if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number - if (this.options.ecmaVersion >= 6) { - if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number - if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number + if (next === 61) { return this.finishOp(types.equality, this.input.charCodeAt(this.pos + 2) === 61 ? 3 : 2) } + if (code === 61 && next === 62 && this.options.ecmaVersion >= 6) { // '=>' + this.pos += 2; + return this.finishToken(types.arrow) + } + return this.finishOp(code === 61 ? types.eq : types.prefix, 1) + }; + + pp$9.getTokenFromCode = function(code) { + switch (code) { + // The interpretation of a dot depends on whether it is followed + // by a digit or another two dots. + case 46: // '.' + return this.readToken_dot() + + // Punctuation tokens. + case 40: ++this.pos; return this.finishToken(types.parenL) + case 41: ++this.pos; return this.finishToken(types.parenR) + case 59: ++this.pos; return this.finishToken(types.semi) + case 44: ++this.pos; return this.finishToken(types.comma) + case 91: ++this.pos; return this.finishToken(types.bracketL) + case 93: ++this.pos; return this.finishToken(types.bracketR) + case 123: ++this.pos; return this.finishToken(types.braceL) + case 125: ++this.pos; return this.finishToken(types.braceR) + case 58: ++this.pos; return this.finishToken(types.colon) + case 63: ++this.pos; return this.finishToken(types.question) + + case 96: // '`' + if (this.options.ecmaVersion < 6) { break } + ++this.pos; + return this.finishToken(types.backQuote) + + case 48: // '0' + var next = this.input.charCodeAt(this.pos + 1); + if (next === 120 || next === 88) { return this.readRadixNumber(16) } // '0x', '0X' - hex number + if (this.options.ecmaVersion >= 6) { + if (next === 111 || next === 79) { return this.readRadixNumber(8) } // '0o', '0O' - octal number + if (next === 98 || next === 66) { return this.readRadixNumber(2) } // '0b', '0B' - binary number + } + + // Anything else beginning with a digit is an integer, octal + // number, or float. + case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 + return this.readNumber(false) + + // Quotes produce strings. + case 34: case 39: // '"', "'" + return this.readString(code) + + // Operators are parsed inline in tiny state machines. '=' (61) is + // often referred to. `finishOp` simply skips the amount of + // characters it is given as second argument, and returns a token + // of the type given by its first argument. + + case 47: // '/' + return this.readToken_slash() + + case 37: case 42: // '%*' + return this.readToken_mult_modulo_exp(code) + + case 124: case 38: // '|&' + return this.readToken_pipe_amp(code) + + case 94: // '^' + return this.readToken_caret() + + case 43: case 45: // '+-' + return this.readToken_plus_min(code) + + case 60: case 62: // '<>' + return this.readToken_lt_gt(code) + + case 61: case 33: // '=!' + return this.readToken_eq_excl(code) + + case 126: // '~' + return this.finishOp(types.prefix, 1) } - // Anything else beginning with a digit is an integer, octal - // number, or float. - case 49: case 50: case 51: case 52: case 53: case 54: case 55: case 56: case 57: // 1-9 - return this.readNumber(false) + this.raise(this.pos, "Unexpected character '" + codePointToString$1(code) + "'"); + }; - // Quotes produce strings. - case 34: case 39: // '"', "'" - return this.readString(code) + pp$9.finishOp = function(type, size) { + var str = this.input.slice(this.pos, this.pos + size); + this.pos += size; + return this.finishToken(type, str) + }; - // Operators are parsed inline in tiny state machines. '=' (61) is - // often referred to. `finishOp` simply skips the amount of - // characters it is given as second argument, and returns a token - // of the type given by its first argument. - - case 47: // '/' - return this.readToken_slash() - - case 37: case 42: // '%*' - return this.readToken_mult_modulo_exp(code) - - case 124: case 38: // '|&' - return this.readToken_pipe_amp(code) - - case 94: // '^' - return this.readToken_caret() - - case 43: case 45: // '+-' - return this.readToken_plus_min(code) - - case 60: case 62: // '<>' - return this.readToken_lt_gt(code) - - case 61: case 33: // '=!' - return this.readToken_eq_excl(code) - - case 126: // '~' - return this.finishOp(types.prefix, 1) - } - - this.raise(this.pos, "Unexpected character '" + codePointToString(code) + "'"); -}; - -pp$8.finishOp = function(type, size) { - var str = this.input.slice(this.pos, this.pos + size); - this.pos += size; - return this.finishToken(type, str) -}; - -pp$8.readRegexp = function() { - var this$1 = this; - - var escaped, inClass, start = this.pos; - for (;;) { - if (this$1.pos >= this$1.input.length) { this$1.raise(start, "Unterminated regular expression"); } - var ch = this$1.input.charAt(this$1.pos); - if (lineBreak.test(ch)) { this$1.raise(start, "Unterminated regular expression"); } - if (!escaped) { - if (ch === "[") { inClass = true; } - else if (ch === "]" && inClass) { inClass = false; } - else if (ch === "/" && !inClass) { break } - escaped = ch === "\\"; - } else { escaped = false; } - ++this$1.pos; - } - var pattern = this.input.slice(start, this.pos); - ++this.pos; - var flagsStart = this.pos; - var flags = this.readWord1(); - if (this.containsEsc) { this.unexpected(flagsStart); } - - // Validate pattern - var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); - state.reset(start, pattern, flags); - this.validateRegExpFlags(state); - this.validateRegExpPattern(state); - - // Create Literal#value property value. - var value = null; - try { - value = new RegExp(pattern, flags); - } catch (e) { - // ESTree requires null if it failed to instantiate RegExp object. - // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral - } - - return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value}) -}; - -// Read an integer in the given radix. Return null if zero digits -// were read, the integer value otherwise. When `len` is given, this -// will return `null` unless the integer has exactly `len` digits. - -pp$8.readInt = function(radix, len) { - var this$1 = this; - - var start = this.pos, total = 0; - for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { - var code = this$1.input.charCodeAt(this$1.pos), val = (void 0); - if (code >= 97) { val = code - 97 + 10; } // a - else if (code >= 65) { val = code - 65 + 10; } // A - else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 - else { val = Infinity; } - if (val >= radix) { break } - ++this$1.pos; - total = total * radix + val; - } - if (this.pos === start || len != null && this.pos - start !== len) { return null } - - return total -}; - -pp$8.readRadixNumber = function(radix) { - this.pos += 2; // 0x - var val = this.readInt(radix); - if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } - if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } - return this.finishToken(types.num, val) -}; - -// Read an integer, octal integer, or floating-point number. - -pp$8.readNumber = function(startsWithDot) { - var start = this.pos; - if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); } - var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; - if (octal && this.strict) { this.raise(start, "Invalid number"); } - if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } - var next = this.input.charCodeAt(this.pos); - if (next === 46 && !octal) { // '.' + pp$9.readRegexp = function() { + var escaped, inClass, start = this.pos; + for (;;) { + if (this.pos >= this.input.length) { this.raise(start, "Unterminated regular expression"); } + var ch = this.input.charAt(this.pos); + if (lineBreak.test(ch)) { this.raise(start, "Unterminated regular expression"); } + if (!escaped) { + if (ch === "[") { inClass = true; } + else if (ch === "]" && inClass) { inClass = false; } + else if (ch === "/" && !inClass) { break } + escaped = ch === "\\"; + } else { escaped = false; } + ++this.pos; + } + var pattern = this.input.slice(start, this.pos); ++this.pos; - this.readInt(10); - next = this.input.charCodeAt(this.pos); - } - if ((next === 69 || next === 101) && !octal) { // 'eE' - next = this.input.charCodeAt(++this.pos); - if (next === 43 || next === 45) { ++this.pos; } // '+-' - if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } - } - if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } + var flagsStart = this.pos; + var flags = this.readWord1(); + if (this.containsEsc) { this.unexpected(flagsStart); } - var str = this.input.slice(start, this.pos); - var val = octal ? parseInt(str, 8) : parseFloat(str); - return this.finishToken(types.num, val) -}; + // Validate pattern + var state = this.regexpState || (this.regexpState = new RegExpValidationState(this)); + state.reset(start, pattern, flags); + this.validateRegExpFlags(state); + this.validateRegExpPattern(state); -// Read a string value, interpreting backslash-escapes. - -pp$8.readCodePoint = function() { - var ch = this.input.charCodeAt(this.pos), code; - - if (ch === 123) { // '{' - if (this.options.ecmaVersion < 6) { this.unexpected(); } - var codePos = ++this.pos; - code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); - ++this.pos; - if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } - } else { - code = this.readHexChar(4); - } - return code -}; - -function codePointToString(code) { - // UTF-16 Decoding - if (code <= 0xFFFF) { return String.fromCharCode(code) } - code -= 0x10000; - return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) -} - -pp$8.readString = function(quote) { - var this$1 = this; - - var out = "", chunkStart = ++this.pos; - for (;;) { - if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated string constant"); } - var ch = this$1.input.charCodeAt(this$1.pos); - if (ch === quote) { break } - if (ch === 92) { // '\' - out += this$1.input.slice(chunkStart, this$1.pos); - out += this$1.readEscapedChar(false); - chunkStart = this$1.pos; - } else { - if (isNewLine(ch, this$1.options.ecmaVersion >= 10)) { this$1.raise(this$1.start, "Unterminated string constant"); } - ++this$1.pos; + // Create Literal#value property value. + var value = null; + try { + value = new RegExp(pattern, flags); + } catch (e) { + // ESTree requires null if it failed to instantiate RegExp object. + // https://github.com/estree/estree/blob/a27003adf4fd7bfad44de9cef372a2eacd527b1c/es5.md#regexpliteral } - } - out += this.input.slice(chunkStart, this.pos++); - return this.finishToken(types.string, out) -}; -// Reads template string tokens. + return this.finishToken(types.regexp, {pattern: pattern, flags: flags, value: value}) + }; -var INVALID_TEMPLATE_ESCAPE_ERROR = {}; + // Read an integer in the given radix. Return null if zero digits + // were read, the integer value otherwise. When `len` is given, this + // will return `null` unless the integer has exactly `len` digits. -pp$8.tryReadTemplateToken = function() { - this.inTemplateElement = true; - try { - this.readTmplToken(); - } catch (err) { - if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { - this.readInvalidTemplateToken(); - } else { - throw err + pp$9.readInt = function(radix, len) { + var start = this.pos, total = 0; + for (var i = 0, e = len == null ? Infinity : len; i < e; ++i) { + var code = this.input.charCodeAt(this.pos), val = (void 0); + if (code >= 97) { val = code - 97 + 10; } // a + else if (code >= 65) { val = code - 65 + 10; } // A + else if (code >= 48 && code <= 57) { val = code - 48; } // 0-9 + else { val = Infinity; } + if (val >= radix) { break } + ++this.pos; + total = total * radix + val; } + if (this.pos === start || len != null && this.pos - start !== len) { return null } + + return total + }; + + pp$9.readRadixNumber = function(radix) { + var start = this.pos; + this.pos += 2; // 0x + var val = this.readInt(radix); + if (val == null) { this.raise(this.start + 2, "Expected number in radix " + radix); } + if (this.options.ecmaVersion >= 11 && this.input.charCodeAt(this.pos) === 110) { + val = typeof BigInt !== "undefined" ? BigInt(this.input.slice(start, this.pos)) : null; + ++this.pos; + } else if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } + return this.finishToken(types.num, val) + }; + + // Read an integer, octal integer, or floating-point number. + + pp$9.readNumber = function(startsWithDot) { + var start = this.pos; + if (!startsWithDot && this.readInt(10) === null) { this.raise(start, "Invalid number"); } + var octal = this.pos - start >= 2 && this.input.charCodeAt(start) === 48; + if (octal && this.strict) { this.raise(start, "Invalid number"); } + if (octal && /[89]/.test(this.input.slice(start, this.pos))) { octal = false; } + var next = this.input.charCodeAt(this.pos); + if (!octal && !startsWithDot && this.options.ecmaVersion >= 11 && next === 110) { + var str$1 = this.input.slice(start, this.pos); + var val$1 = typeof BigInt !== "undefined" ? BigInt(str$1) : null; + ++this.pos; + if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } + return this.finishToken(types.num, val$1) + } + if (next === 46 && !octal) { // '.' + ++this.pos; + this.readInt(10); + next = this.input.charCodeAt(this.pos); + } + if ((next === 69 || next === 101) && !octal) { // 'eE' + next = this.input.charCodeAt(++this.pos); + if (next === 43 || next === 45) { ++this.pos; } // '+-' + if (this.readInt(10) === null) { this.raise(start, "Invalid number"); } + } + if (isIdentifierStart(this.fullCharCodeAtPos())) { this.raise(this.pos, "Identifier directly after number"); } + + var str = this.input.slice(start, this.pos); + var val = octal ? parseInt(str, 8) : parseFloat(str); + return this.finishToken(types.num, val) + }; + + // Read a string value, interpreting backslash-escapes. + + pp$9.readCodePoint = function() { + var ch = this.input.charCodeAt(this.pos), code; + + if (ch === 123) { // '{' + if (this.options.ecmaVersion < 6) { this.unexpected(); } + var codePos = ++this.pos; + code = this.readHexChar(this.input.indexOf("}", this.pos) - this.pos); + ++this.pos; + if (code > 0x10FFFF) { this.invalidStringToken(codePos, "Code point out of bounds"); } + } else { + code = this.readHexChar(4); + } + return code + }; + + function codePointToString$1(code) { + // UTF-16 Decoding + if (code <= 0xFFFF) { return String.fromCharCode(code) } + code -= 0x10000; + return String.fromCharCode((code >> 10) + 0xD800, (code & 1023) + 0xDC00) } - this.inTemplateElement = false; -}; + pp$9.readString = function(quote) { + var out = "", chunkStart = ++this.pos; + for (;;) { + if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated string constant"); } + var ch = this.input.charCodeAt(this.pos); + if (ch === quote) { break } + if (ch === 92) { // '\' + out += this.input.slice(chunkStart, this.pos); + out += this.readEscapedChar(false); + chunkStart = this.pos; + } else { + if (isNewLine(ch, this.options.ecmaVersion >= 10)) { this.raise(this.start, "Unterminated string constant"); } + ++this.pos; + } + } + out += this.input.slice(chunkStart, this.pos++); + return this.finishToken(types.string, out) + }; -pp$8.invalidStringToken = function(position, message) { - if (this.inTemplateElement && this.options.ecmaVersion >= 9) { - throw INVALID_TEMPLATE_ESCAPE_ERROR - } else { - this.raise(position, message); - } -}; + // Reads template string tokens. -pp$8.readTmplToken = function() { - var this$1 = this; + var INVALID_TEMPLATE_ESCAPE_ERROR = {}; - var out = "", chunkStart = this.pos; - for (;;) { - if (this$1.pos >= this$1.input.length) { this$1.raise(this$1.start, "Unterminated template"); } - var ch = this$1.input.charCodeAt(this$1.pos); - if (ch === 96 || ch === 36 && this$1.input.charCodeAt(this$1.pos + 1) === 123) { // '`', '${' - if (this$1.pos === this$1.start && (this$1.type === types.template || this$1.type === types.invalidTemplate)) { - if (ch === 36) { - this$1.pos += 2; - return this$1.finishToken(types.dollarBraceL) - } else { - ++this$1.pos; - return this$1.finishToken(types.backQuote) + pp$9.tryReadTemplateToken = function() { + this.inTemplateElement = true; + try { + this.readTmplToken(); + } catch (err) { + if (err === INVALID_TEMPLATE_ESCAPE_ERROR) { + this.readInvalidTemplateToken(); + } else { + throw err + } + } + + this.inTemplateElement = false; + }; + + pp$9.invalidStringToken = function(position, message) { + if (this.inTemplateElement && this.options.ecmaVersion >= 9) { + throw INVALID_TEMPLATE_ESCAPE_ERROR + } else { + this.raise(position, message); + } + }; + + pp$9.readTmplToken = function() { + var out = "", chunkStart = this.pos; + for (;;) { + if (this.pos >= this.input.length) { this.raise(this.start, "Unterminated template"); } + var ch = this.input.charCodeAt(this.pos); + if (ch === 96 || ch === 36 && this.input.charCodeAt(this.pos + 1) === 123) { // '`', '${' + if (this.pos === this.start && (this.type === types.template || this.type === types.invalidTemplate)) { + if (ch === 36) { + this.pos += 2; + return this.finishToken(types.dollarBraceL) + } else { + ++this.pos; + return this.finishToken(types.backQuote) + } } + out += this.input.slice(chunkStart, this.pos); + return this.finishToken(types.template, out) } - out += this$1.input.slice(chunkStart, this$1.pos); - return this$1.finishToken(types.template, out) + if (ch === 92) { // '\' + out += this.input.slice(chunkStart, this.pos); + out += this.readEscapedChar(true); + chunkStart = this.pos; + } else if (isNewLine(ch)) { + out += this.input.slice(chunkStart, this.pos); + ++this.pos; + switch (ch) { + case 13: + if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } + case 10: + out += "\n"; + break + default: + out += String.fromCharCode(ch); + break + } + if (this.options.locations) { + ++this.curLine; + this.lineStart = this.pos; + } + chunkStart = this.pos; + } else { + ++this.pos; + } } - if (ch === 92) { // '\' - out += this$1.input.slice(chunkStart, this$1.pos); - out += this$1.readEscapedChar(true); - chunkStart = this$1.pos; - } else if (isNewLine(ch)) { - out += this$1.input.slice(chunkStart, this$1.pos); - ++this$1.pos; - switch (ch) { - case 13: - if (this$1.input.charCodeAt(this$1.pos) === 10) { ++this$1.pos; } - case 10: - out += "\n"; + }; + + // Reads a template token to search for the end, without validating any escape sequences + pp$9.readInvalidTemplateToken = function() { + for (; this.pos < this.input.length; this.pos++) { + switch (this.input[this.pos]) { + case "\\": + ++this.pos; break - default: - out += String.fromCharCode(ch); + + case "$": + if (this.input[this.pos + 1] !== "{") { + break + } + // falls through + + case "`": + return this.finishToken(types.invalidTemplate, this.input.slice(this.start, this.pos)) + + // no default + } + } + this.raise(this.start, "Unterminated template"); + }; + + // Used to read escaped characters + + pp$9.readEscapedChar = function(inTemplate) { + var ch = this.input.charCodeAt(++this.pos); + ++this.pos; + switch (ch) { + case 110: return "\n" // 'n' -> '\n' + case 114: return "\r" // 'r' -> '\r' + case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' + case 117: return codePointToString$1(this.readCodePoint()) // 'u' + case 116: return "\t" // 't' -> '\t' + case 98: return "\b" // 'b' -> '\b' + case 118: return "\u000b" // 'v' -> '\u000b' + case 102: return "\f" // 'f' -> '\f' + case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' + case 10: // ' \n' + if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } + return "" + default: + if (ch >= 48 && ch <= 55) { + var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; + var octal = parseInt(octalStr, 8); + if (octal > 255) { + octalStr = octalStr.slice(0, -1); + octal = parseInt(octalStr, 8); + } + this.pos += octalStr.length - 1; + ch = this.input.charCodeAt(this.pos); + if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { + this.invalidStringToken( + this.pos - 1 - octalStr.length, + inTemplate + ? "Octal literal in template string" + : "Octal literal in strict mode" + ); + } + return String.fromCharCode(octal) + } + if (isNewLine(ch)) { + // Unicode new line characters after \ get removed from output in both + // template literals and strings + return "" + } + return String.fromCharCode(ch) + } + }; + + // Used to read character escape sequences ('\x', '\u', '\U'). + + pp$9.readHexChar = function(len) { + var codePos = this.pos; + var n = this.readInt(16, len); + if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } + return n + }; + + // Read an identifier, and return it as a string. Sets `this.containsEsc` + // to whether the word contained a '\u' escape. + // + // Incrementally adds only escaped chars, adding other chunks as-is + // as a micro-optimization. + + pp$9.readWord1 = function() { + this.containsEsc = false; + var word = "", first = true, chunkStart = this.pos; + var astral = this.options.ecmaVersion >= 6; + while (this.pos < this.input.length) { + var ch = this.fullCharCodeAtPos(); + if (isIdentifierChar(ch, astral)) { + this.pos += ch <= 0xffff ? 1 : 2; + } else if (ch === 92) { // "\" + this.containsEsc = true; + word += this.input.slice(chunkStart, this.pos); + var escStart = this.pos; + if (this.input.charCodeAt(++this.pos) !== 117) // "u" + { this.invalidStringToken(this.pos, "Expecting Unicode escape sequence \\uXXXX"); } + ++this.pos; + var esc = this.readCodePoint(); + if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) + { this.invalidStringToken(escStart, "Invalid Unicode escape"); } + word += codePointToString$1(esc); + chunkStart = this.pos; + } else { break } - if (this$1.options.locations) { - ++this$1.curLine; - this$1.lineStart = this$1.pos; - } - chunkStart = this$1.pos; - } else { - ++this$1.pos; + first = false; } - } -}; + return word + this.input.slice(chunkStart, this.pos) + }; -// Reads a template token to search for the end, without validating any escape sequences -pp$8.readInvalidTemplateToken = function() { - var this$1 = this; + // Read an identifier or keyword token. Will check for reserved + // words when necessary. - for (; this.pos < this.input.length; this.pos++) { - switch (this$1.input[this$1.pos]) { - case "\\": - ++this$1.pos; - break - - case "$": - if (this$1.input[this$1.pos + 1] !== "{") { - break - } - // falls through - - case "`": - return this$1.finishToken(types.invalidTemplate, this$1.input.slice(this$1.start, this$1.pos)) - - // no default + pp$9.readWord = function() { + var word = this.readWord1(); + var type = types.name; + if (this.keywords.test(word)) { + if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); } + type = keywords$1[word]; } + return this.finishToken(type, word) + }; + + // Acorn is a tiny, fast JavaScript parser written in JavaScript. + + var version = "7.1.0"; + + Parser.acorn = { + Parser: Parser, + version: version, + defaultOptions: defaultOptions, + Position: Position, + SourceLocation: SourceLocation, + getLineInfo: getLineInfo, + Node: Node, + TokenType: TokenType, + tokTypes: types, + keywordTypes: keywords$1, + TokContext: TokContext, + tokContexts: types$1, + isIdentifierChar: isIdentifierChar, + isIdentifierStart: isIdentifierStart, + Token: Token, + isNewLine: isNewLine, + lineBreak: lineBreak, + lineBreakG: lineBreakG, + nonASCIIwhitespace: nonASCIIwhitespace + }; + + // The main exported interface (under `self.acorn` when in the + // browser) is a `parse` function that takes a code string and + // returns an abstract syntax tree as specified by [Mozilla parser + // API][api]. + // + // [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API + + function parse(input, options) { + return Parser.parse(input, options) } - this.raise(this.start, "Unterminated template"); -}; -// Used to read escaped characters + // This function tries to parse a single expression at a given + // offset in a string. Useful for parsing mixed-language formats + // that embed JavaScript expressions. -pp$8.readEscapedChar = function(inTemplate) { - var ch = this.input.charCodeAt(++this.pos); - ++this.pos; - switch (ch) { - case 110: return "\n" // 'n' -> '\n' - case 114: return "\r" // 'r' -> '\r' - case 120: return String.fromCharCode(this.readHexChar(2)) // 'x' - case 117: return codePointToString(this.readCodePoint()) // 'u' - case 116: return "\t" // 't' -> '\t' - case 98: return "\b" // 'b' -> '\b' - case 118: return "\u000b" // 'v' -> '\u000b' - case 102: return "\f" // 'f' -> '\f' - case 13: if (this.input.charCodeAt(this.pos) === 10) { ++this.pos; } // '\r\n' - case 10: // ' \n' - if (this.options.locations) { this.lineStart = this.pos; ++this.curLine; } - return "" - default: - if (ch >= 48 && ch <= 55) { - var octalStr = this.input.substr(this.pos - 1, 3).match(/^[0-7]+/)[0]; - var octal = parseInt(octalStr, 8); - if (octal > 255) { - octalStr = octalStr.slice(0, -1); - octal = parseInt(octalStr, 8); - } - this.pos += octalStr.length - 1; - ch = this.input.charCodeAt(this.pos); - if ((octalStr !== "0" || ch === 56 || ch === 57) && (this.strict || inTemplate)) { - this.invalidStringToken( - this.pos - 1 - octalStr.length, - inTemplate - ? "Octal literal in template string" - : "Octal literal in strict mode" - ); - } - return String.fromCharCode(octal) - } - return String.fromCharCode(ch) + function parseExpressionAt(input, pos, options) { + return Parser.parseExpressionAt(input, pos, options) } -}; -// Used to read character escape sequences ('\x', '\u', '\U'). + // Acorn is organized as a tokenizer and a recursive-descent parser. + // The `tokenizer` export provides an interface to the tokenizer. -pp$8.readHexChar = function(len) { - var codePos = this.pos; - var n = this.readInt(16, len); - if (n === null) { this.invalidStringToken(codePos, "Bad character escape sequence"); } - return n -}; - -// Read an identifier, and return it as a string. Sets `this.containsEsc` -// to whether the word contained a '\u' escape. -// -// Incrementally adds only escaped chars, adding other chunks as-is -// as a micro-optimization. - -pp$8.readWord1 = function() { - var this$1 = this; - - this.containsEsc = false; - var word = "", first = true, chunkStart = this.pos; - var astral = this.options.ecmaVersion >= 6; - while (this.pos < this.input.length) { - var ch = this$1.fullCharCodeAtPos(); - if (isIdentifierChar(ch, astral)) { - this$1.pos += ch <= 0xffff ? 1 : 2; - } else if (ch === 92) { // "\" - this$1.containsEsc = true; - word += this$1.input.slice(chunkStart, this$1.pos); - var escStart = this$1.pos; - if (this$1.input.charCodeAt(++this$1.pos) !== 117) // "u" - { this$1.invalidStringToken(this$1.pos, "Expecting Unicode escape sequence \\uXXXX"); } - ++this$1.pos; - var esc = this$1.readCodePoint(); - if (!(first ? isIdentifierStart : isIdentifierChar)(esc, astral)) - { this$1.invalidStringToken(escStart, "Invalid Unicode escape"); } - word += codePointToString(esc); - chunkStart = this$1.pos; - } else { - break - } - first = false; + function tokenizer(input, options) { + return Parser.tokenizer(input, options) } - return word + this.input.slice(chunkStart, this.pos) -}; -// Read an identifier or keyword token. Will check for reserved -// words when necessary. + exports.Node = Node; + exports.Parser = Parser; + exports.Position = Position; + exports.SourceLocation = SourceLocation; + exports.TokContext = TokContext; + exports.Token = Token; + exports.TokenType = TokenType; + exports.defaultOptions = defaultOptions; + exports.getLineInfo = getLineInfo; + exports.isIdentifierChar = isIdentifierChar; + exports.isIdentifierStart = isIdentifierStart; + exports.isNewLine = isNewLine; + exports.keywordTypes = keywords$1; + exports.lineBreak = lineBreak; + exports.lineBreakG = lineBreakG; + exports.nonASCIIwhitespace = nonASCIIwhitespace; + exports.parse = parse; + exports.parseExpressionAt = parseExpressionAt; + exports.tokContexts = types$1; + exports.tokTypes = types; + exports.tokenizer = tokenizer; + exports.version = version; -pp$8.readWord = function() { - var word = this.readWord1(); - var type = types.name; - if (this.keywords.test(word)) { - if (this.containsEsc) { this.raiseRecoverable(this.start, "Escape sequence in keyword " + word); } - type = keywords$1[word]; - } - return this.finishToken(type, word) -}; + Object.defineProperty(exports, '__esModule', { value: true }); -// Acorn is a tiny, fast JavaScript parser written in JavaScript. -// -// Acorn was written by Marijn Haverbeke, Ingvar Stepanyan, and -// various contributors and released under an MIT license. -// -// Git repositories for Acorn are available at -// -// http://marijnhaverbeke.nl/git/acorn -// https://github.com/acornjs/acorn.git -// -// Please use the [github bug tracker][ghbt] to report issues. -// -// [ghbt]: https://github.com/acornjs/acorn/issues -// -// [walk]: util/walk.js - -var version = "6.0.1"; - -// The main exported interface (under `self.acorn` when in the -// browser) is a `parse` function that takes a code string and -// returns an abstract syntax tree as specified by [Mozilla parser -// API][api]. -// -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API - -function parse(input, options) { - return Parser.parse(input, options) -} - -// This function tries to parse a single expression at a given -// offset in a string. Useful for parsing mixed-language formats -// that embed JavaScript expressions. - -function parseExpressionAt(input, pos, options) { - return Parser.parseExpressionAt(input, pos, options) -} - -// Acorn is organized as a tokenizer and a recursive-descent parser. -// The `tokenizer` export provides an interface to the tokenizer. - -function tokenizer(input, options) { - return Parser.tokenizer(input, options) -} - -exports.version = version; -exports.parse = parse; -exports.parseExpressionAt = parseExpressionAt; -exports.tokenizer = tokenizer; -exports.Parser = Parser; -exports.defaultOptions = defaultOptions; -exports.Position = Position; -exports.SourceLocation = SourceLocation; -exports.getLineInfo = getLineInfo; -exports.Node = Node; -exports.TokenType = TokenType; -exports.tokTypes = types; -exports.keywordTypes = keywords$1; -exports.TokContext = TokContext; -exports.tokContexts = types$1; -exports.isIdentifierChar = isIdentifierChar; -exports.isIdentifierStart = isIdentifierStart; -exports.Token = Token; -exports.isNewLine = isNewLine; -exports.lineBreak = lineBreak; -exports.lineBreakG = lineBreakG; -exports.nonASCIIwhitespace = nonASCIIwhitespace; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); +})); // clang-format on
diff --git a/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js b/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js index 5038bc17..90bb8b4 100644 --- a/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js +++ b/third_party/blink/renderer/devtools/front_end/formatter_worker/acorn/acorn_loose.js
@@ -2,1430 +2,1384 @@ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('acorn')) : typeof define === 'function' && define.amd ? define(['exports', 'acorn'], factory) : - (factory((global.acorn = global.acorn || {}, global.acorn.loose = {}),global.acorn)); -}(this, (function (exports,acorn) { 'use strict'; + (global = global || self, factory((global.acorn = global.acorn || {}, global.acorn.loose = {}), global.acorn)); +}(this, function (exports, acorn) { 'use strict'; -function noop() {} + function noop() {} -var LooseParser = function LooseParser(input, options) { - if ( options === void 0 ) options = {}; + var LooseParser = function LooseParser(input, options) { + if ( options === void 0 ) options = {}; - this.toks = this.constructor.BaseParser.tokenizer(input, options); - this.options = this.toks.options; - this.input = this.toks.input; - this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0}; - this.tok.validateRegExpFlags = noop; - this.tok.validateRegExpPattern = noop; - if (this.options.locations) { - var here = this.toks.curPosition(); - this.tok.loc = new acorn.SourceLocation(this.toks, here, here); - } - this.ahead = []; // Tokens ahead - this.context = []; // Indentation contexted - this.curIndent = 0; - this.curLineStart = 0; - this.nextLineStart = this.lineEnd(this.curLineStart) + 1; - this.inAsync = false; - this.inFunction = false; -}; - -LooseParser.prototype.startNode = function startNode () { - return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) -}; - -LooseParser.prototype.storeCurrentPos = function storeCurrentPos () { - return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start -}; - -LooseParser.prototype.startNodeAt = function startNodeAt (pos) { - if (this.options.locations) { - return new acorn.Node(this.toks, pos[0], pos[1]) - } else { - return new acorn.Node(this.toks, pos) - } -}; - -LooseParser.prototype.finishNode = function finishNode (node, type) { - node.type = type; - node.end = this.last.end; - if (this.options.locations) - { node.loc.end = this.last.loc.end; } - if (this.options.ranges) - { node.range[1] = this.last.end; } - return node -}; - -LooseParser.prototype.dummyNode = function dummyNode (type) { - var dummy = this.startNode(); - dummy.type = type; - dummy.end = dummy.start; - if (this.options.locations) - { dummy.loc.end = dummy.loc.start; } - if (this.options.ranges) - { dummy.range[1] = dummy.start; } - this.last = {type: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc}; - return dummy -}; - -LooseParser.prototype.dummyIdent = function dummyIdent () { - var dummy = this.dummyNode("Identifier"); - dummy.name = "✖"; - return dummy -}; - -LooseParser.prototype.dummyString = function dummyString () { - var dummy = this.dummyNode("Literal"); - dummy.value = dummy.raw = "✖"; - return dummy -}; - -LooseParser.prototype.eat = function eat (type) { - if (this.tok.type === type) { - this.next(); - return true - } else { - return false - } -}; - -LooseParser.prototype.isContextual = function isContextual (name) { - return this.tok.type === acorn.tokTypes.name && this.tok.value === name -}; - -LooseParser.prototype.eatContextual = function eatContextual (name) { - return this.tok.value === name && this.eat(acorn.tokTypes.name) -}; - -LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () { - return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR || - acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start)) -}; - -LooseParser.prototype.semicolon = function semicolon () { - return this.eat(acorn.tokTypes.semi) -}; - -LooseParser.prototype.expect = function expect (type) { - var this$1 = this; - - if (this.eat(type)) { return true } - for (var i = 1; i <= 2; i++) { - if (this$1.lookAhead(i).type === type) { - for (var j = 0; j < i; j++) { this$1.next(); } - return true + this.toks = this.constructor.BaseParser.tokenizer(input, options); + this.options = this.toks.options; + this.input = this.toks.input; + this.tok = this.last = {type: acorn.tokTypes.eof, start: 0, end: 0}; + this.tok.validateRegExpFlags = noop; + this.tok.validateRegExpPattern = noop; + if (this.options.locations) { + var here = this.toks.curPosition(); + this.tok.loc = new acorn.SourceLocation(this.toks, here, here); } - } -}; + this.ahead = []; // Tokens ahead + this.context = []; // Indentation contexted + this.curIndent = 0; + this.curLineStart = 0; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + this.inAsync = false; + this.inFunction = false; + }; -LooseParser.prototype.pushCx = function pushCx () { - this.context.push(this.curIndent); -}; + LooseParser.prototype.startNode = function startNode () { + return new acorn.Node(this.toks, this.tok.start, this.options.locations ? this.tok.loc.start : null) + }; -LooseParser.prototype.popCx = function popCx () { - this.curIndent = this.context.pop(); -}; + LooseParser.prototype.storeCurrentPos = function storeCurrentPos () { + return this.options.locations ? [this.tok.start, this.tok.loc.start] : this.tok.start + }; -LooseParser.prototype.lineEnd = function lineEnd (pos) { - while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; } - return pos -}; - -LooseParser.prototype.indentationAfter = function indentationAfter (pos) { - var this$1 = this; - - for (var count = 0;; ++pos) { - var ch = this$1.input.charCodeAt(pos); - if (ch === 32) { ++count; } - else if (ch === 9) { count += this$1.options.tabSize; } - else { return count } - } -}; - -LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) { - if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true } - return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && - (!blockHeuristic || this.nextLineStart >= this.input.length || - this.indentationAfter(this.nextLineStart) < indent) -}; - -LooseParser.prototype.tokenStartsLine = function tokenStartsLine () { - var this$1 = this; - - for (var p = this.tok.start - 1; p >= this.curLineStart; --p) { - var ch = this$1.input.charCodeAt(p); - if (ch !== 9 && ch !== 32) { return false } - } - return true -}; - -LooseParser.prototype.extend = function extend (name, f) { - this[name] = f(this[name]); -}; - -LooseParser.prototype.parse = function parse () { - this.next(); - return this.parseTopLevel() -}; - -LooseParser.extend = function extend () { - var plugins = [], len = arguments.length; - while ( len-- ) plugins[ len ] = arguments[ len ]; - - var cls = this; - for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } - return cls -}; - -LooseParser.parse = function parse (input, options) { - return new this(input, options).parse() -}; - -// Allows plugins to extend the base parser / tokenizer used -LooseParser.BaseParser = acorn.Parser; - -var lp = LooseParser.prototype; - -function isSpace(ch) { - return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch) -} - -lp.next = function() { - var this$1 = this; - - this.last = this.tok; - if (this.ahead.length) - { this.tok = this.ahead.shift(); } - else - { this.tok = this.readToken(); } - - if (this.tok.start >= this.nextLineStart) { - while (this.tok.start >= this.nextLineStart) { - this$1.curLineStart = this$1.nextLineStart; - this$1.nextLineStart = this$1.lineEnd(this$1.curLineStart) + 1; - } - this.curIndent = this.indentationAfter(this.curLineStart); - } -}; - -lp.readToken = function() { - var this$1 = this; - - for (;;) { - try { - this$1.toks.next(); - if (this$1.toks.type === acorn.tokTypes.dot && - this$1.input.substr(this$1.toks.end, 1) === "." && - this$1.options.ecmaVersion >= 6) { - this$1.toks.end++; - this$1.toks.type = acorn.tokTypes.ellipsis; - } - return new acorn.Token(this$1.toks) - } catch (e) { - if (!(e instanceof SyntaxError)) { throw e } - - // Try to skip some text, based on the error message, and then continue - var msg = e.message, pos = e.raisedAt, replace = true; - if (/unterminated/i.test(msg)) { - pos = this$1.lineEnd(e.pos + 1); - if (/string/.test(msg)) { - replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this$1.input.slice(e.pos + 1, pos)}; - } else if (/regular expr/i.test(msg)) { - var re = this$1.input.slice(e.pos, pos); - try { re = new RegExp(re); } catch (e) { /* ignore compilation error due to new syntax */ } - replace = {start: e.pos, end: pos, type: acorn.tokTypes.regexp, value: re}; - } else if (/template/.test(msg)) { - replace = { - start: e.pos, - end: pos, - type: acorn.tokTypes.template, - value: this$1.input.slice(e.pos, pos) - }; - } else { - replace = false; - } - } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) { - while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; } - } else if (/character escape|expected hexadecimal/i.test(msg)) { - while (pos < this.input.length) { - var ch = this$1.input.charCodeAt(pos++); - if (ch === 34 || ch === 39 || acorn.isNewLine(ch)) { break } - } - } else if (/unexpected character/i.test(msg)) { - pos++; - replace = false; - } else if (/regular expression/i.test(msg)) { - replace = true; - } else { - throw e - } - this$1.resetTo(pos); - if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: "✖"}; } - if (replace) { - if (this$1.options.locations) - { replace.loc = new acorn.SourceLocation( - this$1.toks, - acorn.getLineInfo(this$1.input, replace.start), - acorn.getLineInfo(this$1.input, replace.end)); } - return replace - } - } - } -}; - -lp.resetTo = function(pos) { - var this$1 = this; - - this.toks.pos = pos; - var ch = this.input.charAt(pos - 1); - this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || - /[enwfd]/.test(ch) && - /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)); - - if (this.options.locations) { - this.toks.curLine = 1; - this.toks.lineStart = acorn.lineBreakG.lastIndex = 0; - var match; - while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) { - ++this$1.toks.curLine; - this$1.toks.lineStart = match.index + match[0].length; - } - } -}; - -lp.lookAhead = function(n) { - var this$1 = this; - - while (n > this.ahead.length) - { this$1.ahead.push(this$1.readToken()); } - return this.ahead[n - 1] -}; - -function isDummy(node) { return node.name === "✖" } - -var lp$1 = LooseParser.prototype; - -lp$1.parseTopLevel = function() { - var this$1 = this; - - var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0); - node.body = []; - while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this$1.parseStatement()); } - this.toks.adaptDirectivePrologue(node.body); - this.last = this.tok; - if (this.options.ecmaVersion >= 6) { - node.sourceType = this.options.sourceType; - } - return this.finishNode(node, "Program") -}; - -lp$1.parseStatement = function() { - var this$1 = this; - - var starttype = this.tok.type, node = this.startNode(), kind; - - if (this.toks.isLet()) { - starttype = acorn.tokTypes._var; - kind = "let"; - } - - switch (starttype) { - case acorn.tokTypes._break: case acorn.tokTypes._continue: - this.next(); - var isBreak = starttype === acorn.tokTypes._break; - if (this.semicolon() || this.canInsertSemicolon()) { - node.label = null; + LooseParser.prototype.startNodeAt = function startNodeAt (pos) { + if (this.options.locations) { + return new acorn.Node(this.toks, pos[0], pos[1]) } else { - node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null; - this.semicolon(); + return new acorn.Node(this.toks, pos) } - return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + }; - case acorn.tokTypes._debugger: + LooseParser.prototype.finishNode = function finishNode (node, type) { + node.type = type; + node.end = this.last.end; + if (this.options.locations) + { node.loc.end = this.last.loc.end; } + if (this.options.ranges) + { node.range[1] = this.last.end; } + return node + }; + + LooseParser.prototype.dummyNode = function dummyNode (type) { + var dummy = this.startNode(); + dummy.type = type; + dummy.end = dummy.start; + if (this.options.locations) + { dummy.loc.end = dummy.loc.start; } + if (this.options.ranges) + { dummy.range[1] = dummy.start; } + this.last = {type: acorn.tokTypes.name, start: dummy.start, end: dummy.start, loc: dummy.loc}; + return dummy + }; + + LooseParser.prototype.dummyIdent = function dummyIdent () { + var dummy = this.dummyNode("Identifier"); + dummy.name = "✖"; + return dummy + }; + + LooseParser.prototype.dummyString = function dummyString () { + var dummy = this.dummyNode("Literal"); + dummy.value = dummy.raw = "✖"; + return dummy + }; + + LooseParser.prototype.eat = function eat (type) { + if (this.tok.type === type) { + this.next(); + return true + } else { + return false + } + }; + + LooseParser.prototype.isContextual = function isContextual (name) { + return this.tok.type === acorn.tokTypes.name && this.tok.value === name + }; + + LooseParser.prototype.eatContextual = function eatContextual (name) { + return this.tok.value === name && this.eat(acorn.tokTypes.name) + }; + + LooseParser.prototype.canInsertSemicolon = function canInsertSemicolon () { + return this.tok.type === acorn.tokTypes.eof || this.tok.type === acorn.tokTypes.braceR || + acorn.lineBreak.test(this.input.slice(this.last.end, this.tok.start)) + }; + + LooseParser.prototype.semicolon = function semicolon () { + return this.eat(acorn.tokTypes.semi) + }; + + LooseParser.prototype.expect = function expect (type) { + if (this.eat(type)) { return true } + for (var i = 1; i <= 2; i++) { + if (this.lookAhead(i).type === type) { + for (var j = 0; j < i; j++) { this.next(); } + return true + } + } + }; + + LooseParser.prototype.pushCx = function pushCx () { + this.context.push(this.curIndent); + }; + + LooseParser.prototype.popCx = function popCx () { + this.curIndent = this.context.pop(); + }; + + LooseParser.prototype.lineEnd = function lineEnd (pos) { + while (pos < this.input.length && !acorn.isNewLine(this.input.charCodeAt(pos))) { ++pos; } + return pos + }; + + LooseParser.prototype.indentationAfter = function indentationAfter (pos) { + for (var count = 0;; ++pos) { + var ch = this.input.charCodeAt(pos); + if (ch === 32) { ++count; } + else if (ch === 9) { count += this.options.tabSize; } + else { return count } + } + }; + + LooseParser.prototype.closes = function closes (closeTok, indent, line, blockHeuristic) { + if (this.tok.type === closeTok || this.tok.type === acorn.tokTypes.eof) { return true } + return line !== this.curLineStart && this.curIndent < indent && this.tokenStartsLine() && + (!blockHeuristic || this.nextLineStart >= this.input.length || + this.indentationAfter(this.nextLineStart) < indent) + }; + + LooseParser.prototype.tokenStartsLine = function tokenStartsLine () { + for (var p = this.tok.start - 1; p >= this.curLineStart; --p) { + var ch = this.input.charCodeAt(p); + if (ch !== 9 && ch !== 32) { return false } + } + return true + }; + + LooseParser.prototype.extend = function extend (name, f) { + this[name] = f(this[name]); + }; + + LooseParser.prototype.parse = function parse () { this.next(); - this.semicolon(); - return this.finishNode(node, "DebuggerStatement") + return this.parseTopLevel() + }; - case acorn.tokTypes._do: - this.next(); - node.body = this.parseStatement(); - node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent(); - this.semicolon(); - return this.finishNode(node, "DoWhileStatement") + LooseParser.extend = function extend () { + var plugins = [], len = arguments.length; + while ( len-- ) plugins[ len ] = arguments[ len ]; - case acorn.tokTypes._for: - this.next(); // `for` keyword - var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await"); + var cls = this; + for (var i = 0; i < plugins.length; i++) { cls = plugins[i](cls); } + return cls + }; - this.pushCx(); - this.expect(acorn.tokTypes.parenL); - if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) } - var isLet = this.toks.isLet(); - if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const) { - var init$1 = this.parseVar(this.startNode(), true, isLet ? "let" : this.tok.value); - if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) { + LooseParser.parse = function parse (input, options) { + return new this(input, options).parse() + }; + + // Allows plugins to extend the base parser / tokenizer used + LooseParser.BaseParser = acorn.Parser; + + var lp = LooseParser.prototype; + + function isSpace(ch) { + return (ch < 14 && ch > 8) || ch === 32 || ch === 160 || acorn.isNewLine(ch) + } + + lp.next = function() { + this.last = this.tok; + if (this.ahead.length) + { this.tok = this.ahead.shift(); } + else + { this.tok = this.readToken(); } + + if (this.tok.start >= this.nextLineStart) { + while (this.tok.start >= this.nextLineStart) { + this.curLineStart = this.nextLineStart; + this.nextLineStart = this.lineEnd(this.curLineStart) + 1; + } + this.curIndent = this.indentationAfter(this.curLineStart); + } + }; + + lp.readToken = function() { + for (;;) { + try { + this.toks.next(); + if (this.toks.type === acorn.tokTypes.dot && + this.input.substr(this.toks.end, 1) === "." && + this.options.ecmaVersion >= 6) { + this.toks.end++; + this.toks.type = acorn.tokTypes.ellipsis; + } + return new acorn.Token(this.toks) + } catch (e) { + if (!(e instanceof SyntaxError)) { throw e } + + // Try to skip some text, based on the error message, and then continue + var msg = e.message, pos = e.raisedAt, replace = true; + if (/unterminated/i.test(msg)) { + pos = this.lineEnd(e.pos + 1); + if (/string/.test(msg)) { + replace = {start: e.pos, end: pos, type: acorn.tokTypes.string, value: this.input.slice(e.pos + 1, pos)}; + } else if (/regular expr/i.test(msg)) { + var re = this.input.slice(e.pos, pos); + try { re = new RegExp(re); } catch (e) { /* ignore compilation error due to new syntax */ } + replace = {start: e.pos, end: pos, type: acorn.tokTypes.regexp, value: re}; + } else if (/template/.test(msg)) { + replace = { + start: e.pos, + end: pos, + type: acorn.tokTypes.template, + value: this.input.slice(e.pos, pos) + }; + } else { + replace = false; + } + } else if (/invalid (unicode|regexp|number)|expecting unicode|octal literal|is reserved|directly after number|expected number in radix/i.test(msg)) { + while (pos < this.input.length && !isSpace(this.input.charCodeAt(pos))) { ++pos; } + } else if (/character escape|expected hexadecimal/i.test(msg)) { + while (pos < this.input.length) { + var ch = this.input.charCodeAt(pos++); + if (ch === 34 || ch === 39 || acorn.isNewLine(ch)) { break } + } + } else if (/unexpected character/i.test(msg)) { + pos++; + replace = false; + } else if (/regular expression/i.test(msg)) { + replace = true; + } else { + throw e + } + this.resetTo(pos); + if (replace === true) { replace = {start: pos, end: pos, type: acorn.tokTypes.name, value: "✖"}; } + if (replace) { + if (this.options.locations) + { replace.loc = new acorn.SourceLocation( + this.toks, + acorn.getLineInfo(this.input, replace.start), + acorn.getLineInfo(this.input, replace.end)); } + return replace + } + } + } + }; + + lp.resetTo = function(pos) { + this.toks.pos = pos; + var ch = this.input.charAt(pos - 1); + this.toks.exprAllowed = !ch || /[[{(,;:?/*=+\-~!|&%^<>]/.test(ch) || + /[enwfd]/.test(ch) && + /\b(case|else|return|throw|new|in|(instance|type)?of|delete|void)$/.test(this.input.slice(pos - 10, pos)); + + if (this.options.locations) { + this.toks.curLine = 1; + this.toks.lineStart = acorn.lineBreakG.lastIndex = 0; + var match; + while ((match = acorn.lineBreakG.exec(this.input)) && match.index < pos) { + ++this.toks.curLine; + this.toks.lineStart = match.index + match[0].length; + } + } + }; + + lp.lookAhead = function(n) { + while (n > this.ahead.length) + { this.ahead.push(this.readToken()); } + return this.ahead[n - 1] + }; + + function isDummy(node) { return node.name === "✖" } + + var lp$1 = LooseParser.prototype; + + lp$1.parseTopLevel = function() { + var node = this.startNodeAt(this.options.locations ? [0, acorn.getLineInfo(this.input, 0)] : 0); + node.body = []; + while (this.tok.type !== acorn.tokTypes.eof) { node.body.push(this.parseStatement()); } + this.toks.adaptDirectivePrologue(node.body); + this.last = this.tok; + node.sourceType = this.options.sourceType; + return this.finishNode(node, "Program") + }; + + lp$1.parseStatement = function() { + var starttype = this.tok.type, node = this.startNode(), kind; + + if (this.toks.isLet()) { + starttype = acorn.tokTypes._var; + kind = "let"; + } + + switch (starttype) { + case acorn.tokTypes._break: case acorn.tokTypes._continue: + this.next(); + var isBreak = starttype === acorn.tokTypes._break; + if (this.semicolon() || this.canInsertSemicolon()) { + node.label = null; + } else { + node.label = this.tok.type === acorn.tokTypes.name ? this.parseIdent() : null; + this.semicolon(); + } + return this.finishNode(node, isBreak ? "BreakStatement" : "ContinueStatement") + + case acorn.tokTypes._debugger: + this.next(); + this.semicolon(); + return this.finishNode(node, "DebuggerStatement") + + case acorn.tokTypes._do: + this.next(); + node.body = this.parseStatement(); + node.test = this.eat(acorn.tokTypes._while) ? this.parseParenExpression() : this.dummyIdent(); + this.semicolon(); + return this.finishNode(node, "DoWhileStatement") + + case acorn.tokTypes._for: + this.next(); // `for` keyword + var isAwait = this.options.ecmaVersion >= 9 && this.inAsync && this.eatContextual("await"); + + this.pushCx(); + this.expect(acorn.tokTypes.parenL); + if (this.tok.type === acorn.tokTypes.semi) { return this.parseFor(node, null) } + var isLet = this.toks.isLet(); + if (isLet || this.tok.type === acorn.tokTypes._var || this.tok.type === acorn.tokTypes._const) { + var init$1 = this.parseVar(this.startNode(), true, isLet ? "let" : this.tok.value); + if (init$1.declarations.length === 1 && (this.tok.type === acorn.tokTypes._in || this.isContextual("of"))) { + if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) { + node.await = isAwait; + } + return this.parseForIn(node, init$1) + } + return this.parseFor(node, init$1) + } + var init = this.parseExpression(true); + if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) { if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) { node.await = isAwait; } - return this.parseForIn(node, init$1) + return this.parseForIn(node, this.toAssignable(init)) } - return this.parseFor(node, init$1) - } - var init = this.parseExpression(true); - if (this.tok.type === acorn.tokTypes._in || this.isContextual("of")) { - if (this.options.ecmaVersion >= 9 && this.tok.type !== acorn.tokTypes._in) { - node.await = isAwait; + return this.parseFor(node, init) + + case acorn.tokTypes._function: + this.next(); + return this.parseFunction(node, true) + + case acorn.tokTypes._if: + this.next(); + node.test = this.parseParenExpression(); + node.consequent = this.parseStatement(); + node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null; + return this.finishNode(node, "IfStatement") + + case acorn.tokTypes._return: + this.next(); + if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; } + else { node.argument = this.parseExpression(); this.semicolon(); } + return this.finishNode(node, "ReturnStatement") + + case acorn.tokTypes._switch: + var blockIndent = this.curIndent, line = this.curLineStart; + this.next(); + node.discriminant = this.parseParenExpression(); + node.cases = []; + this.pushCx(); + this.expect(acorn.tokTypes.braceL); + + var cur; + while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) { + if (this.tok.type === acorn.tokTypes._case || this.tok.type === acorn.tokTypes._default) { + var isCase = this.tok.type === acorn.tokTypes._case; + if (cur) { this.finishNode(cur, "SwitchCase"); } + node.cases.push(cur = this.startNode()); + cur.consequent = []; + this.next(); + if (isCase) { cur.test = this.parseExpression(); } + else { cur.test = null; } + this.expect(acorn.tokTypes.colon); + } else { + if (!cur) { + node.cases.push(cur = this.startNode()); + cur.consequent = []; + cur.test = null; + } + cur.consequent.push(this.parseStatement()); + } } - return this.parseForIn(node, this.toAssignable(init)) + if (cur) { this.finishNode(cur, "SwitchCase"); } + this.popCx(); + this.eat(acorn.tokTypes.braceR); + return this.finishNode(node, "SwitchStatement") + + case acorn.tokTypes._throw: + this.next(); + node.argument = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ThrowStatement") + + case acorn.tokTypes._try: + this.next(); + node.block = this.parseBlock(); + node.handler = null; + if (this.tok.type === acorn.tokTypes._catch) { + var clause = this.startNode(); + this.next(); + if (this.eat(acorn.tokTypes.parenL)) { + clause.param = this.toAssignable(this.parseExprAtom(), true); + this.expect(acorn.tokTypes.parenR); + } else { + clause.param = null; + } + clause.body = this.parseBlock(); + node.handler = this.finishNode(clause, "CatchClause"); + } + node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null; + if (!node.handler && !node.finalizer) { return node.block } + return this.finishNode(node, "TryStatement") + + case acorn.tokTypes._var: + case acorn.tokTypes._const: + return this.parseVar(node, false, kind || this.tok.value) + + case acorn.tokTypes._while: + this.next(); + node.test = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WhileStatement") + + case acorn.tokTypes._with: + this.next(); + node.object = this.parseParenExpression(); + node.body = this.parseStatement(); + return this.finishNode(node, "WithStatement") + + case acorn.tokTypes.braceL: + return this.parseBlock() + + case acorn.tokTypes.semi: + this.next(); + return this.finishNode(node, "EmptyStatement") + + case acorn.tokTypes._class: + return this.parseClass(true) + + case acorn.tokTypes._import: + if (this.options.ecmaVersion > 10 && this.lookAhead(1).type === acorn.tokTypes.parenL) { + node.expression = this.parseExpression(); + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } + + return this.parseImport() + + case acorn.tokTypes._export: + return this.parseExport() + + default: + if (this.toks.isAsyncFunction()) { + this.next(); + this.next(); + return this.parseFunction(node, true, true) + } + var expr = this.parseExpression(); + if (isDummy(expr)) { + this.next(); + if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") } + return this.parseStatement() + } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.colon)) { + node.body = this.parseStatement(); + node.label = expr; + return this.finishNode(node, "LabeledStatement") + } else { + node.expression = expr; + this.semicolon(); + return this.finishNode(node, "ExpressionStatement") + } } - return this.parseFor(node, init) + }; - case acorn.tokTypes._function: - this.next(); - return this.parseFunction(node, true) - - case acorn.tokTypes._if: - this.next(); - node.test = this.parseParenExpression(); - node.consequent = this.parseStatement(); - node.alternate = this.eat(acorn.tokTypes._else) ? this.parseStatement() : null; - return this.finishNode(node, "IfStatement") - - case acorn.tokTypes._return: - this.next(); - if (this.eat(acorn.tokTypes.semi) || this.canInsertSemicolon()) { node.argument = null; } - else { node.argument = this.parseExpression(); this.semicolon(); } - return this.finishNode(node, "ReturnStatement") - - case acorn.tokTypes._switch: - var blockIndent = this.curIndent, line = this.curLineStart; - this.next(); - node.discriminant = this.parseParenExpression(); - node.cases = []; + lp$1.parseBlock = function() { + var node = this.startNode(); this.pushCx(); this.expect(acorn.tokTypes.braceL); - - var cur; - while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) { - if (this$1.tok.type === acorn.tokTypes._case || this$1.tok.type === acorn.tokTypes._default) { - var isCase = this$1.tok.type === acorn.tokTypes._case; - if (cur) { this$1.finishNode(cur, "SwitchCase"); } - node.cases.push(cur = this$1.startNode()); - cur.consequent = []; - this$1.next(); - if (isCase) { cur.test = this$1.parseExpression(); } - else { cur.test = null; } - this$1.expect(acorn.tokTypes.colon); - } else { - if (!cur) { - node.cases.push(cur = this$1.startNode()); - cur.consequent = []; - cur.test = null; - } - cur.consequent.push(this$1.parseStatement()); - } - } - if (cur) { this.finishNode(cur, "SwitchCase"); } + var blockIndent = this.curIndent, line = this.curLineStart; + node.body = []; + while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) + { node.body.push(this.parseStatement()); } this.popCx(); this.eat(acorn.tokTypes.braceR); - return this.finishNode(node, "SwitchStatement") + return this.finishNode(node, "BlockStatement") + }; - case acorn.tokTypes._throw: + lp$1.parseFor = function(node, init) { + node.init = init; + node.test = node.update = null; + if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); } + if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); } + this.popCx(); + this.expect(acorn.tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, "ForStatement") + }; + + lp$1.parseForIn = function(node, init) { + var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement"; this.next(); - node.argument = this.parseExpression(); + node.left = init; + node.right = this.parseExpression(); + this.popCx(); + this.expect(acorn.tokTypes.parenR); + node.body = this.parseStatement(); + return this.finishNode(node, type) + }; + + lp$1.parseVar = function(node, noIn, kind) { + node.kind = kind; + this.next(); + node.declarations = []; + do { + var decl = this.startNode(); + decl.id = this.options.ecmaVersion >= 6 ? this.toAssignable(this.parseExprAtom(), true) : this.parseIdent(); + decl.init = this.eat(acorn.tokTypes.eq) ? this.parseMaybeAssign(noIn) : null; + node.declarations.push(this.finishNode(decl, "VariableDeclarator")); + } while (this.eat(acorn.tokTypes.comma)) + if (!node.declarations.length) { + var decl$1 = this.startNode(); + decl$1.id = this.dummyIdent(); + node.declarations.push(this.finishNode(decl$1, "VariableDeclarator")); + } + if (!noIn) { this.semicolon(); } + return this.finishNode(node, "VariableDeclaration") + }; + + lp$1.parseClass = function(isStatement) { + var node = this.startNode(); + this.next(); + if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + else { node.id = null; } + node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null; + node.body = this.startNode(); + node.body.body = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(acorn.tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent, line)) { + if (this.semicolon()) { continue } + var method = this.startNode(), isGenerator = (void 0), isAsync = (void 0); + if (this.options.ecmaVersion >= 6) { + method.static = false; + isGenerator = this.eat(acorn.tokTypes.star); + } + this.parsePropertyName(method); + if (isDummy(method.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(acorn.tokTypes.comma); continue } + if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" && + (this.tok.type !== acorn.tokTypes.parenL && this.tok.type !== acorn.tokTypes.braceL)) { + method.static = true; + isGenerator = this.eat(acorn.tokTypes.star); + this.parsePropertyName(method); + } else { + method.static = false; + } + if (!method.computed && + method.key.type === "Identifier" && method.key.name === "async" && this.tok.type !== acorn.tokTypes.parenL && + !this.canInsertSemicolon()) { + isAsync = true; + isGenerator = this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.star); + this.parsePropertyName(method); + } else { + isAsync = false; + } + if (this.options.ecmaVersion >= 5 && method.key.type === "Identifier" && + !method.computed && (method.key.name === "get" || method.key.name === "set") && + this.tok.type !== acorn.tokTypes.parenL && this.tok.type !== acorn.tokTypes.braceL) { + method.kind = method.key.name; + this.parsePropertyName(method); + method.value = this.parseMethod(false); + } else { + if (!method.computed && !method.static && !isGenerator && !isAsync && ( + method.key.type === "Identifier" && method.key.name === "constructor" || + method.key.type === "Literal" && method.key.value === "constructor")) { + method.kind = "constructor"; + } else { + method.kind = "method"; + } + method.value = this.parseMethod(isGenerator, isAsync); + } + node.body.body.push(this.finishNode(method, "MethodDefinition")); + } + this.popCx(); + if (!this.eat(acorn.tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } this.semicolon(); - return this.finishNode(node, "ThrowStatement") + this.finishNode(node.body, "ClassBody"); + return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") + }; - case acorn.tokTypes._try: + lp$1.parseFunction = function(node, isStatement, isAsync) { + var oldInAsync = this.inAsync, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) { + node.generator = this.eat(acorn.tokTypes.star); + } + if (this.options.ecmaVersion >= 8) { + node.async = !!isAsync; + } + if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } + else if (isStatement === true) { node.id = this.dummyIdent(); } + this.inAsync = node.async; + this.inFunction = true; + node.params = this.parseFunctionParams(); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); + this.inAsync = oldInAsync; + this.inFunction = oldInFunction; + return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") + }; + + lp$1.parseExport = function() { + var node = this.startNode(); this.next(); - node.block = this.parseBlock(); - node.handler = null; - if (this.tok.type === acorn.tokTypes._catch) { - var clause = this.startNode(); - this.next(); - if (this.eat(acorn.tokTypes.parenL)) { - clause.param = this.toAssignable(this.parseExprAtom(), true); - this.expect(acorn.tokTypes.parenR); + if (this.eat(acorn.tokTypes.star)) { + node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString(); + return this.finishNode(node, "ExportAllDeclaration") + } + if (this.eat(acorn.tokTypes._default)) { + // export default (function foo() {}) // This is FunctionExpression. + var isAsync; + if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { + var fNode = this.startNode(); + this.next(); + if (isAsync) { this.next(); } + node.declaration = this.parseFunction(fNode, "nullableID", isAsync); + } else if (this.tok.type === acorn.tokTypes._class) { + node.declaration = this.parseClass("nullableID"); } else { - clause.param = null; + node.declaration = this.parseMaybeAssign(); + this.semicolon(); } - clause.body = this.parseBlock(); - node.handler = this.finishNode(clause, "CatchClause"); + return this.finishNode(node, "ExportDefaultDeclaration") } - node.finalizer = this.eat(acorn.tokTypes._finally) ? this.parseBlock() : null; - if (!node.handler && !node.finalizer) { return node.block } - return this.finishNode(node, "TryStatement") - - case acorn.tokTypes._var: - case acorn.tokTypes._const: - return this.parseVar(node, false, kind || this.tok.value) - - case acorn.tokTypes._while: - this.next(); - node.test = this.parseParenExpression(); - node.body = this.parseStatement(); - return this.finishNode(node, "WhileStatement") - - case acorn.tokTypes._with: - this.next(); - node.object = this.parseParenExpression(); - node.body = this.parseStatement(); - return this.finishNode(node, "WithStatement") - - case acorn.tokTypes.braceL: - return this.parseBlock() - - case acorn.tokTypes.semi: - this.next(); - return this.finishNode(node, "EmptyStatement") - - case acorn.tokTypes._class: - return this.parseClass(true) - - case acorn.tokTypes._import: - return this.parseImport() - - case acorn.tokTypes._export: - return this.parseExport() - - default: - if (this.toks.isAsyncFunction()) { - this.next(); - this.next(); - return this.parseFunction(node, true, true) - } - var expr = this.parseExpression(); - if (isDummy(expr)) { - this.next(); - if (this.tok.type === acorn.tokTypes.eof) { return this.finishNode(node, "EmptyStatement") } - return this.parseStatement() - } else if (starttype === acorn.tokTypes.name && expr.type === "Identifier" && this.eat(acorn.tokTypes.colon)) { - node.body = this.parseStatement(); - node.label = expr; - return this.finishNode(node, "LabeledStatement") + if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { + node.declaration = this.parseStatement(); + node.specifiers = []; + node.source = null; } else { - node.expression = expr; - this.semicolon(); - return this.finishNode(node, "ExpressionStatement") - } - } -}; - -lp$1.parseBlock = function() { - var this$1 = this; - - var node = this.startNode(); - this.pushCx(); - this.expect(acorn.tokTypes.braceL); - var blockIndent = this.curIndent, line = this.curLineStart; - node.body = []; - while (!this.closes(acorn.tokTypes.braceR, blockIndent, line, true)) - { node.body.push(this$1.parseStatement()); } - this.popCx(); - this.eat(acorn.tokTypes.braceR); - return this.finishNode(node, "BlockStatement") -}; - -lp$1.parseFor = function(node, init) { - node.init = init; - node.test = node.update = null; - if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.semi) { node.test = this.parseExpression(); } - if (this.eat(acorn.tokTypes.semi) && this.tok.type !== acorn.tokTypes.parenR) { node.update = this.parseExpression(); } - this.popCx(); - this.expect(acorn.tokTypes.parenR); - node.body = this.parseStatement(); - return this.finishNode(node, "ForStatement") -}; - -lp$1.parseForIn = function(node, init) { - var type = this.tok.type === acorn.tokTypes._in ? "ForInStatement" : "ForOfStatement"; - this.next(); - node.left = init; - node.right = this.parseExpression(); - this.popCx(); - this.expect(acorn.tokTypes.parenR); - node.body = this.parseStatement(); - return this.finishNode(node, type) -}; - -lp$1.parseVar = function(node, noIn, kind) { - var this$1 = this; - - node.kind = kind; - this.next(); - node.declarations = []; - do { - var decl = this$1.startNode(); - decl.id = this$1.options.ecmaVersion >= 6 ? this$1.toAssignable(this$1.parseExprAtom(), true) : this$1.parseIdent(); - decl.init = this$1.eat(acorn.tokTypes.eq) ? this$1.parseMaybeAssign(noIn) : null; - node.declarations.push(this$1.finishNode(decl, "VariableDeclarator")); - } while (this.eat(acorn.tokTypes.comma)) - if (!node.declarations.length) { - var decl$1 = this.startNode(); - decl$1.id = this.dummyIdent(); - node.declarations.push(this.finishNode(decl$1, "VariableDeclarator")); - } - if (!noIn) { this.semicolon(); } - return this.finishNode(node, "VariableDeclaration") -}; - -lp$1.parseClass = function(isStatement) { - var this$1 = this; - - var node = this.startNode(); - this.next(); - if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } - else if (isStatement === true) { node.id = this.dummyIdent(); } - else { node.id = null; } - node.superClass = this.eat(acorn.tokTypes._extends) ? this.parseExpression() : null; - node.body = this.startNode(); - node.body.body = []; - this.pushCx(); - var indent = this.curIndent + 1, line = this.curLineStart; - this.eat(acorn.tokTypes.braceL); - if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } - while (!this.closes(acorn.tokTypes.braceR, indent, line)) { - if (this$1.semicolon()) { continue } - var method = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0); - if (this$1.options.ecmaVersion >= 6) { - method.static = false; - isGenerator = this$1.eat(acorn.tokTypes.star); - } - this$1.parsePropertyName(method); - if (isDummy(method.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue } - if (method.key.type === "Identifier" && !method.computed && method.key.name === "static" && - (this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL)) { - method.static = true; - isGenerator = this$1.eat(acorn.tokTypes.star); - this$1.parsePropertyName(method); - } else { - method.static = false; - } - if (!method.computed && - method.key.type === "Identifier" && method.key.name === "async" && this$1.tok.type !== acorn.tokTypes.parenL && - !this$1.canInsertSemicolon()) { - isAsync = true; - isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star); - this$1.parsePropertyName(method); - } else { - isAsync = false; - } - if (this$1.options.ecmaVersion >= 5 && method.key.type === "Identifier" && - !method.computed && (method.key.name === "get" || method.key.name === "set") && - this$1.tok.type !== acorn.tokTypes.parenL && this$1.tok.type !== acorn.tokTypes.braceL) { - method.kind = method.key.name; - this$1.parsePropertyName(method); - method.value = this$1.parseMethod(false); - } else { - if (!method.computed && !method.static && !isGenerator && !isAsync && ( - method.key.type === "Identifier" && method.key.name === "constructor" || - method.key.type === "Literal" && method.key.value === "constructor")) { - method.kind = "constructor"; - } else { - method.kind = "method"; - } - method.value = this$1.parseMethod(isGenerator, isAsync); - } - node.body.body.push(this$1.finishNode(method, "MethodDefinition")); - } - this.popCx(); - if (!this.eat(acorn.tokTypes.braceR)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start; - if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } - } - this.semicolon(); - this.finishNode(node.body, "ClassBody"); - return this.finishNode(node, isStatement ? "ClassDeclaration" : "ClassExpression") -}; - -lp$1.parseFunction = function(node, isStatement, isAsync) { - var oldInAsync = this.inAsync, oldInFunction = this.inFunction; - this.initFunction(node); - if (this.options.ecmaVersion >= 6) { - node.generator = this.eat(acorn.tokTypes.star); - } - if (this.options.ecmaVersion >= 8) { - node.async = !!isAsync; - } - if (this.tok.type === acorn.tokTypes.name) { node.id = this.parseIdent(); } - else if (isStatement === true) { node.id = this.dummyIdent(); } - this.inAsync = node.async; - this.inFunction = true; - node.params = this.parseFunctionParams(); - node.body = this.parseBlock(); - this.toks.adaptDirectivePrologue(node.body.body); - this.inAsync = oldInAsync; - this.inFunction = oldInFunction; - return this.finishNode(node, isStatement ? "FunctionDeclaration" : "FunctionExpression") -}; - -lp$1.parseExport = function() { - var node = this.startNode(); - this.next(); - if (this.eat(acorn.tokTypes.star)) { - node.source = this.eatContextual("from") ? this.parseExprAtom() : this.dummyString(); - return this.finishNode(node, "ExportAllDeclaration") - } - if (this.eat(acorn.tokTypes._default)) { - // export default (function foo() {}) // This is FunctionExpression. - var isAsync; - if (this.tok.type === acorn.tokTypes._function || (isAsync = this.toks.isAsyncFunction())) { - var fNode = this.startNode(); - this.next(); - if (isAsync) { this.next(); } - node.declaration = this.parseFunction(fNode, "nullableID", isAsync); - } else if (this.tok.type === acorn.tokTypes._class) { - node.declaration = this.parseClass("nullableID"); - } else { - node.declaration = this.parseMaybeAssign(); + node.declaration = null; + node.specifiers = this.parseExportSpecifierList(); + node.source = this.eatContextual("from") ? this.parseExprAtom() : null; this.semicolon(); } - return this.finishNode(node, "ExportDefaultDeclaration") - } - if (this.tok.type.keyword || this.toks.isLet() || this.toks.isAsyncFunction()) { - node.declaration = this.parseStatement(); - node.specifiers = []; - node.source = null; - } else { - node.declaration = null; - node.specifiers = this.parseExportSpecifierList(); - node.source = this.eatContextual("from") ? this.parseExprAtom() : null; - this.semicolon(); - } - return this.finishNode(node, "ExportNamedDeclaration") -}; + return this.finishNode(node, "ExportNamedDeclaration") + }; -lp$1.parseImport = function() { - var node = this.startNode(); - this.next(); - if (this.tok.type === acorn.tokTypes.string) { - node.specifiers = []; - node.source = this.parseExprAtom(); - } else { - var elt; - if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") { - elt = this.startNode(); - elt.local = this.parseIdent(); - this.finishNode(elt, "ImportDefaultSpecifier"); - this.eat(acorn.tokTypes.comma); - } - node.specifiers = this.parseImportSpecifiers(); - node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString(); - if (elt) { node.specifiers.unshift(elt); } - } - this.semicolon(); - return this.finishNode(node, "ImportDeclaration") -}; - -lp$1.parseImportSpecifiers = function() { - var this$1 = this; - - var elts = []; - if (this.tok.type === acorn.tokTypes.star) { - var elt = this.startNode(); + lp$1.parseImport = function() { + var node = this.startNode(); this.next(); - elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); - elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")); - } else { + if (this.tok.type === acorn.tokTypes.string) { + node.specifiers = []; + node.source = this.parseExprAtom(); + } else { + var elt; + if (this.tok.type === acorn.tokTypes.name && this.tok.value !== "from") { + elt = this.startNode(); + elt.local = this.parseIdent(); + this.finishNode(elt, "ImportDefaultSpecifier"); + this.eat(acorn.tokTypes.comma); + } + node.specifiers = this.parseImportSpecifiers(); + node.source = this.eatContextual("from") && this.tok.type === acorn.tokTypes.string ? this.parseExprAtom() : this.dummyString(); + if (elt) { node.specifiers.unshift(elt); } + } + this.semicolon(); + return this.finishNode(node, "ImportDeclaration") + }; + + lp$1.parseImportSpecifiers = function() { + var elts = []; + if (this.tok.type === acorn.tokTypes.star) { + var elt = this.startNode(); + this.next(); + elt.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); + elts.push(this.finishNode(elt, "ImportNamespaceSpecifier")); + } else { + var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; + this.pushCx(); + this.eat(acorn.tokTypes.braceL); + if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { + var elt$1 = this.startNode(); + if (this.eat(acorn.tokTypes.star)) { + elt$1.local = this.eatContextual("as") ? this.parseIdent() : this.dummyIdent(); + this.finishNode(elt$1, "ImportNamespaceSpecifier"); + } else { + if (this.isContextual("from")) { break } + elt$1.imported = this.parseIdent(); + if (isDummy(elt$1.imported)) { break } + elt$1.local = this.eatContextual("as") ? this.parseIdent() : elt$1.imported; + this.finishNode(elt$1, "ImportSpecifier"); + } + elts.push(elt$1); + this.eat(acorn.tokTypes.comma); + } + this.eat(acorn.tokTypes.braceR); + this.popCx(); + } + return elts + }; + + lp$1.parseExportSpecifierList = function() { + var elts = []; var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; this.pushCx(); this.eat(acorn.tokTypes.braceL); if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { - var elt$1 = this$1.startNode(); - if (this$1.eat(acorn.tokTypes.star)) { - elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : this$1.dummyIdent(); - this$1.finishNode(elt$1, "ImportNamespaceSpecifier"); - } else { - if (this$1.isContextual("from")) { break } - elt$1.imported = this$1.parseIdent(); - if (isDummy(elt$1.imported)) { break } - elt$1.local = this$1.eatContextual("as") ? this$1.parseIdent() : elt$1.imported; - this$1.finishNode(elt$1, "ImportSpecifier"); - } - elts.push(elt$1); - this$1.eat(acorn.tokTypes.comma); + if (this.isContextual("from")) { break } + var elt = this.startNode(); + elt.local = this.parseIdent(); + if (isDummy(elt.local)) { break } + elt.exported = this.eatContextual("as") ? this.parseIdent() : elt.local; + this.finishNode(elt, "ExportSpecifier"); + elts.push(elt); + this.eat(acorn.tokTypes.comma); } this.eat(acorn.tokTypes.braceR); this.popCx(); - } - return elts -}; + return elts + }; -lp$1.parseExportSpecifierList = function() { - var this$1 = this; + var lp$2 = LooseParser.prototype; - var elts = []; - var indent = this.curIndent, line = this.curLineStart, continuedLine = this.nextLineStart; - this.pushCx(); - this.eat(acorn.tokTypes.braceL); - if (this.curLineStart > continuedLine) { continuedLine = this.curLineStart; } - while (!this.closes(acorn.tokTypes.braceR, indent + (this.curLineStart <= continuedLine ? 1 : 0), line)) { - if (this$1.isContextual("from")) { break } - var elt = this$1.startNode(); - elt.local = this$1.parseIdent(); - if (isDummy(elt.local)) { break } - elt.exported = this$1.eatContextual("as") ? this$1.parseIdent() : elt.local; - this$1.finishNode(elt, "ExportSpecifier"); - elts.push(elt); - this$1.eat(acorn.tokTypes.comma); - } - this.eat(acorn.tokTypes.braceR); - this.popCx(); - return elts -}; + lp$2.checkLVal = function(expr) { + if (!expr) { return expr } + switch (expr.type) { + case "Identifier": + case "MemberExpression": + return expr -var lp$2 = LooseParser.prototype; + case "ParenthesizedExpression": + expr.expression = this.checkLVal(expr.expression); + return expr -lp$2.checkLVal = function(expr) { - if (!expr) { return expr } - switch (expr.type) { - case "Identifier": - case "MemberExpression": + default: + return this.dummyIdent() + } + }; + + lp$2.parseExpression = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseMaybeAssign(noIn); + if (this.tok.type === acorn.tokTypes.comma) { + var node = this.startNodeAt(start); + node.expressions = [expr]; + while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this.parseMaybeAssign(noIn)); } + return this.finishNode(node, "SequenceExpression") + } return expr + }; - case "ParenthesizedExpression": - expr.expression = this.checkLVal(expr.expression); + lp$2.parseParenExpression = function() { + this.pushCx(); + this.expect(acorn.tokTypes.parenL); + var val = this.parseExpression(); + this.popCx(); + this.expect(acorn.tokTypes.parenR); + return val + }; + + lp$2.parseMaybeAssign = function(noIn) { + if (this.toks.isContextual("yield")) { + var node = this.startNode(); + this.next(); + if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) { + node.delegate = false; + node.argument = null; + } else { + node.delegate = this.eat(acorn.tokTypes.star); + node.argument = this.parseMaybeAssign(); + } + return this.finishNode(node, "YieldExpression") + } + + var start = this.storeCurrentPos(); + var left = this.parseMaybeConditional(noIn); + if (this.tok.type.isAssign) { + var node$1 = this.startNodeAt(start); + node$1.operator = this.tok.value; + node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left); + this.next(); + node$1.right = this.parseMaybeAssign(noIn); + return this.finishNode(node$1, "AssignmentExpression") + } + return left + }; + + lp$2.parseMaybeConditional = function(noIn) { + var start = this.storeCurrentPos(); + var expr = this.parseExprOps(noIn); + if (this.eat(acorn.tokTypes.question)) { + var node = this.startNodeAt(start); + node.test = expr; + node.consequent = this.parseMaybeAssign(); + node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent(); + return this.finishNode(node, "ConditionalExpression") + } return expr + }; - default: - return this.dummyIdent() - } -}; + lp$2.parseExprOps = function(noIn) { + var start = this.storeCurrentPos(); + var indent = this.curIndent, line = this.curLineStart; + return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) + }; -lp$2.parseExpression = function(noIn) { - var this$1 = this; + lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) { + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left } + var prec = this.tok.type.binop; + if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) { + if (prec > minPrec) { + var node = this.startNodeAt(start); + node.left = left; + node.operator = this.tok.value; + this.next(); + if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { + node.right = this.dummyIdent(); + } else { + var rightStart = this.storeCurrentPos(); + node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line); + } + this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); + return this.parseExprOp(node, start, minPrec, noIn, indent, line) + } + } + return left + }; - var start = this.storeCurrentPos(); - var expr = this.parseMaybeAssign(noIn); - if (this.tok.type === acorn.tokTypes.comma) { - var node = this.startNodeAt(start); - node.expressions = [expr]; - while (this.eat(acorn.tokTypes.comma)) { node.expressions.push(this$1.parseMaybeAssign(noIn)); } - return this.finishNode(node, "SequenceExpression") - } - return expr -}; + lp$2.parseMaybeUnary = function(sawUnary) { + var start = this.storeCurrentPos(), expr; + if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") && + (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) + ) { + expr = this.parseAwait(); + sawUnary = true; + } else if (this.tok.type.prefix) { + var node = this.startNode(), update = this.tok.type === acorn.tokTypes.incDec; + if (!update) { sawUnary = true; } + node.operator = this.tok.value; + node.prefix = true; + this.next(); + node.argument = this.parseMaybeUnary(true); + if (update) { node.argument = this.checkLVal(node.argument); } + expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); + } else if (this.tok.type === acorn.tokTypes.ellipsis) { + var node$1 = this.startNode(); + this.next(); + node$1.argument = this.parseMaybeUnary(sawUnary); + expr = this.finishNode(node$1, "SpreadElement"); + } else { + expr = this.parseExprSubscripts(); + while (this.tok.type.postfix && !this.canInsertSemicolon()) { + var node$2 = this.startNodeAt(start); + node$2.operator = this.tok.value; + node$2.prefix = false; + node$2.argument = this.checkLVal(expr); + this.next(); + expr = this.finishNode(node$2, "UpdateExpression"); + } + } -lp$2.parseParenExpression = function() { - this.pushCx(); - this.expect(acorn.tokTypes.parenL); - var val = this.parseExpression(); - this.popCx(); - this.expect(acorn.tokTypes.parenR); - return val -}; + if (!sawUnary && this.eat(acorn.tokTypes.starstar)) { + var node$3 = this.startNodeAt(start); + node$3.operator = "**"; + node$3.left = expr; + node$3.right = this.parseMaybeUnary(false); + return this.finishNode(node$3, "BinaryExpression") + } -lp$2.parseMaybeAssign = function(noIn) { - if (this.toks.isContextual("yield")) { + return expr + }; + + lp$2.parseExprSubscripts = function() { + var start = this.storeCurrentPos(); + return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) + }; + + lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) { + for (;;) { + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) { + if (this.tok.type === acorn.tokTypes.dot && this.curIndent === startIndent) + { --startIndent; } + else + { return base } + } + + var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this.canInsertSemicolon(); + + if (this.eat(acorn.tokTypes.dot)) { + var node = this.startNodeAt(start); + node.object = base; + if (this.curLineStart !== line && this.curIndent <= startIndent && this.tokenStartsLine()) + { node.property = this.dummyIdent(); } + else + { node.property = this.parsePropertyAccessor() || this.dummyIdent(); } + node.computed = false; + base = this.finishNode(node, "MemberExpression"); + } else if (this.tok.type === acorn.tokTypes.bracketL) { + this.pushCx(); + this.next(); + var node$1 = this.startNodeAt(start); + node$1.object = base; + node$1.property = this.parseExpression(); + node$1.computed = true; + this.popCx(); + this.expect(acorn.tokTypes.bracketR); + base = this.finishNode(node$1, "MemberExpression"); + } else if (!noCalls && this.tok.type === acorn.tokTypes.parenL) { + var exprList = this.parseExprList(acorn.tokTypes.parenR); + if (maybeAsyncArrow && this.eat(acorn.tokTypes.arrow)) + { return this.parseArrowExpression(this.startNodeAt(start), exprList, true) } + var node$2 = this.startNodeAt(start); + node$2.callee = base; + node$2.arguments = exprList; + base = this.finishNode(node$2, "CallExpression"); + } else if (this.tok.type === acorn.tokTypes.backQuote) { + var node$3 = this.startNodeAt(start); + node$3.tag = base; + node$3.quasi = this.parseTemplate(); + base = this.finishNode(node$3, "TaggedTemplateExpression"); + } else { + return base + } + } + }; + + lp$2.parseExprAtom = function() { + var node; + switch (this.tok.type) { + case acorn.tokTypes._this: + case acorn.tokTypes._super: + var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super"; + node = this.startNode(); + this.next(); + return this.finishNode(node, type) + + case acorn.tokTypes.name: + var start = this.storeCurrentPos(); + var id = this.parseIdent(); + var isAsync = false; + if (id.name === "async" && !this.canInsertSemicolon()) { + if (this.eat(acorn.tokTypes._function)) + { return this.parseFunction(this.startNodeAt(start), false, true) } + if (this.tok.type === acorn.tokTypes.name) { + id = this.parseIdent(); + isAsync = true; + } + } + return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id + + case acorn.tokTypes.regexp: + node = this.startNode(); + var val = this.tok.value; + node.regex = {pattern: val.pattern, flags: val.flags}; + node.value = val.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes.num: case acorn.tokTypes.string: + node = this.startNode(); + node.value = this.tok.value; + node.raw = this.input.slice(this.tok.start, this.tok.end); + if (this.tok.type === acorn.tokTypes.num && node.raw.charCodeAt(node.raw.length - 1) === 110) { node.bigint = node.raw.slice(0, -1); } + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false: + node = this.startNode(); + node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true; + node.raw = this.tok.type.keyword; + this.next(); + return this.finishNode(node, "Literal") + + case acorn.tokTypes.parenL: + var parenStart = this.storeCurrentPos(); + this.next(); + var inner = this.parseExpression(); + this.expect(acorn.tokTypes.parenR); + if (this.eat(acorn.tokTypes.arrow)) { + // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. + var params = inner.expressions || [inner]; + if (params.length && isDummy(params[params.length - 1])) + { params.pop(); } + return this.parseArrowExpression(this.startNodeAt(parenStart), params) + } + if (this.options.preserveParens) { + var par = this.startNodeAt(parenStart); + par.expression = inner; + inner = this.finishNode(par, "ParenthesizedExpression"); + } + return inner + + case acorn.tokTypes.bracketL: + node = this.startNode(); + node.elements = this.parseExprList(acorn.tokTypes.bracketR, true); + return this.finishNode(node, "ArrayExpression") + + case acorn.tokTypes.braceL: + return this.parseObj() + + case acorn.tokTypes._class: + return this.parseClass(false) + + case acorn.tokTypes._function: + node = this.startNode(); + this.next(); + return this.parseFunction(node, false) + + case acorn.tokTypes._new: + return this.parseNew() + + case acorn.tokTypes.backQuote: + return this.parseTemplate() + + case acorn.tokTypes._import: + if (this.options.ecmaVersion >= 11) { + return this.parseExprImport() + } else { + return this.dummyIdent() + } + + default: + return this.dummyIdent() + } + }; + + lp$2.parseExprImport = function() { + var node = this.startNode(); + this.next(); // skip `import` + switch (this.tok.type) { + case acorn.tokTypes.parenL: + return this.parseDynamicImport(node) + default: + node.name = "import"; + return this.finishNode(node, "Identifier") + } + }; + + lp$2.parseDynamicImport = function(node) { + node.source = this.parseExprList(acorn.tokTypes.parenR)[0] || this.dummyString(); + return this.finishNode(node, "ImportExpression") + }; + + lp$2.parseNew = function() { + var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart; + var meta = this.parseIdent(true); + if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) { + node.meta = meta; + node.property = this.parseIdent(true); + return this.finishNode(node, "MetaProperty") + } + var start = this.storeCurrentPos(); + node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line); + if (this.tok.type === acorn.tokTypes.parenL) { + node.arguments = this.parseExprList(acorn.tokTypes.parenR); + } else { + node.arguments = []; + } + return this.finishNode(node, "NewExpression") + }; + + lp$2.parseTemplateElement = function() { + var elem = this.startNode(); + + // The loose parser accepts invalid unicode escapes even in untagged templates. + if (this.tok.type === acorn.tokTypes.invalidTemplate) { + elem.value = { + raw: this.tok.value, + cooked: null + }; + } else { + elem.value = { + raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), + cooked: this.tok.value + }; + } + this.next(); + elem.tail = this.tok.type === acorn.tokTypes.backQuote; + return this.finishNode(elem, "TemplateElement") + }; + + lp$2.parseTemplate = function() { var node = this.startNode(); this.next(); - if (this.semicolon() || this.canInsertSemicolon() || (this.tok.type !== acorn.tokTypes.star && !this.tok.type.startsExpr)) { - node.delegate = false; - node.argument = null; - } else { - node.delegate = this.eat(acorn.tokTypes.star); - node.argument = this.parseMaybeAssign(); - } - return this.finishNode(node, "YieldExpression") - } - - var start = this.storeCurrentPos(); - var left = this.parseMaybeConditional(noIn); - if (this.tok.type.isAssign) { - var node$1 = this.startNodeAt(start); - node$1.operator = this.tok.value; - node$1.left = this.tok.type === acorn.tokTypes.eq ? this.toAssignable(left) : this.checkLVal(left); - this.next(); - node$1.right = this.parseMaybeAssign(noIn); - return this.finishNode(node$1, "AssignmentExpression") - } - return left -}; - -lp$2.parseMaybeConditional = function(noIn) { - var start = this.storeCurrentPos(); - var expr = this.parseExprOps(noIn); - if (this.eat(acorn.tokTypes.question)) { - var node = this.startNodeAt(start); - node.test = expr; - node.consequent = this.parseMaybeAssign(); - node.alternate = this.expect(acorn.tokTypes.colon) ? this.parseMaybeAssign(noIn) : this.dummyIdent(); - return this.finishNode(node, "ConditionalExpression") - } - return expr -}; - -lp$2.parseExprOps = function(noIn) { - var start = this.storeCurrentPos(); - var indent = this.curIndent, line = this.curLineStart; - return this.parseExprOp(this.parseMaybeUnary(false), start, -1, noIn, indent, line) -}; - -lp$2.parseExprOp = function(left, start, minPrec, noIn, indent, line) { - if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { return left } - var prec = this.tok.type.binop; - if (prec != null && (!noIn || this.tok.type !== acorn.tokTypes._in)) { - if (prec > minPrec) { - var node = this.startNodeAt(start); - node.left = left; - node.operator = this.tok.value; + node.expressions = []; + var curElt = this.parseTemplateElement(); + node.quasis = [curElt]; + while (!curElt.tail) { this.next(); - if (this.curLineStart !== line && this.curIndent < indent && this.tokenStartsLine()) { - node.right = this.dummyIdent(); + node.expressions.push(this.parseExpression()); + if (this.expect(acorn.tokTypes.braceR)) { + curElt = this.parseTemplateElement(); } else { - var rightStart = this.storeCurrentPos(); - node.right = this.parseExprOp(this.parseMaybeUnary(false), rightStart, prec, noIn, indent, line); + curElt = this.startNode(); + curElt.value = {cooked: "", raw: ""}; + curElt.tail = true; + this.finishNode(curElt, "TemplateElement"); } - this.finishNode(node, /&&|\|\|/.test(node.operator) ? "LogicalExpression" : "BinaryExpression"); - return this.parseExprOp(node, start, minPrec, noIn, indent, line) + node.quasis.push(curElt); } - } - return left -}; + this.expect(acorn.tokTypes.backQuote); + return this.finishNode(node, "TemplateLiteral") + }; -lp$2.parseMaybeUnary = function(sawUnary) { - var this$1 = this; - - var start = this.storeCurrentPos(), expr; - if (this.options.ecmaVersion >= 8 && this.toks.isContextual("await") && - (this.inAsync || (!this.inFunction && this.options.allowAwaitOutsideFunction)) - ) { - expr = this.parseAwait(); - sawUnary = true; - } else if (this.tok.type.prefix) { - var node = this.startNode(), update = this.tok.type === acorn.tokTypes.incDec; - if (!update) { sawUnary = true; } - node.operator = this.tok.value; - node.prefix = true; - this.next(); - node.argument = this.parseMaybeUnary(true); - if (update) { node.argument = this.checkLVal(node.argument); } - expr = this.finishNode(node, update ? "UpdateExpression" : "UnaryExpression"); - } else if (this.tok.type === acorn.tokTypes.ellipsis) { - var node$1 = this.startNode(); - this.next(); - node$1.argument = this.parseMaybeUnary(sawUnary); - expr = this.finishNode(node$1, "SpreadElement"); - } else { - expr = this.parseExprSubscripts(); - while (this.tok.type.postfix && !this.canInsertSemicolon()) { - var node$2 = this$1.startNodeAt(start); - node$2.operator = this$1.tok.value; - node$2.prefix = false; - node$2.argument = this$1.checkLVal(expr); - this$1.next(); - expr = this$1.finishNode(node$2, "UpdateExpression"); - } - } - - if (!sawUnary && this.eat(acorn.tokTypes.starstar)) { - var node$3 = this.startNodeAt(start); - node$3.operator = "**"; - node$3.left = expr; - node$3.right = this.parseMaybeUnary(false); - return this.finishNode(node$3, "BinaryExpression") - } - - return expr -}; - -lp$2.parseExprSubscripts = function() { - var start = this.storeCurrentPos(); - return this.parseSubscripts(this.parseExprAtom(), start, false, this.curIndent, this.curLineStart) -}; - -lp$2.parseSubscripts = function(base, start, noCalls, startIndent, line) { - var this$1 = this; - - for (;;) { - if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) { - if (this$1.tok.type === acorn.tokTypes.dot && this$1.curIndent === startIndent) - { --startIndent; } - else - { return base } - } - - var maybeAsyncArrow = base.type === "Identifier" && base.name === "async" && !this$1.canInsertSemicolon(); - - if (this$1.eat(acorn.tokTypes.dot)) { - var node = this$1.startNodeAt(start); - node.object = base; - if (this$1.curLineStart !== line && this$1.curIndent <= startIndent && this$1.tokenStartsLine()) - { node.property = this$1.dummyIdent(); } - else - { node.property = this$1.parsePropertyAccessor() || this$1.dummyIdent(); } - node.computed = false; - base = this$1.finishNode(node, "MemberExpression"); - } else if (this$1.tok.type === acorn.tokTypes.bracketL) { - this$1.pushCx(); - this$1.next(); - var node$1 = this$1.startNodeAt(start); - node$1.object = base; - node$1.property = this$1.parseExpression(); - node$1.computed = true; - this$1.popCx(); - this$1.expect(acorn.tokTypes.bracketR); - base = this$1.finishNode(node$1, "MemberExpression"); - } else if (!noCalls && this$1.tok.type === acorn.tokTypes.parenL) { - var exprList = this$1.parseExprList(acorn.tokTypes.parenR); - if (maybeAsyncArrow && this$1.eat(acorn.tokTypes.arrow)) - { return this$1.parseArrowExpression(this$1.startNodeAt(start), exprList, true) } - var node$2 = this$1.startNodeAt(start); - node$2.callee = base; - node$2.arguments = exprList; - base = this$1.finishNode(node$2, "CallExpression"); - } else if (this$1.tok.type === acorn.tokTypes.backQuote) { - var node$3 = this$1.startNodeAt(start); - node$3.tag = base; - node$3.quasi = this$1.parseTemplate(); - base = this$1.finishNode(node$3, "TaggedTemplateExpression"); - } else { - return base - } - } -}; - -lp$2.parseExprAtom = function() { - var node; - switch (this.tok.type) { - case acorn.tokTypes._this: - case acorn.tokTypes._super: - var type = this.tok.type === acorn.tokTypes._this ? "ThisExpression" : "Super"; - node = this.startNode(); - this.next(); - return this.finishNode(node, type) - - case acorn.tokTypes.name: - var start = this.storeCurrentPos(); - var id = this.parseIdent(); - var isAsync = false; - if (id.name === "async" && !this.canInsertSemicolon()) { - if (this.eat(acorn.tokTypes._function)) - { return this.parseFunction(this.startNodeAt(start), false, true) } - if (this.tok.type === acorn.tokTypes.name) { - id = this.parseIdent(); + lp$2.parseObj = function() { + var node = this.startNode(); + node.properties = []; + this.pushCx(); + var indent = this.curIndent + 1, line = this.curLineStart; + this.eat(acorn.tokTypes.braceL); + if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } + while (!this.closes(acorn.tokTypes.braceR, indent, line)) { + var prop = this.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0); + if (this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.ellipsis)) { + prop.argument = this.parseMaybeAssign(); + node.properties.push(this.finishNode(prop, "SpreadElement")); + this.eat(acorn.tokTypes.comma); + continue + } + if (this.options.ecmaVersion >= 6) { + start = this.storeCurrentPos(); + prop.method = false; + prop.shorthand = false; + isGenerator = this.eat(acorn.tokTypes.star); + } + this.parsePropertyName(prop); + if (this.toks.isAsyncProp(prop)) { isAsync = true; - } - } - return this.eat(acorn.tokTypes.arrow) ? this.parseArrowExpression(this.startNodeAt(start), [id], isAsync) : id - - case acorn.tokTypes.regexp: - node = this.startNode(); - var val = this.tok.value; - node.regex = {pattern: val.pattern, flags: val.flags}; - node.value = val.value; - node.raw = this.input.slice(this.tok.start, this.tok.end); - this.next(); - return this.finishNode(node, "Literal") - - case acorn.tokTypes.num: case acorn.tokTypes.string: - node = this.startNode(); - node.value = this.tok.value; - node.raw = this.input.slice(this.tok.start, this.tok.end); - this.next(); - return this.finishNode(node, "Literal") - - case acorn.tokTypes._null: case acorn.tokTypes._true: case acorn.tokTypes._false: - node = this.startNode(); - node.value = this.tok.type === acorn.tokTypes._null ? null : this.tok.type === acorn.tokTypes._true; - node.raw = this.tok.type.keyword; - this.next(); - return this.finishNode(node, "Literal") - - case acorn.tokTypes.parenL: - var parenStart = this.storeCurrentPos(); - this.next(); - var inner = this.parseExpression(); - this.expect(acorn.tokTypes.parenR); - if (this.eat(acorn.tokTypes.arrow)) { - // (a,)=>a // SequenceExpression makes dummy in the last hole. Drop the dummy. - var params = inner.expressions || [inner]; - if (params.length && isDummy(params[params.length - 1])) - { params.pop(); } - return this.parseArrowExpression(this.startNodeAt(parenStart), params) - } - if (this.options.preserveParens) { - var par = this.startNodeAt(parenStart); - par.expression = inner; - inner = this.finishNode(par, "ParenthesizedExpression"); - } - return inner - - case acorn.tokTypes.bracketL: - node = this.startNode(); - node.elements = this.parseExprList(acorn.tokTypes.bracketR, true); - return this.finishNode(node, "ArrayExpression") - - case acorn.tokTypes.braceL: - return this.parseObj() - - case acorn.tokTypes._class: - return this.parseClass(false) - - case acorn.tokTypes._function: - node = this.startNode(); - this.next(); - return this.parseFunction(node, false) - - case acorn.tokTypes._new: - return this.parseNew() - - case acorn.tokTypes.backQuote: - return this.parseTemplate() - - default: - return this.dummyIdent() - } -}; - -lp$2.parseNew = function() { - var node = this.startNode(), startIndent = this.curIndent, line = this.curLineStart; - var meta = this.parseIdent(true); - if (this.options.ecmaVersion >= 6 && this.eat(acorn.tokTypes.dot)) { - node.meta = meta; - node.property = this.parseIdent(true); - return this.finishNode(node, "MetaProperty") - } - var start = this.storeCurrentPos(); - node.callee = this.parseSubscripts(this.parseExprAtom(), start, true, startIndent, line); - if (this.tok.type === acorn.tokTypes.parenL) { - node.arguments = this.parseExprList(acorn.tokTypes.parenR); - } else { - node.arguments = []; - } - return this.finishNode(node, "NewExpression") -}; - -lp$2.parseTemplateElement = function() { - var elem = this.startNode(); - - // The loose parser accepts invalid unicode escapes even in untagged templates. - if (this.tok.type === acorn.tokTypes.invalidTemplate) { - elem.value = { - raw: this.tok.value, - cooked: null - }; - } else { - elem.value = { - raw: this.input.slice(this.tok.start, this.tok.end).replace(/\r\n?/g, "\n"), - cooked: this.tok.value - }; - } - this.next(); - elem.tail = this.tok.type === acorn.tokTypes.backQuote; - return this.finishNode(elem, "TemplateElement") -}; - -lp$2.parseTemplate = function() { - var this$1 = this; - - var node = this.startNode(); - this.next(); - node.expressions = []; - var curElt = this.parseTemplateElement(); - node.quasis = [curElt]; - while (!curElt.tail) { - this$1.next(); - node.expressions.push(this$1.parseExpression()); - if (this$1.expect(acorn.tokTypes.braceR)) { - curElt = this$1.parseTemplateElement(); - } else { - curElt = this$1.startNode(); - curElt.value = {cooked: "", raw: ""}; - curElt.tail = true; - this$1.finishNode(curElt, "TemplateElement"); - } - node.quasis.push(curElt); - } - this.expect(acorn.tokTypes.backQuote); - return this.finishNode(node, "TemplateLiteral") -}; - -lp$2.parseObj = function() { - var this$1 = this; - - var node = this.startNode(); - node.properties = []; - this.pushCx(); - var indent = this.curIndent + 1, line = this.curLineStart; - this.eat(acorn.tokTypes.braceL); - if (this.curIndent + 1 < indent) { indent = this.curIndent; line = this.curLineStart; } - while (!this.closes(acorn.tokTypes.braceR, indent, line)) { - var prop = this$1.startNode(), isGenerator = (void 0), isAsync = (void 0), start = (void 0); - if (this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.ellipsis)) { - prop.argument = this$1.parseMaybeAssign(); - node.properties.push(this$1.finishNode(prop, "SpreadElement")); - this$1.eat(acorn.tokTypes.comma); - continue - } - if (this$1.options.ecmaVersion >= 6) { - start = this$1.storeCurrentPos(); - prop.method = false; - prop.shorthand = false; - isGenerator = this$1.eat(acorn.tokTypes.star); - } - this$1.parsePropertyName(prop); - if (this$1.toks.isAsyncProp(prop)) { - isAsync = true; - isGenerator = this$1.options.ecmaVersion >= 9 && this$1.eat(acorn.tokTypes.star); - this$1.parsePropertyName(prop); - } else { - isAsync = false; - } - if (isDummy(prop.key)) { if (isDummy(this$1.parseMaybeAssign())) { this$1.next(); } this$1.eat(acorn.tokTypes.comma); continue } - if (this$1.eat(acorn.tokTypes.colon)) { - prop.kind = "init"; - prop.value = this$1.parseMaybeAssign(); - } else if (this$1.options.ecmaVersion >= 6 && (this$1.tok.type === acorn.tokTypes.parenL || this$1.tok.type === acorn.tokTypes.braceL)) { - prop.kind = "init"; - prop.method = true; - prop.value = this$1.parseMethod(isGenerator, isAsync); - } else if (this$1.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && - !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && - (this$1.tok.type !== acorn.tokTypes.comma && this$1.tok.type !== acorn.tokTypes.braceR && this$1.tok.type !== acorn.tokTypes.eq)) { - prop.kind = prop.key.name; - this$1.parsePropertyName(prop); - prop.value = this$1.parseMethod(false); - } else { - prop.kind = "init"; - if (this$1.options.ecmaVersion >= 6) { - if (this$1.eat(acorn.tokTypes.eq)) { - var assign = this$1.startNodeAt(start); - assign.operator = "="; - assign.left = prop.key; - assign.right = this$1.parseMaybeAssign(); - prop.value = this$1.finishNode(assign, "AssignmentExpression"); - } else { - prop.value = prop.key; - } + isGenerator = this.options.ecmaVersion >= 9 && this.eat(acorn.tokTypes.star); + this.parsePropertyName(prop); } else { - prop.value = this$1.dummyIdent(); + isAsync = false; } - prop.shorthand = true; + if (isDummy(prop.key)) { if (isDummy(this.parseMaybeAssign())) { this.next(); } this.eat(acorn.tokTypes.comma); continue } + if (this.eat(acorn.tokTypes.colon)) { + prop.kind = "init"; + prop.value = this.parseMaybeAssign(); + } else if (this.options.ecmaVersion >= 6 && (this.tok.type === acorn.tokTypes.parenL || this.tok.type === acorn.tokTypes.braceL)) { + prop.kind = "init"; + prop.method = true; + prop.value = this.parseMethod(isGenerator, isAsync); + } else if (this.options.ecmaVersion >= 5 && prop.key.type === "Identifier" && + !prop.computed && (prop.key.name === "get" || prop.key.name === "set") && + (this.tok.type !== acorn.tokTypes.comma && this.tok.type !== acorn.tokTypes.braceR && this.tok.type !== acorn.tokTypes.eq)) { + prop.kind = prop.key.name; + this.parsePropertyName(prop); + prop.value = this.parseMethod(false); + } else { + prop.kind = "init"; + if (this.options.ecmaVersion >= 6) { + if (this.eat(acorn.tokTypes.eq)) { + var assign = this.startNodeAt(start); + assign.operator = "="; + assign.left = prop.key; + assign.right = this.parseMaybeAssign(); + prop.value = this.finishNode(assign, "AssignmentExpression"); + } else { + prop.value = prop.key; + } + } else { + prop.value = this.dummyIdent(); + } + prop.shorthand = true; + } + node.properties.push(this.finishNode(prop, "Property")); + this.eat(acorn.tokTypes.comma); } - node.properties.push(this$1.finishNode(prop, "Property")); - this$1.eat(acorn.tokTypes.comma); - } - this.popCx(); - if (!this.eat(acorn.tokTypes.braceR)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start; - if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } - } - return this.finishNode(node, "ObjectExpression") -}; + this.popCx(); + if (!this.eat(acorn.tokTypes.braceR)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return this.finishNode(node, "ObjectExpression") + }; -lp$2.parsePropertyName = function(prop) { - if (this.options.ecmaVersion >= 6) { - if (this.eat(acorn.tokTypes.bracketL)) { - prop.computed = true; - prop.key = this.parseExpression(); - this.expect(acorn.tokTypes.bracketR); - return + lp$2.parsePropertyName = function(prop) { + if (this.options.ecmaVersion >= 6) { + if (this.eat(acorn.tokTypes.bracketL)) { + prop.computed = true; + prop.key = this.parseExpression(); + this.expect(acorn.tokTypes.bracketR); + return + } else { + prop.computed = false; + } + } + var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent(); + prop.key = key || this.dummyIdent(); + }; + + lp$2.parsePropertyAccessor = function() { + if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() } + }; + + lp$2.parseIdent = function() { + var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword; + if (!name) { return this.dummyIdent() } + var node = this.startNode(); + this.next(); + node.name = name; + return this.finishNode(node, "Identifier") + }; + + lp$2.initFunction = function(node) { + node.id = null; + node.params = []; + if (this.options.ecmaVersion >= 6) { + node.generator = false; + node.expression = false; + } + if (this.options.ecmaVersion >= 8) + { node.async = false; } + }; + + // Convert existing expression atom to assignable pattern + // if possible. + + lp$2.toAssignable = function(node, binding) { + if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) ; else if (node.type === "ParenthesizedExpression") { + this.toAssignable(node.expression, binding); + } else if (this.options.ecmaVersion < 6) { + return this.dummyIdent() + } else if (node.type === "ObjectExpression") { + node.type = "ObjectPattern"; + for (var i = 0, list = node.properties; i < list.length; i += 1) + { + var prop = list[i]; + + this.toAssignable(prop, binding); + } + } else if (node.type === "ArrayExpression") { + node.type = "ArrayPattern"; + this.toAssignableList(node.elements, binding); + } else if (node.type === "Property") { + this.toAssignable(node.value, binding); + } else if (node.type === "SpreadElement") { + node.type = "RestElement"; + this.toAssignable(node.argument, binding); + } else if (node.type === "AssignmentExpression") { + node.type = "AssignmentPattern"; + delete node.operator; } else { - prop.computed = false; + return this.dummyIdent() } - } - var key = (this.tok.type === acorn.tokTypes.num || this.tok.type === acorn.tokTypes.string) ? this.parseExprAtom() : this.parseIdent(); - prop.key = key || this.dummyIdent(); -}; + return node + }; -lp$2.parsePropertyAccessor = function() { - if (this.tok.type === acorn.tokTypes.name || this.tok.type.keyword) { return this.parseIdent() } -}; - -lp$2.parseIdent = function() { - var name = this.tok.type === acorn.tokTypes.name ? this.tok.value : this.tok.type.keyword; - if (!name) { return this.dummyIdent() } - var node = this.startNode(); - this.next(); - node.name = name; - return this.finishNode(node, "Identifier") -}; - -lp$2.initFunction = function(node) { - node.id = null; - node.params = []; - if (this.options.ecmaVersion >= 6) { - node.generator = false; - node.expression = false; - } - if (this.options.ecmaVersion >= 8) - { node.async = false; } -}; - -// Convert existing expression atom to assignable pattern -// if possible. - -lp$2.toAssignable = function(node, binding) { - var this$1 = this; - - if (!node || node.type === "Identifier" || (node.type === "MemberExpression" && !binding)) { - // Okay - } else if (node.type === "ParenthesizedExpression") { - this.toAssignable(node.expression, binding); - } else if (this.options.ecmaVersion < 6) { - return this.dummyIdent() - } else if (node.type === "ObjectExpression") { - node.type = "ObjectPattern"; - for (var i = 0, list = node.properties; i < list.length; i += 1) + lp$2.toAssignableList = function(exprList, binding) { + for (var i = 0, list = exprList; i < list.length; i += 1) { - var prop = list[i]; + var expr = list[i]; - this$1.toAssignable(prop, binding); + this.toAssignable(expr, binding); } - } else if (node.type === "ArrayExpression") { - node.type = "ArrayPattern"; - this.toAssignableList(node.elements, binding); - } else if (node.type === "Property") { - this.toAssignable(node.value, binding); - } else if (node.type === "SpreadElement") { - node.type = "RestElement"; - this.toAssignable(node.argument, binding); - } else if (node.type === "AssignmentExpression") { - node.type = "AssignmentPattern"; - delete node.operator; - } else { - return this.dummyIdent() - } - return node -}; + return exprList + }; -lp$2.toAssignableList = function(exprList, binding) { - var this$1 = this; + lp$2.parseFunctionParams = function(params) { + params = this.parseExprList(acorn.tokTypes.parenR); + return this.toAssignableList(params, true) + }; - for (var i = 0, list = exprList; i < list.length; i += 1) - { - var expr = list[i]; - - this$1.toAssignable(expr, binding); - } - return exprList -}; - -lp$2.parseFunctionParams = function(params) { - params = this.parseExprList(acorn.tokTypes.parenR); - return this.toAssignableList(params, true) -}; - -lp$2.parseMethod = function(isGenerator, isAsync) { - var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction; - this.initFunction(node); - if (this.options.ecmaVersion >= 6) - { node.generator = !!isGenerator; } - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - this.inAsync = node.async; - this.inFunction = true; - node.params = this.parseFunctionParams(); - node.body = this.parseBlock(); - this.toks.adaptDirectivePrologue(node.body.body); - this.inAsync = oldInAsync; - this.inFunction = oldInFunction; - return this.finishNode(node, "FunctionExpression") -}; - -lp$2.parseArrowExpression = function(node, params, isAsync) { - var oldInAsync = this.inAsync, oldInFunction = this.inFunction; - this.initFunction(node); - if (this.options.ecmaVersion >= 8) - { node.async = !!isAsync; } - this.inAsync = node.async; - this.inFunction = true; - node.params = this.toAssignableList(params, true); - node.expression = this.tok.type !== acorn.tokTypes.braceL; - if (node.expression) { - node.body = this.parseMaybeAssign(); - } else { + lp$2.parseMethod = function(isGenerator, isAsync) { + var node = this.startNode(), oldInAsync = this.inAsync, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 6) + { node.generator = !!isGenerator; } + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inFunction = true; + node.params = this.parseFunctionParams(); node.body = this.parseBlock(); this.toks.adaptDirectivePrologue(node.body.body); - } - this.inAsync = oldInAsync; - this.inFunction = oldInFunction; - return this.finishNode(node, "ArrowFunctionExpression") -}; + this.inAsync = oldInAsync; + this.inFunction = oldInFunction; + return this.finishNode(node, "FunctionExpression") + }; -lp$2.parseExprList = function(close, allowEmpty) { - var this$1 = this; - - this.pushCx(); - var indent = this.curIndent, line = this.curLineStart, elts = []; - this.next(); // Opening bracket - while (!this.closes(close, indent + 1, line)) { - if (this$1.eat(acorn.tokTypes.comma)) { - elts.push(allowEmpty ? null : this$1.dummyIdent()); - continue - } - var elt = this$1.parseMaybeAssign(); - if (isDummy(elt)) { - if (this$1.closes(close, indent, line)) { break } - this$1.next(); + lp$2.parseArrowExpression = function(node, params, isAsync) { + var oldInAsync = this.inAsync, oldInFunction = this.inFunction; + this.initFunction(node); + if (this.options.ecmaVersion >= 8) + { node.async = !!isAsync; } + this.inAsync = node.async; + this.inFunction = true; + node.params = this.toAssignableList(params, true); + node.expression = this.tok.type !== acorn.tokTypes.braceL; + if (node.expression) { + node.body = this.parseMaybeAssign(); } else { - elts.push(elt); + node.body = this.parseBlock(); + this.toks.adaptDirectivePrologue(node.body.body); } - this$1.eat(acorn.tokTypes.comma); + this.inAsync = oldInAsync; + this.inFunction = oldInFunction; + return this.finishNode(node, "ArrowFunctionExpression") + }; + + lp$2.parseExprList = function(close, allowEmpty) { + this.pushCx(); + var indent = this.curIndent, line = this.curLineStart, elts = []; + this.next(); // Opening bracket + while (!this.closes(close, indent + 1, line)) { + if (this.eat(acorn.tokTypes.comma)) { + elts.push(allowEmpty ? null : this.dummyIdent()); + continue + } + var elt = this.parseMaybeAssign(); + if (isDummy(elt)) { + if (this.closes(close, indent, line)) { break } + this.next(); + } else { + elts.push(elt); + } + this.eat(acorn.tokTypes.comma); + } + this.popCx(); + if (!this.eat(close)) { + // If there is no closing brace, make the node span to the start + // of the next token (this is useful for Tern) + this.last.end = this.tok.start; + if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } + } + return elts + }; + + lp$2.parseAwait = function() { + var node = this.startNode(); + this.next(); + node.argument = this.parseMaybeUnary(); + return this.finishNode(node, "AwaitExpression") + }; + + // Acorn: Loose parser + + acorn.defaultOptions.tabSize = 4; + + function parse(input, options) { + return LooseParser.parse(input, options) } - this.popCx(); - if (!this.eat(close)) { - // If there is no closing brace, make the node span to the start - // of the next token (this is useful for Tern) - this.last.end = this.tok.start; - if (this.options.locations) { this.last.loc.end = this.tok.loc.start; } - } - return elts -}; -lp$2.parseAwait = function() { - var node = this.startNode(); - this.next(); - node.argument = this.parseMaybeUnary(); - return this.finishNode(node, "AwaitExpression") -}; + exports.LooseParser = LooseParser; + exports.parse = parse; -// Acorn: Loose parser -// -// This module provides an alternative parser that exposes that same -// interface as the main module's `parse` function, but will try to -// parse anything as JavaScript, repairing syntax error the best it -// can. There are circumstances in which it will raise an error and -// give up, but they are very rare. The resulting AST will be a mostly -// valid JavaScript AST (as per the [Mozilla parser API][api], except -// that: -// -// - Return outside functions is allowed -// -// - Label consistency (no conflicts, break only to existing labels) -// is not enforced. -// -// - Bogus Identifier nodes with a name of `"✖"` are inserted whenever -// the parser got too confused to return anything meaningful. -// -// [api]: https://developer.mozilla.org/en-US/docs/SpiderMonkey/Parser_API -// -// The expected use for this is to *first* try `acorn.parse`, and only -// if that fails switch to the loose parser. The loose parser might -// parse badly indented code incorrectly, so **don't** use it as your -// default parser. -// -// Quite a lot of acorn.js is duplicated here. The alternative was to -// add a *lot* of extra cruft to that file, making it less readable -// and slower. Copying and editing the code allowed me to make -// invasive changes and simplifications without creating a complicated -// tangle. + Object.defineProperty(exports, '__esModule', { value: true }); -acorn.defaultOptions.tabSize = 4; - -function parse(input, options) { - return LooseParser.parse(input, options) -} - -exports.parse = parse; -exports.LooseParser = LooseParser; - -Object.defineProperty(exports, '__esModule', { value: true }); - -}))); +})); // clang-format on
diff --git a/third_party/blink/renderer/devtools/front_end/help/Help.js b/third_party/blink/renderer/devtools/front_end/help/Help.js index 5c31963b..71b3bd3 100644 --- a/third_party/blink/renderer/devtools/front_end/help/Help.js +++ b/third_party/blink/renderer/devtools/front_end/help/Help.js
@@ -79,7 +79,7 @@ * @return {boolean} */ handleAction(context, actionId) { - InspectorFrontendHost.openInNewTab(Help.latestReleaseNote().link); + Host.InspectorFrontendHost.openInNewTab(Help.latestReleaseNote().link); return true; } }; @@ -95,7 +95,8 @@ * @return {boolean} */ handleAction(context, actionId) { - InspectorFrontendHost.openInNewTab('https://bugs.chromium.org/p/chromium/issues/entry?template=DevTools+issue'); + Host.InspectorFrontendHost.openInNewTab( + 'https://bugs.chromium.org/p/chromium/issues/entry?template=DevTools+issue'); return true; } };
diff --git a/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js b/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js index 41eb8db6..dc0f50dd 100644 --- a/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js +++ b/third_party/blink/renderer/devtools/front_end/help/ReleaseNoteView.js
@@ -33,7 +33,7 @@ const actionContainer = container.createChild('div', 'release-note-action-container'); actionContainer.appendChild(UI.createTextButton(Common.UIString('Learn more'), event => { event.consume(true); - InspectorFrontendHost.openInNewTab(releaseNote.link); + Host.InspectorFrontendHost.openInNewTab(releaseNote.link); })); actionContainer.appendChild(UI.createTextButton(Common.UIString('Close'), event => { event.consume(true);
diff --git a/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js b/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js index 33cbc85e..c8e0eda 100644 --- a/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js +++ b/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHost.js
@@ -31,22 +31,23 @@ * @implements {InspectorFrontendHostAPI} * @unrestricted */ -Host.InspectorFrontendHostStub = class { +export class InspectorFrontendHostStub { /** * @suppressGlobalPropertiesCheck */ constructor() { /** * @param {!Event} event + * @this {InspectorFrontendHostAPI} */ function stopEventPropagation(event) { // Let browser handle Ctrl+/Ctrl- shortcuts in hosted mode. - const zoomModifier = Host.isMac() ? event.metaKey : event.ctrlKey; + const zoomModifier = this.platform() === 'mac' ? event.metaKey : event.ctrlKey; if (zoomModifier && (event.keyCode === 187 || event.keyCode === 189)) { event.stopPropagation(); } } - document.addEventListener('keydown', stopEventPropagation, true); + document.addEventListener('keydown', stopEventPropagation.bind(this), true); /** * @type {!Map<string, !Array<string>>} */ @@ -498,17 +499,22 @@ setAddExtensionCallback(callback) { // Extensions are not supported in hosted mode. } -}; +} + +/** + * @type {!InspectorFrontendHostStub} + */ +let _InspectorFrontendHost = window.InspectorFrontendHost; /** * @unrestricted */ -Host.InspectorFrontendAPIImpl = class { +export class InspectorFrontendAPIImpl { constructor() { this._debugFrontend = !!Root.Runtime.queryParam('debugFrontend') || (window['InspectorTest'] && window['InspectorTest']['debugTest']); - const descriptors = Host.InspectorFrontendAPIImpl.EventDescriptors; + const descriptors = Host.InspectorFrontendHostAPI.EventDescriptors; for (let i = 0; i < descriptors.length; ++i) { this[descriptors[i][1]] = this._dispatch.bind(this, descriptors[i][0], descriptors[i][2], descriptors[i][3]); } @@ -532,7 +538,7 @@ // Single argument methods get dispatched with the param. if (signature.length < 2) { try { - InspectorFrontendHost.events.dispatchEventToListeners(name, params[0]); + _InspectorFrontendHost.events.dispatchEventToListeners(name, params[0]); } catch (e) { console.error(e + ' ' + e.stack); } @@ -543,7 +549,7 @@ data[signature[i]] = params[i]; } try { - InspectorFrontendHost.events.dispatchEventToListeners(name, data); + _InspectorFrontendHost.events.dispatchEventToListeners(name, data); } catch (e) { console.error(e + ' ' + e.stack); } @@ -557,88 +563,45 @@ streamWrite(id, chunk) { Host.ResourceLoader.streamWrite(id, chunk); } -}; +} -Host.InspectorFrontendAPIImpl.EventDescriptors = [ - [Host.InspectorFrontendHostAPI.Events.AppendedToURL, 'appendedToURL', ['url']], - [Host.InspectorFrontendHostAPI.Events.CanceledSaveURL, 'canceledSaveURL', ['url']], - [Host.InspectorFrontendHostAPI.Events.ContextMenuCleared, 'contextMenuCleared', []], - [Host.InspectorFrontendHostAPI.Events.ContextMenuItemSelected, 'contextMenuItemSelected', ['id']], - [Host.InspectorFrontendHostAPI.Events.DeviceCountUpdated, 'deviceCountUpdated', ['count']], - [Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, 'devicesDiscoveryConfigChanged', ['config']], - [ - Host.InspectorFrontendHostAPI.Events.DevicesPortForwardingStatusChanged, 'devicesPortForwardingStatusChanged', - ['status'] - ], - [Host.InspectorFrontendHostAPI.Events.DevicesUpdated, 'devicesUpdated', ['devices']], - [Host.InspectorFrontendHostAPI.Events.DispatchMessage, 'dispatchMessage', ['messageObject']], - [Host.InspectorFrontendHostAPI.Events.DispatchMessageChunk, 'dispatchMessageChunk', ['messageChunk', 'messageSize']], - [Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode, 'enterInspectElementMode', []], - [Host.InspectorFrontendHostAPI.Events.EyeDropperPickedColor, 'eyeDropperPickedColor', ['color']], - [Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, 'fileSystemsLoaded', ['fileSystems']], - [Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, 'fileSystemRemoved', ['fileSystemPath']], - [Host.InspectorFrontendHostAPI.Events.FileSystemAdded, 'fileSystemAdded', ['errorMessage', 'fileSystem']], - [ - Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, 'fileSystemFilesChangedAddedRemoved', - ['changed', 'added', 'removed'] - ], - [ - Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, 'indexingTotalWorkCalculated', - ['requestId', 'fileSystemPath', 'totalWork'] - ], - [Host.InspectorFrontendHostAPI.Events.IndexingWorked, 'indexingWorked', ['requestId', 'fileSystemPath', 'worked']], - [Host.InspectorFrontendHostAPI.Events.IndexingDone, 'indexingDone', ['requestId', 'fileSystemPath']], - [Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, 'keyEventUnhandled', ['event']], - [Host.InspectorFrontendHostAPI.Events.ReloadInspectedPage, 'reloadInspectedPage', ['hard']], - [Host.InspectorFrontendHostAPI.Events.RevealSourceLine, 'revealSourceLine', ['url', 'lineNumber', 'columnNumber']], - [Host.InspectorFrontendHostAPI.Events.SavedURL, 'savedURL', ['url', 'fileSystemPath']], - [Host.InspectorFrontendHostAPI.Events.SearchCompleted, 'searchCompleted', ['requestId', 'fileSystemPath', 'files']], - [Host.InspectorFrontendHostAPI.Events.SetInspectedTabId, 'setInspectedTabId', ['tabId']], - [Host.InspectorFrontendHostAPI.Events.SetUseSoftMenu, 'setUseSoftMenu', ['useSoftMenu']], - [Host.InspectorFrontendHostAPI.Events.ShowPanel, 'showPanel', ['panelName']] -]; - -/** - * @type {!Host.InspectorFrontendHostStub} - */ -let InspectorFrontendHost = window.InspectorFrontendHost; (function() { function initializeInspectorFrontendHost() { let proto; - if (!InspectorFrontendHost) { + if (!_InspectorFrontendHost) { // Instantiate stub for web-hosted mode if necessary. - window.InspectorFrontendHost = InspectorFrontendHost = new Host.InspectorFrontendHostStub(); + window.InspectorFrontendHost = _InspectorFrontendHost = new InspectorFrontendHostStub(); } else { // Otherwise add stubs for missing methods that are declared in the interface. - proto = Host.InspectorFrontendHostStub.prototype; + proto = InspectorFrontendHostStub.prototype; for (const name of Object.getOwnPropertyNames(proto)) { const stub = proto[name]; - if (typeof stub !== 'function' || InspectorFrontendHost[name]) { + if (typeof stub !== 'function' || _InspectorFrontendHost[name]) { continue; } console.error( - 'Incompatible embedder: method InspectorFrontendHost.' + name + ' is missing. Using stub instead.'); - InspectorFrontendHost[name] = stub; + 'Incompatible embedder: method Host.InspectorFrontendHost.' + name + ' is missing. Using stub instead.'); + _InspectorFrontendHost[name] = stub; } } // Attach the events object. - InspectorFrontendHost.events = new Common.Object(); + _InspectorFrontendHost.events = new Common.Object(); } // FIXME: This file is included into both apps, since the devtools_app needs the InspectorFrontendHostAPI only, // so the host instance should not initialized there. initializeInspectorFrontendHost(); - window.InspectorFrontendAPI = new Host.InspectorFrontendAPIImpl(); + window.InspectorFrontendAPI = new InspectorFrontendAPIImpl(); })(); /** * @param {!Object<string, string>=} prefs * @return {boolean} */ -Host.isUnderTest = function(prefs) { +export function isUnderTest(prefs) { // Integration tests rely on test queryParam. if (Root.Runtime.queryParam('test')) { return true; @@ -648,4 +611,21 @@ return prefs['isUnderTest'] === 'true'; } return Common.settings && Common.settings.createSetting('isUnderTest', false).get(); -}; +} + +/* Legacy exported object */ +self.Host = self.Host || {}; + +/* Legacy exported object */ +Host = Host || {}; + +/** @type {!InspectorFrontendHostStub} */ +Host.InspectorFrontendHost = _InspectorFrontendHost; + +/** @constructor */ +Host.InspectorFrontendHostStub = InspectorFrontendHostStub; + +/** @constructor */ +Host.InspectorFrontendAPIImpl = InspectorFrontendAPIImpl; + +Host.isUnderTest = isUnderTest; \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js b/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js index e017314..2d09632 100644 --- a/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js +++ b/third_party/blink/renderer/devtools/front_end/host/InspectorFrontendHostAPI.js
@@ -2,10 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -Host.InspectorFrontendHostAPI = {}; - /** @enum {symbol} */ -Host.InspectorFrontendHostAPI.Events = { +export const Events = { AppendedToURL: Symbol('appendedToURL'), CanceledSaveURL: Symbol('canceledSaveURL'), ContextMenuCleared: Symbol('contextMenuCleared'), @@ -34,3 +32,44 @@ SetUseSoftMenu: Symbol('setUseSoftMenu'), ShowPanel: Symbol('showPanel') }; + +export const EventDescriptors = [ + [Events.AppendedToURL, 'appendedToURL', ['url']], + [Events.CanceledSaveURL, 'canceledSaveURL', ['url']], + [Events.ContextMenuCleared, 'contextMenuCleared', []], + [Events.ContextMenuItemSelected, 'contextMenuItemSelected', ['id']], + [Events.DeviceCountUpdated, 'deviceCountUpdated', ['count']], + [Events.DevicesDiscoveryConfigChanged, 'devicesDiscoveryConfigChanged', ['config']], + [Events.DevicesPortForwardingStatusChanged, 'devicesPortForwardingStatusChanged', ['status']], + [Events.DevicesUpdated, 'devicesUpdated', ['devices']], + [Events.DispatchMessage, 'dispatchMessage', ['messageObject']], + [Events.DispatchMessageChunk, 'dispatchMessageChunk', ['messageChunk', 'messageSize']], + [Events.EnterInspectElementMode, 'enterInspectElementMode', []], + [Events.EyeDropperPickedColor, 'eyeDropperPickedColor', ['color']], + [Events.FileSystemsLoaded, 'fileSystemsLoaded', ['fileSystems']], + [Events.FileSystemRemoved, 'fileSystemRemoved', ['fileSystemPath']], + [Events.FileSystemAdded, 'fileSystemAdded', ['errorMessage', 'fileSystem']], + [Events.FileSystemFilesChangedAddedRemoved, 'fileSystemFilesChangedAddedRemoved', ['changed', 'added', 'removed']], + [Events.IndexingTotalWorkCalculated, 'indexingTotalWorkCalculated', ['requestId', 'fileSystemPath', 'totalWork']], + [Events.IndexingWorked, 'indexingWorked', ['requestId', 'fileSystemPath', 'worked']], + [Events.IndexingDone, 'indexingDone', ['requestId', 'fileSystemPath']], + [Events.KeyEventUnhandled, 'keyEventUnhandled', ['event']], + [Events.ReloadInspectedPage, 'reloadInspectedPage', ['hard']], + [Events.RevealSourceLine, 'revealSourceLine', ['url', 'lineNumber', 'columnNumber']], + [Events.SavedURL, 'savedURL', ['url', 'fileSystemPath']], + [Events.SearchCompleted, 'searchCompleted', ['requestId', 'fileSystemPath', 'files']], + [Events.SetInspectedTabId, 'setInspectedTabId', ['tabId']], + [Events.SetUseSoftMenu, 'setUseSoftMenu', ['useSoftMenu']], + [Events.ShowPanel, 'showPanel', ['panelName']] +]; + +/* Legacy exported object */ +self.Host = self.Host || {}; + +/* Legacy exported object */ +Host = Host || {}; + +Host.InspectorFrontendHostAPI = {}; + +Host.InspectorFrontendHostAPI.Events = Events; +Host.InspectorFrontendHostAPI.EventDescriptors = EventDescriptors; \ No newline at end of file
diff --git a/third_party/blink/renderer/devtools/front_end/host/Platform.js b/third_party/blink/renderer/devtools/front_end/host/Platform.js index 463cc66c..3f52f6a 100644 --- a/third_party/blink/renderer/devtools/front_end/host/Platform.js +++ b/third_party/blink/renderer/devtools/front_end/host/Platform.js
@@ -25,65 +25,88 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -/** - * @return {string} - */ -Host.platform = function() { - if (!Host._platform) { - Host._platform = InspectorFrontendHost.platform(); - } - return Host._platform; -}; -/** - * @return {boolean} - */ -Host.isMac = function() { - if (typeof Host._isMac === 'undefined') { - Host._isMac = Host.platform() === 'mac'; - } - - return Host._isMac; -}; - -/** - * @return {boolean} - */ -Host.isWin = function() { - if (typeof Host._isWin === 'undefined') { - Host._isWin = Host.platform() === 'windows'; - } - - return Host._isWin; -}; - -/** - * @return {boolean} - */ -Host.isCustomDevtoolsFrontend = function() { - if (typeof Host._isCustomDevtoolsFronend === 'undefined') { - Host._isCustomDevtoolsFronend = window.location.toString().startsWith('devtools://devtools/custom/'); - } - return Host._isCustomDevtoolsFronend; -}; +let _platform; /** * @return {string} */ -Host.fontFamily = function() { - if (Host._fontFamily) { - return Host._fontFamily; +export function platform() { + if (!_platform) { + _platform = Host.InspectorFrontendHost.platform(); } - switch (Host.platform()) { + return _platform; +} + +let _isMac; + +/** + * @return {boolean} + */ +export function isMac() { + if (typeof _isMac === 'undefined') { + _isMac = platform() === 'mac'; + } + + return _isMac; +} + +let _isWin; + +/** + * @return {boolean} + */ +export function isWin() { + if (typeof _isWin === 'undefined') { + _isWin = platform() === 'windows'; + } + + return _isWin; +} + +let _isCustomDevtoolsFrontend; + +/** + * @return {boolean} + */ +export function isCustomDevtoolsFrontend() { + if (typeof _isCustomDevtoolsFrontend === 'undefined') { + _isCustomDevtoolsFrontend = window.location.toString().startsWith('devtools://devtools/custom/'); + } + return _isCustomDevtoolsFrontend; +} + +let _fontFamily; + +/** + * @return {string} + */ +export function fontFamily() { + if (_fontFamily) { + return _fontFamily; + } + switch (platform()) { case 'linux': - Host._fontFamily = 'Roboto, Ubuntu, Arial, sans-serif'; + _fontFamily = 'Roboto, Ubuntu, Arial, sans-serif'; break; case 'mac': - Host._fontFamily = '\'Lucida Grande\', sans-serif'; + _fontFamily = '\'Lucida Grande\', sans-serif'; break; case 'windows': - Host._fontFamily = '\'Segoe UI\', Tahoma, sans-serif'; + _fontFamily = '\'Segoe UI\', Tahoma, sans-serif'; break; } - return Host._fontFamily; -}; + return _fontFamily; +} + +/* Legacy exported object */ +self.Host = self.Host || {}; + +/* Legacy exported object */ +Host = Host || {}; + +Host.platform = platform; +Host.isWin = isWin; +Host.isMac = isMac; +Host.isCustomDevtoolsFrontend = isCustomDevtoolsFrontend; +Host.fontFamily = fontFamily;
diff --git a/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js b/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js index 512ec2b..fb2fe37 100644 --- a/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js +++ b/third_party/blink/renderer/devtools/front_end/host/ResourceLoader.js
@@ -1,35 +1,37 @@ // Copyright (c) 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. -Host.ResourceLoader = {}; +const ResourceLoader = {}; +export default ResourceLoader; -Host.ResourceLoader._lastStreamId = 0; +export let _lastStreamId = 0; + /** @type {!Object.<number, !Common.OutputStream>} */ -Host.ResourceLoader._boundStreams = {}; +export const _boundStreams = {}; /** * @param {!Common.OutputStream} stream * @return {number} */ -Host.ResourceLoader._bindOutputStream = function(stream) { - Host.ResourceLoader._boundStreams[++Host.ResourceLoader._lastStreamId] = stream; - return Host.ResourceLoader._lastStreamId; +export const _bindOutputStream = function(stream) { + _boundStreams[++_lastStreamId] = stream; + return _lastStreamId; }; /** * @param {number} id */ -Host.ResourceLoader._discardOutputStream = function(id) { - Host.ResourceLoader._boundStreams[id].close(); - delete Host.ResourceLoader._boundStreams[id]; +export const _discardOutputStream = function(id) { + _boundStreams[id].close(); + delete _boundStreams[id]; }; /** * @param {number} id * @param {string} chunk */ -Host.ResourceLoader.streamWrite = function(id, chunk) { - Host.ResourceLoader._boundStreams[id].write(chunk); +export const streamWrite = function(id, chunk) { + _boundStreams[id].write(chunk); }; /** @@ -37,9 +39,9 @@ * @param {?Object.<string, string>} headers * @param {function(number, !Object.<string, string>, string)} callback */ -Host.ResourceLoader.load = function(url, headers, callback) { +export function load(url, headers, callback) { const stream = new Common.StringOutputStream(); - Host.ResourceLoader.loadAsStream(url, headers, stream, mycallback); + loadAsStream(url, headers, stream, mycallback); /** * @param {number} statusCode @@ -48,7 +50,7 @@ function mycallback(statusCode, headers) { callback(statusCode, headers, stream.data()); } -}; +} /** * @param {string} url @@ -56,8 +58,8 @@ * @param {!Common.OutputStream} stream * @param {function(number, !Object.<string, string>)=} callback */ -Host.ResourceLoader.loadAsStream = function(url, headers, stream, callback) { - const streamId = Host.ResourceLoader._bindOutputStream(stream); +export const loadAsStream = function(url, headers, stream, callback) { + const streamId = _bindOutputStream(stream); const parsedURL = new Common.ParsedURL(url); if (parsedURL.isDataURL()) { loadXHR(url).then(dataURLDecodeSuccessful).catch(dataURLDecodeFailed); @@ -70,7 +72,7 @@ rawHeaders.push(key + ': ' + headers[key]); } } - InspectorFrontendHost.loadNetworkResource(url, rawHeaders.join('\r\n'), streamId, finishedCallback); + Host.InspectorFrontendHost.loadNetworkResource(url, rawHeaders.join('\r\n'), streamId, finishedCallback); /** * @param {!InspectorFrontendHostAPI.LoadNetworkResourceResult} response @@ -79,14 +81,14 @@ if (callback) { callback(response.statusCode, response.headers || {}); } - Host.ResourceLoader._discardOutputStream(streamId); + _discardOutputStream(streamId); } /** * @param {string} text */ function dataURLDecodeSuccessful(text) { - Host.ResourceLoader.streamWrite(streamId, text); + streamWrite(streamId, text); finishedCallback(/** @type {!InspectorFrontendHostAPI.LoadNetworkResourceResult} */ ({statusCode: 200})); } @@ -94,3 +96,48 @@ finishedCallback(/** @type {!InspectorFrontendHostAPI.LoadNetworkResourceResult} */ ({statusCode: 404})); } }; + +/* Legacy exported object */ +self.Host = self.Host || {}; + +/* Legacy exported object */ +Host = Host || {}; + +Host.ResourceLoader = ResourceLoader; + +Host.ResourceLoader._lastStreamId = _lastStreamId; + +/** @type {!Object.<number, !Common.OutputStream>} */ +Host.ResourceLoader._boundStreams = _boundStreams; + +/** + * @param {!Common.OutputStream} stream + * @return {number} + */ +Host.ResourceLoader._bindOutputStream = _bindOutputStream; + +/** + * @param {number} id + */ +Host.ResourceLoader._discardOutputStream = _discardOutputStream; + +/** + * @param {number} id + * @param {string} chunk + */ +Host.ResourceLoader.streamWrite = streamWrite; + +/** + * @param {string} url + * @param {?Object.<string, string>} headers + * @param {function(number, !Object.<string, string>, string)} callback + */ +Host.ResourceLoader.load = load; + +/** + * @param {string} url + * @param {?Object.<string, string>} headers + * @param {!Common.OutputStream} stream + * @param {function(number, !Object.<string, string>)=} callback + */ +Host.ResourceLoader.loadAsStream = loadAsStream;
diff --git a/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js b/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js index 55a5d8d..e4293bbe 100644 --- a/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js +++ b/third_party/blink/renderer/devtools/front_end/host/UserMetrics.js
@@ -31,14 +31,14 @@ /** * @unrestricted */ -Host.UserMetrics = class { +export default class UserMetrics { /** * @param {string} panelName */ panelShown(panelName) { - const code = Host.UserMetrics._PanelCodes[panelName] || 0; - const size = Object.keys(Host.UserMetrics._PanelCodes).length + 1; - InspectorFrontendHost.recordEnumeratedHistogram('DevTools.PanelShown', code, size); + const code = _PanelCodes[panelName] || 0; + const size = Object.keys(_PanelCodes).length + 1; + Host.InspectorFrontendHost.recordEnumeratedHistogram('DevTools.PanelShown', code, size); // Store that the user has changed the panel so we know launch histograms should not be fired. this._panelChangedSinceLaunch = true; } @@ -51,11 +51,11 @@ } /** - * @param {!Host.UserMetrics.Action} action + * @param {!Action} action */ actionTaken(action) { - const size = Object.keys(Host.UserMetrics.Action).length + 1; - InspectorFrontendHost.recordEnumeratedHistogram('DevTools.ActionTaken', action, size); + const size = Object.keys(Action).length + 1; + Host.InspectorFrontendHost.recordEnumeratedHistogram('DevTools.ActionTaken', action, size); } /** @@ -82,7 +82,7 @@ } // This fires the event for the appropriate launch histogram. // The duration is measured as the time elapsed since the time origin of the document. - InspectorFrontendHost.recordPerformanceHistogram(histogramName, performance.now()); + Host.InspectorFrontendHost.recordPerformanceHistogram(histogramName, performance.now()); }, 0); }); } @@ -95,14 +95,14 @@ // Other calls to panelLoaded will be ignored if the name does not match the one set here. this._launchPanelName = panelName; } -}; +} // Codes below are used to collect UMA histograms in the Chromium port. // Do not change the values below, additional actions are needed on the Chromium side // in order to add more codes. /** @enum {number} */ -Host.UserMetrics.Action = { +export const Action = { WindowDocked: 1, WindowUndocked: 2, ScriptsBreakpointSet: 3, @@ -139,7 +139,7 @@ FilmStripStartedRecording: 33, }; -Host.UserMetrics._PanelCodes = { +export const _PanelCodes = { elements: 1, resources: 2, network: 3, @@ -171,5 +171,19 @@ 'drawer-network.blocked-urls': 28, }; +/* Legacy exported object */ +self.Host = self.Host || {}; + +/* Legacy exported object */ +Host = Host || {}; + +/** @constructor */ +Host.UserMetrics = UserMetrics; + +/** @enum {number} */ +Host.UserMetrics.Action = Action; + +Host.UserMetrics._PanelCodes = _PanelCodes; + /** @type {!Host.UserMetrics} */ -Host.userMetrics = new Host.UserMetrics(); +Host.userMetrics = new UserMetrics();
diff --git a/third_party/blink/renderer/devtools/front_end/host/host.js b/third_party/blink/renderer/devtools/front_end/host/host.js new file mode 100644 index 0000000..233da1f4 --- /dev/null +++ b/third_party/blink/renderer/devtools/front_end/host/host.js
@@ -0,0 +1,21 @@ +// Copyright 2019 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 './InspectorFrontendHostAPI.js'; +import './InspectorFrontendHost.js'; +import './ResourceLoader.js'; +import './UserMetrics.js'; +import './Platform.js'; + +import * as InspectorFrontendHost from './InspectorFrontendHost.js'; +import * as Platform from './Platform.js'; +import * as ResourceLoader from './ResourceLoader.js'; +import * as UserMetrics from './UserMetrics.js'; + +export { + InspectorFrontendHost, + Platform, + ResourceLoader, + UserMetrics, +};
diff --git a/third_party/blink/renderer/devtools/front_end/host/module.json b/third_party/blink/renderer/devtools/front_end/host/module.json index 62febc3e..44459c4e 100644 --- a/third_party/blink/renderer/devtools/front_end/host/module.json +++ b/third_party/blink/renderer/devtools/front_end/host/module.json
@@ -3,7 +3,9 @@ "common", "platform" ], - "scripts": [ + "scripts": [], + "modules": [ + "host.js", "InspectorFrontendHostAPI.js", "InspectorFrontendHost.js", "Platform.js",
diff --git a/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js b/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js index f948cac5..15d5265 100644 --- a/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js +++ b/third_party/blink/renderer/devtools/front_end/inspector_main/InspectorMain.js
@@ -40,10 +40,11 @@ new InspectorMain.BackendSettingsSync(); new MobileThrottling.NetworkPanelIndicator(); - InspectorFrontendHost.events.addEventListener(Host.InspectorFrontendHostAPI.Events.ReloadInspectedPage, event => { - const hard = /** @type {boolean} */ (event.data); - SDK.ResourceTreeModel.reloadAllPages(hard); - }); + Host.InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHostAPI.Events.ReloadInspectedPage, event => { + const hard = /** @type {boolean} */ (event.data); + SDK.ResourceTreeModel.reloadAllPages(hard); + }); } }; @@ -96,7 +97,7 @@ const element = createElement('div'); const shadowRoot = UI.createShadowRootWithCoreStyles(element, 'inspector_main/nodeIcon.css'); this._element = shadowRoot.createChild('div', 'node-icon'); - element.addEventListener('click', () => InspectorFrontendHost.openNodeFrontend(), false); + element.addEventListener('click', () => Host.InspectorFrontendHost.openNodeFrontend(), false); this._button = new UI.ToolbarItem(element); this._button.setTitle(Common.UIString('Open dedicated DevTools for Node.js')); SDK.targetManager.addEventListener( @@ -177,7 +178,7 @@ } _updateAutoAttach() { - InspectorFrontendHost.setOpenNewWindowForPopups(this._autoAttachSetting.get()); + Host.InspectorFrontendHost.setOpenNewWindowForPopups(this._autoAttachSetting.get()); } _update() {
diff --git a/third_party/blink/renderer/devtools/front_end/main/Main.js b/third_party/blink/renderer/devtools/front_end/main/Main.js index 04d62f0..a047e50 100644 --- a/third_party/blink/renderer/devtools/front_end/main/Main.js +++ b/third_party/blink/renderer/devtools/front_end/main/Main.js
@@ -65,7 +65,7 @@ await Root.Runtime.appStarted(); Root.Runtime.setPlatform(Host.platform()); Root.Runtime.setL10nCallback(ls); - InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this)); + Host.InspectorFrontendHost.getPreferences(this._gotPreferences.bind(this)); } /** @@ -102,8 +102,8 @@ localStorage = new Common.SettingsStorage({}, undefined, undefined, undefined, storagePrefix); } const globalStorage = new Common.SettingsStorage( - prefs, InspectorFrontendHost.setPreference, InspectorFrontendHost.removePreference, - InspectorFrontendHost.clearPreferences, storagePrefix); + prefs, Host.InspectorFrontendHost.setPreference, Host.InspectorFrontendHost.removePreference, + Host.InspectorFrontendHost.clearPreferences, storagePrefix); Common.settings = new Common.Settings(globalStorage, localStorage); if (!Host.isUnderTest()) { new Common.VersionController().updateVersion(); @@ -185,7 +185,7 @@ this._addMainEventListeners(document); const canDock = !!Root.Runtime.queryParam('can_dock'); - UI.zoomManager = new UI.ZoomManager(window, InspectorFrontendHost); + UI.zoomManager = new UI.ZoomManager(window, Host.InspectorFrontendHost); UI.inspectorView = UI.InspectorView.instance(); UI.ContextMenu.initialize(); UI.ContextMenu.installHandler(document); @@ -249,15 +249,15 @@ const toggleSearchNodeAction = UI.actionRegistry.action('elements.toggle-element-search'); // TODO: we should not access actions from other modules. if (toggleSearchNodeAction) { - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.EnterInspectElementMode, toggleSearchNodeAction.execute.bind(toggleSearchNodeAction), this); } - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.RevealSourceLine, this._revealSourceLine, this); UI.inspectorView.createToolbars(); - InspectorFrontendHost.loadCompleted(); + Host.InspectorFrontendHost.loadCompleted(); const extensions = self.runtime.extensions(Common.QueryParamHandler); for (const extension of extensions) { @@ -288,7 +288,7 @@ await /** @type {!Common.Runnable} */ (instance).run(); } // Used for browser tests. - InspectorFrontendHost.readyForTest(); + Host.InspectorFrontendHost.readyForTest(); // Asynchronously run the extensions. setTimeout(this._lateInitialization.bind(this), 100); Main.Main.timeEnd('Main._initializeTarget'); @@ -336,7 +336,7 @@ ]; const actionKeys = UI.shortcutRegistry.keysForActions(forwardedActions).map(UI.KeyboardShortcut.keyCodeAndModifiersFromKey); - InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys)); + Host.InspectorFrontendHost.setWhitelistedShortcuts(JSON.stringify(actionKeys)); } _registerMessageSinkListener() { @@ -485,19 +485,19 @@ * @return {boolean} */ handleAction(context, actionId) { - if (InspectorFrontendHost.isHostedMode()) { + if (Host.InspectorFrontendHost.isHostedMode()) { return false; } switch (actionId) { case 'main.zoom-in': - InspectorFrontendHost.zoomIn(); + Host.InspectorFrontendHost.zoomIn(); return true; case 'main.zoom-out': - InspectorFrontendHost.zoomOut(); + Host.InspectorFrontendHost.zoomOut(); return true; case 'main.zoom-reset': - InspectorFrontendHost.resetZoom(); + Host.InspectorFrontendHost.resetZoom(); return true; } return false;
diff --git a/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js b/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js index 80ae440..04c63896 100644 --- a/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js +++ b/third_party/blink/renderer/devtools/front_end/network/BinaryResourceView.js
@@ -78,7 +78,7 @@ async _copySelectedViewToClipboard() { const viewObject = this._getCurrentViewObject(); - InspectorFrontendHost.copyText(await viewObject.content()); + Host.InspectorFrontendHost.copyText(await viewObject.content()); this._copiedText.setText(viewObject.copiedMessage); this._copiedText.element.classList.remove('fadeout'); /** @@ -144,11 +144,13 @@ const footerSection = copyMenu.footerSection(); footerSection.appendItem( - ls`Copy as Base64`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.base64())); + ls`Copy as Base64`, + async () => Host.InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.base64())); footerSection.appendItem( - ls`Copy as Hex`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.hex())); + ls`Copy as Hex`, async () => Host.InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.hex())); footerSection.appendItem( - ls`Copy as UTF-8`, async () => InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.utf8())); + ls`Copy as UTF-8`, + async () => Host.InspectorFrontendHost.copyText(await this._binaryResourceViewFactory.utf8())); } };
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js b/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js index c6143af..10a21c3 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkDataGridNode.js
@@ -817,7 +817,7 @@ } _openInNewTab() { - InspectorFrontendHost.openInNewTab(this._request.url()); + Host.InspectorFrontendHost.openInNewTab(this._request.url()); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js index 8aa0b86a..6bce12d 100644 --- a/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js +++ b/third_party/blink/renderer/devtools/front_end/network/NetworkLogView.js
@@ -427,14 +427,14 @@ * @param {!SDK.NetworkRequest} request */ static _copyRequestHeaders(request) { - InspectorFrontendHost.copyText(request.requestHeadersText()); + Host.InspectorFrontendHost.copyText(request.requestHeadersText()); } /** * @param {!SDK.NetworkRequest} request */ static _copyResponseHeaders(request) { - InspectorFrontendHost.copyText(request.responseHeadersText); + Host.InspectorFrontendHost.copyText(request.responseHeadersText); } /** @@ -448,7 +448,7 @@ } else if (contentData.encoded) { content = window.atob(content); } - InspectorFrontendHost.copyText(content); + Host.InspectorFrontendHost.copyText(content); } /** @@ -1213,7 +1213,8 @@ const footerSection = copyMenu.footerSection(); if (request) { copyMenu.defaultSection().appendItem( - UI.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, request.contentURL())); + UI.copyLinkAddressLabel(), + Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, request.contentURL())); if (request.requestHeadersText()) { copyMenu.defaultSection().appendItem( Common.UIString('Copy request headers'), Network.NetworkLogView._copyRequestHeaders.bind(null, request)); @@ -1323,7 +1324,7 @@ async _copyAll() { const harArchive = {log: await SDK.HARLog.build(this._harRequests())}; - InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2)); + Host.InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2)); } /** @@ -1332,7 +1333,7 @@ */ async _copyCurlCommand(request, platform) { const command = await this._generateCurlCommand(request, platform); - InspectorFrontendHost.copyText(command); + Host.InspectorFrontendHost.copyText(command); } /** @@ -1340,7 +1341,7 @@ */ async _copyAllCurlCommand(platform) { const commands = await this._generateAllCurlCommand(SDK.networkLog.requests(), platform); - InspectorFrontendHost.copyText(commands); + Host.InspectorFrontendHost.copyText(commands); } /** @@ -1349,12 +1350,12 @@ */ async _copyFetchCall(request, platform) { const command = await this._generateFetchCall(request); - InspectorFrontendHost.copyText(command); + Host.InspectorFrontendHost.copyText(command); } async _copyAllFetchCall() { const commands = await this._generateAllFetchCall(SDK.networkLog.requests()); - InspectorFrontendHost.copyText(commands); + Host.InspectorFrontendHost.copyText(commands); } /** @@ -1362,12 +1363,12 @@ */ async _copyPowerShellCommand(request) { const command = await this._generatePowerShellCommand(request); - InspectorFrontendHost.copyText(command); + Host.InspectorFrontendHost.copyText(command); } async _copyAllPowerShellCommand() { const commands = await this._generateAllPowerShellCommand(SDK.networkLog.requests()); - InspectorFrontendHost.copyText(commands); + Host.InspectorFrontendHost.copyText(commands); } async exportAll() {
diff --git a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js index c78ff602..9145383 100644 --- a/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js +++ b/third_party/blink/renderer/devtools/front_end/network/ResourceWebSocketFrameView.js
@@ -103,7 +103,7 @@ } else { contextMenu.clipboardSection().appendItem( Common.UIString('Copy message'), - InspectorFrontendHost.copyText.bind(InspectorFrontendHost, node.data.data)); + Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, node.data.data)); } contextMenu.footerSection().appendItem(Common.UIString('Clear all'), this._clearFrames.bind(this)); }
diff --git a/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js b/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js index 4186fc9d..d86b5bc 100644 --- a/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js +++ b/third_party/blink/renderer/devtools/front_end/network/SignedExchangeInfoView.js
@@ -89,7 +89,7 @@ const viewCertLink = certURLElement.createChild('span', 'devtools-link header-toggle'); viewCertLink.textContent = Common.UIString('View certificate'); viewCertLink.addEventListener( - 'click', InspectorFrontendHost.showCertificateViewer.bind(null, signature.certificates), false); + 'click', Host.InspectorFrontendHost.showCertificateViewer.bind(null, signature.certificates), false); } signatureCategory.createLeaf(certURLElement); }
diff --git a/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js b/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js index 76ecfc4..ccb2444 100644 --- a/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js +++ b/third_party/blink/renderer/devtools/front_end/node_main/NodeConnectionsPanel.js
@@ -13,7 +13,7 @@ const image = container.createChild('img', 'node-panel-logo'); image.src = 'https://nodejs.org/static/images/logos/nodejs-new-pantone-black.png'; - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); /** @type {!Adb.Config} */ @@ -23,12 +23,12 @@ this.setDefaultFocusedElement(this.contentElement); // Trigger notification once. - InspectorFrontendHost.setDevicesUpdatesEnabled(false); - InspectorFrontendHost.setDevicesUpdatesEnabled(true); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true); this._networkDiscoveryView = new NodeMain.NodeConnectionsView(config => { this._config.networkDiscoveryConfig = config; - InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); + Host.InspectorFrontendHost.setDevicesDiscoveryConfig(this._config); }); this._networkDiscoveryView.show(container); }
diff --git a/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js b/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js index 16de289..4786743 100644 --- a/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js +++ b/third_party/blink/renderer/devtools/front_end/node_main/NodeMain.js
@@ -38,10 +38,10 @@ parentTarget.registerTargetDispatcher(this); this._targetAgent.setDiscoverTargets(true); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); - InspectorFrontendHost.setDevicesUpdatesEnabled(false); - InspectorFrontendHost.setDevicesUpdatesEnabled(true); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(false); + Host.InspectorFrontendHost.setDevicesUpdatesEnabled(true); } /** @@ -64,7 +64,7 @@ * @override */ dispose() { - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.DevicesDiscoveryConfigChanged, this._devicesDiscoveryConfigChanged, this); for (const sessionId of this._childTargets.keys()) {
diff --git a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js index b77eb97..31b3873d 100644 --- a/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js +++ b/third_party/blink/renderer/devtools/front_end/object_ui/ObjectPropertiesSection.js
@@ -934,7 +934,8 @@ contextMenu.appendApplicableItems(this.property.value); } if (!this.property.synthetic && this.nameElement && this.nameElement.title) { - const copyPathHandler = InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this.nameElement.title); + const copyPathHandler = + Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost, this.nameElement.title); contextMenu.clipboardSection().appendItem(ls`Copy property path`, copyPathHandler); } if (this.property.parentObject instanceof SDK.LocalJSONObject) {
diff --git a/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js b/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js index 6efb09a..206fdc2cf 100644 --- a/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js +++ b/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystem.js
@@ -67,7 +67,7 @@ * @return {!Promise<?Persistence.IsolatedFileSystem>} */ static create(manager, path, embedderPath, type, name, rootURL) { - const domFileSystem = InspectorFrontendHost.isolatedFileSystem(name, rootURL); + const domFileSystem = Host.InspectorFrontendHost.isolatedFileSystem(name, rootURL); if (!domFileSystem) { return Promise.resolve(/** @type {?Persistence.IsolatedFileSystem} */ (null)); } @@ -628,7 +628,7 @@ searchInPath(query, progress) { return new Promise(resolve => { const requestId = this._manager.registerCallback(innerCallback); - InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query); + Host.InspectorFrontendHost.searchInPath(requestId, this._embedderPath, query); /** * @param {!Array<string>} files @@ -647,7 +647,7 @@ indexContent(progress) { progress.setTotalWork(1); const requestId = this._manager.registerProgress(progress); - InspectorFrontendHost.indexPath(requestId, this._embedderPath, JSON.stringify(this._excludedEmbedderFolders)); + Host.InspectorFrontendHost.indexPath(requestId, this._embedderPath, JSON.stringify(this._excludedEmbedderFolders)); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js b/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js index f08840a..f204966 100644 --- a/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js +++ b/third_party/blink/renderer/devtools/front_end/persistence/IsolatedFileSystemManager.js
@@ -42,19 +42,19 @@ /** @type {!Map<number, !Common.Progress>} */ this._progresses = new Map(); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.FileSystemRemoved, this._onFileSystemRemoved, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.FileSystemAdded, this._onFileSystemAdded, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.FileSystemFilesChangedAddedRemoved, this._onFileSystemFilesChanged, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.IndexingTotalWorkCalculated, this._onIndexingTotalWorkCalculated, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.IndexingWorked, this._onIndexingWorked, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.IndexingDone, this._onIndexingDone, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.SearchCompleted, this._onSearchCompleted, this); this._initExcludePatterSetting(); @@ -70,9 +70,9 @@ _requestFileSystems() { let fulfill; const promise = new Promise(f => fulfill = f); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.FileSystemsLoaded, onFileSystemsLoaded, this); - InspectorFrontendHost.requestFileSystems(); + Host.InspectorFrontendHost.requestFileSystems(); return promise; /** @@ -103,7 +103,7 @@ addFileSystem(type) { return new Promise(resolve => { this._fileSystemRequestResolve = resolve; - InspectorFrontendHost.addFileSystem(type || ''); + Host.InspectorFrontendHost.addFileSystem(type || ''); }); } @@ -111,7 +111,7 @@ * @param {!Persistence.PlatformFileSystem} fileSystem */ removeFileSystem(fileSystem) { - InspectorFrontendHost.removeFileSystem(fileSystem.embedderPath()); + Host.InspectorFrontendHost.removeFileSystem(fileSystem.embedderPath()); } /** @@ -324,7 +324,7 @@ } progress.worked(worked); if (progress.isCanceled()) { - InspectorFrontendHost.stopIndexing(requestId); + Host.InspectorFrontendHost.stopIndexing(requestId); this._onIndexingDone(event); } }
diff --git a/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js b/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js index a286f5e..a14c690 100644 --- a/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js +++ b/third_party/blink/renderer/devtools/front_end/persistence/PersistenceActions.js
@@ -50,7 +50,7 @@ if (fileURL.startsWith('file://')) { const path = Common.ParsedURL.urlToPlatformPath(fileURL, Host.isWin()); contextMenu.revealSection().appendItem( - Common.UIString('Open in containing folder'), () => InspectorFrontendHost.showItemInFolder(path)); + Common.UIString('Open in containing folder'), () => Host.InspectorFrontendHost.showItemInFolder(path)); } } };
diff --git a/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js b/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js index 62bb74d..10be5ae 100644 --- a/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js +++ b/third_party/blink/renderer/devtools/front_end/protocol_monitor/ProtocolMonitor.js
@@ -122,7 +122,7 @@ contextMenu.defaultSection().appendItem(ls`Documentation`, () => { const [domain, method] = node.data.method.split('.'); const type = node.data.direction === 'sent' ? 'method' : 'event'; - InspectorFrontendHost.openInNewTab( + Host.InspectorFrontendHost.openInNewTab( `https://chromedevtools.github.io/devtools-protocol/tot/${domain}#${type}-${method}`); }); }
diff --git a/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js b/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js index b16bdc5..92b9080 100644 --- a/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js +++ b/third_party/blink/renderer/devtools/front_end/quick_open/CommandMenu.js
@@ -326,7 +326,7 @@ * @return {boolean} */ handleAction(context, actionId) { - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); QuickOpen.QuickOpen.show('>'); return true; }
diff --git a/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js b/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js index 9fcec54e..83b2d20 100644 --- a/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js +++ b/third_party/blink/renderer/devtools/front_end/resources/ResourcesSection.js
@@ -360,7 +360,7 @@ * @return {boolean} */ ondblclick(event) { - InspectorFrontendHost.openInNewTab(this._resource.url); + Host.InspectorFrontendHost.openInNewTab(this._resource.url); return false; }
diff --git a/third_party/blink/renderer/devtools/front_end/root.js b/third_party/blink/renderer/devtools/front_end/root.js index df20787..6447d501a 100644 --- a/third_party/blink/renderer/devtools/front_end/root.js +++ b/third_party/blink/renderer/devtools/front_end/root.js
@@ -4,4 +4,5 @@ import './Runtime.js'; import './common/common.js'; +import './host/host.js'; import './ui/ui.js';
diff --git a/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js b/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js index b1639675..d7fd5ef 100644 --- a/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js +++ b/third_party/blink/renderer/devtools/front_end/screencast/ScreencastView.js
@@ -716,7 +716,7 @@ if (match) { url = match[1]; } - InspectorFrontendHost.inspectedURLChanged(url); + Host.InspectorFrontendHost.inspectedURLChanged(url); this._navigationUrl.value = url; }
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/Connections.js b/third_party/blink/renderer/devtools/front_end/sdk/Connections.js index 3580a03..d2c0fe65 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/Connections.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/Connections.js
@@ -12,9 +12,9 @@ this._messageBuffer = ''; this._messageSize = 0; this._eventListeners = [ - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DispatchMessage, this._dispatchMessage, this), - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.DispatchMessageChunk, this._dispatchMessageChunk, this), ]; } @@ -41,7 +41,7 @@ */ sendRawMessage(message) { if (this._onMessage) { - InspectorFrontendHost.sendMessageToBackend(message); + Host.InspectorFrontendHost.sendMessageToBackend(message); } } @@ -320,7 +320,7 @@ SDK.initMainConnection = async function(createMainTarget, websocketConnectionLost) { Protocol.Connection.setFactory(SDK._createMainConnection.bind(null, websocketConnectionLost)); await createMainTarget(); - InspectorFrontendHost.connectionReady(); + Host.InspectorFrontendHost.connectionReady(); return Promise.resolve(); }; @@ -334,7 +334,7 @@ if (wsParam || wssParam) { const ws = wsParam ? `ws://${wsParam}` : `wss://${wssParam}`; return new SDK.WebSocketConnection(ws, websocketConnectionLost); - } else if (InspectorFrontendHost.isHostedMode()) { + } else if (Host.InspectorFrontendHost.isHostedMode()) { return new SDK.StubConnection(); }
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js b/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js index 015701a4..3da5220 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/DOMModel.js
@@ -595,7 +595,7 @@ async copyNode() { const text = await this._agent.getOuterHTML(this.id); if (text !== null) { - InspectorFrontendHost.copyText(text); + Host.InspectorFrontendHost.copyText(text); } return text; }
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js b/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js index fec74fb..56b983c 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/RuntimeModel.js
@@ -375,11 +375,11 @@ */ _copyRequested(object) { if (!object.objectId) { - InspectorFrontendHost.copyText(object.unserializableValue() || /** @type {string} */ (object.value)); + Host.InspectorFrontendHost.copyText(object.unserializableValue() || /** @type {string} */ (object.value)); return; } object.callFunctionJSON(toStringForClipboard, [{value: object.subtype}]) - .then(InspectorFrontendHost.copyText.bind(InspectorFrontendHost)); + .then(Host.InspectorFrontendHost.copyText.bind(Host.InspectorFrontendHost)); /** * @param {string} subtype
diff --git a/third_party/blink/renderer/devtools/front_end/sdk/Target.js b/third_party/blink/renderer/devtools/front_end/sdk/Target.js index 61c186ca..5917c44 100644 --- a/third_party/blink/renderer/devtools/front_end/sdk/Target.js +++ b/third_party/blink/renderer/devtools/front_end/sdk/Target.js
@@ -196,7 +196,7 @@ const parsedURL = inspectedURL.asParsedURL(); this._inspectedURLName = parsedURL ? parsedURL.lastPathComponentWithFragment() : '#' + this._id; if (!this.parentTarget()) { - InspectorFrontendHost.inspectedURLChanged(inspectedURL || ''); + Host.InspectorFrontendHost.inspectedURLChanged(inspectedURL || ''); } this._targetManager.dispatchEventToListeners(SDK.TargetManager.Events.InspectedURLChanged, this); if (!this._name) {
diff --git a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js index 859056e..81aae1bc 100644 --- a/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js +++ b/third_party/blink/renderer/devtools/front_end/security/SecurityPanel.js
@@ -48,7 +48,7 @@ e.consume(); const names = await SDK.multitargetNetworkManager.getCertificate(origin); if (names.length > 0) { - InspectorFrontendHost.showCertificateViewer(names); + Host.InspectorFrontendHost.showCertificateViewer(names); } }, 'origin-button'); UI.ARIAUtils.markAsMenuButton(certificateButton); @@ -63,7 +63,7 @@ static createCertificateViewerButtonForCert(text, names) { const certificateButton = UI.createTextButton(text, e => { e.consume(); - InspectorFrontendHost.showCertificateViewer(names); + Host.InspectorFrontendHost.showCertificateViewer(names); }, 'security-certificate-button'); UI.ARIAUtils.markAsMenuButton(certificateButton); return certificateButton;
diff --git a/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js b/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js index 13c505f..0e9db479 100644 --- a/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js +++ b/third_party/blink/renderer/devtools/front_end/settings/SettingsScreen.js
@@ -300,7 +300,7 @@ Settings.SettingsScreen._showSettingsScreen(); return true; case 'settings.documentation': - InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/'); + Host.InspectorFrontendHost.openInNewTab('https://developers.google.com/web/tools/chrome-devtools/'); return true; case 'settings.shortcuts': Settings.SettingsScreen._showSettingsScreen(Common.UIString('Shortcuts')); @@ -339,7 +339,7 @@ return; } if (extension.descriptor()['settingName'] === setting.name) { - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); Settings.SettingsScreen._showSettingsScreen(); success = true; } @@ -351,7 +351,7 @@ function revealSettingUI(extension) { const settings = extension.descriptor()['settings']; if (settings && settings.indexOf(setting.name) !== -1) { - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); Settings.SettingsScreen._showSettingsScreen(); success = true; } @@ -367,7 +367,7 @@ } const settings = extension.descriptor()['settings']; if (settings && settings.indexOf(setting.name) !== -1) { - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); Settings.SettingsScreen._showSettingsScreen(extension.descriptor()['id']); success = true; }
diff --git a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js index 8815c0f..d49d57f0 100644 --- a/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js +++ b/third_party/blink/renderer/devtools/front_end/source_frame/ImageView.js
@@ -130,11 +130,11 @@ } _copyImageAsDataURL() { - InspectorFrontendHost.copyText(this._imagePreviewElement.src); + Host.InspectorFrontendHost.copyText(this._imagePreviewElement.src); } _copyImageURL() { - InspectorFrontendHost.copyText(this._url); + Host.InspectorFrontendHost.copyText(this._url); } _saveImage() { @@ -145,7 +145,7 @@ } _openInNewTab() { - InspectorFrontendHost.openInNewTab(this._url); + Host.InspectorFrontendHost.openInNewTab(this._url); } /**
diff --git a/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js b/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js index f0ae060..e30fa88 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js +++ b/third_party/blink/renderer/devtools/front_end/sources/CallStackSidebarPane.js
@@ -388,7 +388,7 @@ } text.push(itemText); } - InspectorFrontendHost.copyText(text.join('\n')); + Host.InspectorFrontendHost.copyText(text.join('\n')); } };
diff --git a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js index 763d1d63..b277a0d 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js +++ b/third_party/blink/renderer/devtools/front_end/sources/DebuggerPlugin.js
@@ -502,7 +502,7 @@ returnByValue: false, generatePreview: false }); - if (!result.object) { + if (!result.object || (result.object.type === 'object' && result.object.subtype === 'error')) { return false; } objectPopoverHelper = await ObjectUI.ObjectPopoverHelper.buildObjectPopover(result.object, popover);
diff --git a/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js b/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js index d6a6e31c6a..7fe0d35 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js +++ b/third_party/blink/renderer/devtools/front_end/sources/NavigatorView.js
@@ -808,7 +808,7 @@ const folderPath = Common.ParsedURL.urlToPlatformPath( Persistence.FileSystemWorkspaceBinding.completeURL(project, path), Host.isWin()); contextMenu.revealSection().appendItem( - Common.UIString('Open folder'), () => InspectorFrontendHost.showItemInFolder(folderPath)); + Common.UIString('Open folder'), () => Host.InspectorFrontendHost.showItemInFolder(folderPath)); if (project.canCreateFile()) { contextMenu.defaultSection().appendItem( Common.UIString('New file'), this._handleContextMenuCreate.bind(this, project, path));
diff --git a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js index 8df7fdd..40d1e82 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js +++ b/third_party/blink/renderer/devtools/front_end/sources/SourcesPanel.js
@@ -321,7 +321,7 @@ this._toggleDebuggerSidebarButton.setEnabled(false); this._revealDebuggerSidebar(); window.focus(); - InspectorFrontendHost.bringToFront(); + Host.InspectorFrontendHost.bringToFront(); } /** @@ -1044,7 +1044,7 @@ if (!entry.isDirectory) { return; } - InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem); + Host.InspectorFrontendHost.upgradeDraggedFileSystemPermissions(entry.filesystem); } };
diff --git a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js index 2681def8..565b60bb 100644 --- a/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js +++ b/third_party/blink/renderer/devtools/front_end/sources/WatchExpressionsSidebarPane.js
@@ -475,7 +475,7 @@ } _copyValueButtonClicked() { - InspectorFrontendHost.copyText(this._valueElement.textContent); + Host.InspectorFrontendHost.copyText(this._valueElement.textContent); } };
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js index 73d3c05..9da39d17 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js +++ b/third_party/blink/renderer/devtools/front_end/ui/ContextMenu.js
@@ -379,7 +379,8 @@ } static initialize() { - InspectorFrontendHost.events.addEventListener(Host.InspectorFrontendHostAPI.Events.SetUseSoftMenu, setUseSoftMenu); + Host.InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHostAPI.Events.SetUseSoftMenu, setUseSoftMenu); /** * @param {!Common.Event} event */ @@ -449,19 +450,19 @@ _innerShow() { const menuObject = this._buildMenuDescriptors(); - if (this._useSoftMenu || UI.ContextMenu._useSoftMenu || InspectorFrontendHost.isHostedMode()) { + if (this._useSoftMenu || UI.ContextMenu._useSoftMenu || Host.InspectorFrontendHost.isHostedMode()) { this._softMenu = new UI.SoftContextMenu(menuObject, this._itemSelected.bind(this)); this._softMenu.show(this._event.target.ownerDocument, new AnchorBox(this._x, this._y, 0, 0)); } else { - InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument); + Host.InspectorFrontendHost.showContextMenuAtPoint(this._x, this._y, menuObject, this._event.target.ownerDocument); /** * @this {UI.ContextMenu} */ function listenToEvents() { - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this); } @@ -506,9 +507,9 @@ } _menuCleared() { - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.ContextMenuCleared, this._menuCleared, this); - InspectorFrontendHost.events.removeEventListener( + Host.InspectorFrontendHost.events.removeEventListener( Host.InspectorFrontendHostAPI.Events.ContextMenuItemSelected, this._onItemSelected, this); }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js b/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js index 2313301..ff8c2d67 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js +++ b/third_party/blink/renderer/devtools/front_end/ui/ForwardedInputEventHandler.js
@@ -6,7 +6,7 @@ */ UI.ForwardedInputEventHandler = class { constructor() { - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.KeyEventUnhandled, this._onKeyEventUnhandled, this); }
diff --git a/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js b/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js index 8b2af91..9c334b6 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js +++ b/third_party/blink/renderer/devtools/front_end/ui/InspectorView.js
@@ -77,7 +77,7 @@ // Create main area tabbed pane. this._tabbedLocation = UI.viewManager.createTabbedLocation( - InspectorFrontendHost.bringToFront.bind(InspectorFrontendHost), 'panel', true, true, + Host.InspectorFrontendHost.bringToFront.bind(Host.InspectorFrontendHost), 'panel', true, true, Root.Runtime.queryParam('panel')); this._tabbedPane = this._tabbedLocation.tabbedPane(); @@ -94,7 +94,8 @@ this._drawerSplitWidget.setMainWidget(this._tabbedPane); this._keyDownBound = this._keyDown.bind(this); - InspectorFrontendHost.events.addEventListener(Host.InspectorFrontendHostAPI.Events.ShowPanel, showPanel.bind(this)); + Host.InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHostAPI.Events.ShowPanel, showPanel.bind(this)); /** * @this {UI.InspectorView}
diff --git a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js index a0ec7038..eb245a8 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js +++ b/third_party/blink/renderer/devtools/front_end/ui/UIUtils.js
@@ -2179,11 +2179,11 @@ const copyButton = fragment.createChild('span', 'expandable-inline-button'); copyButton.setAttribute('data-text', ls`Copy`); copyButton.addEventListener('click', () => { - InspectorFrontendHost.copyText(text); + Host.InspectorFrontendHost.copyText(text); }); copyButton.addEventListener('keydown', event => { if (event.key === 'Enter' || event.key === ' ') { - InspectorFrontendHost.copyText(text); + Host.InspectorFrontendHost.copyText(text); } }); UI.ARIAUtils.markAsButton(copyButton);
diff --git a/third_party/blink/renderer/devtools/front_end/ui/XLink.js b/third_party/blink/renderer/devtools/front_end/ui/XLink.js index 6b3e001..c2dc152 100644 --- a/third_party/blink/renderer/devtools/front_end/ui/XLink.js +++ b/third_party/blink/renderer/devtools/front_end/ui/XLink.js
@@ -40,12 +40,12 @@ this._onClick = event => { event.consume(true); - InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href)); + Host.InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href)); }; this._onKeyDown = event => { if (isEnterOrSpaceKey(event)) { event.consume(true); - InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href)); + Host.InspectorFrontendHost.openInNewTab(/** @type {string} */ (this._href)); } }; } @@ -122,9 +122,9 @@ return; } contextMenu.revealSection().appendItem( - UI.openLinkExternallyLabel(), () => InspectorFrontendHost.openInNewTab(targetNode._href)); + UI.openLinkExternallyLabel(), () => Host.InspectorFrontendHost.openInNewTab(targetNode._href)); contextMenu.revealSection().appendItem( - UI.copyLinkAddressLabel(), () => InspectorFrontendHost.copyText(targetNode._href)); + UI.copyLinkAddressLabel(), () => Host.InspectorFrontendHost.copyText(targetNode._href)); } };
diff --git a/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js b/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js index 7155113..1c69850 100644 --- a/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js +++ b/third_party/blink/renderer/devtools/front_end/workspace/FileManager.js
@@ -36,10 +36,11 @@ super(); /** @type {!Map<string, function(?{fileSystemPath: (string|undefined)})>} */ this._saveCallbacks = new Map(); - InspectorFrontendHost.events.addEventListener(Host.InspectorFrontendHostAPI.Events.SavedURL, this._savedURL, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHostAPI.Events.SavedURL, this._savedURL, this); + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.CanceledSaveURL, this._canceledSavedURL, this); - InspectorFrontendHost.events.addEventListener( + Host.InspectorFrontendHost.events.addEventListener( Host.InspectorFrontendHostAPI.Events.AppendedToURL, this._appendedToURL, this); } @@ -52,7 +53,7 @@ save(url, content, forceSaveAs) { // Remove this url from the saved URLs while it is being saved. const result = new Promise(resolve => this._saveCallbacks.set(url, resolve)); - InspectorFrontendHost.save(url, content, forceSaveAs); + Host.InspectorFrontendHost.save(url, content, forceSaveAs); return result; } @@ -85,14 +86,14 @@ * @param {string} content */ append(url, content) { - InspectorFrontendHost.append(url, content); + Host.InspectorFrontendHost.append(url, content); } /** * @param {string} url */ close(url) { - InspectorFrontendHost.close(url); + Host.InspectorFrontendHost.close(url); } /**
diff --git a/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts b/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts index 0746b0f..3b1406c07c 100644 --- a/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts +++ b/third_party/blink/renderer/devtools/scripts/migration/refactor-to-es-module.ts
@@ -107,14 +107,20 @@ { const legacyNamespaceName = b.memberExpression(b.identifier('self'), b.identifier(refactoringNamespace), false); const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([])); - ast.program.body.push(b.expressionStatement.from({expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), comments: [b.commentBlock('Legacy exported object', true, false)]})); + ast.program.body.push(b.expressionStatement.from({ + expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), + comments: [b.commentBlock(' Legacy exported object ', true, false)] + })); } // UI = UI || {}; const legacyNamespaceName = b.identifier(refactoringNamespace) { const legacyNamespaceOr = b.logicalExpression("||", legacyNamespaceName, b.objectExpression([])); - ast.program.body.push(b.expressionStatement.from({expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), comments: [b.commentBlock('Legacy exported object', true, false)]})); + ast.program.body.push(b.expressionStatement.from({ + expression: b.assignmentExpression('=', legacyNamespaceName, legacyNamespaceOr), + comments: [b.commentBlock(' Legacy exported object ', true, false)] + })); } // UI.ARIAUtils = ARIAUtils;
diff --git a/third_party/blink/renderer/modules/filesystem/BUILD.gn b/third_party/blink/renderer/modules/filesystem/BUILD.gn index 23bd32d4..2e2f3d0 100644 --- a/third_party/blink/renderer/modules/filesystem/BUILD.gn +++ b/third_party/blink/renderer/modules/filesystem/BUILD.gn
@@ -45,7 +45,6 @@ "file_entry_sync.h", "file_system_callbacks.cc", "file_system_callbacks.h", - "file_system_client.h", "file_system_dispatcher.cc", "file_system_dispatcher.h", "file_writer.cc", @@ -58,8 +57,6 @@ "html_input_element_file_system.h", "local_file_system.cc", "local_file_system.h", - "local_file_system_client.cc", - "local_file_system_client.h", "metadata.h", "sync_callback_helper.h", "worker_global_scope_file_system.cc",
diff --git a/third_party/blink/renderer/modules/filesystem/file_system_client.h b/third_party/blink/renderer/modules/filesystem/file_system_client.h deleted file mode 100644 index 7288beb2..0000000 --- a/third_party/blink/renderer/modules/filesystem/file_system_client.h +++ /dev/null
@@ -1,73 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_ - -#include <memory> - -#include "base/callback.h" -#include "base/macros.h" -#include "third_party/blink/public/mojom/filesystem/file_system.mojom-blink.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" - -namespace blink { - -class ExecutionContext; -class LocalFrame; -class WorkerClients; - -class FileSystemClient { - USING_FAST_MALLOC(FileSystemClient); - - public: - FileSystemClient() = default; - virtual ~FileSystemClient() = default; - - virtual bool RequestFileSystemAccessSync(ExecutionContext*) = 0; - virtual void RequestFileSystemAccessAsync(ExecutionContext*, - base::OnceCallback<void(bool)>) = 0; - - private: - DISALLOW_COPY_AND_ASSIGN(FileSystemClient); -}; - -MODULES_EXPORT void ProvideLocalFileSystemTo(LocalFrame&, - std::unique_ptr<FileSystemClient>); - -MODULES_EXPORT void ProvideLocalFileSystemToWorker( - WorkerClients*, - std::unique_ptr<FileSystemClient>); - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_FILE_SYSTEM_CLIENT_H_
diff --git a/third_party/blink/renderer/modules/filesystem/local_file_system.cc b/third_party/blink/renderer/modules/filesystem/local_file_system.cc index b0cd5d9b..021c6a7b 100644 --- a/third_party/blink/renderer/modules/filesystem/local_file_system.cc +++ b/third_party/blink/renderer/modules/filesystem/local_file_system.cc
@@ -47,7 +47,6 @@ #include "third_party/blink/renderer/core/workers/worker_global_scope.h" #include "third_party/blink/renderer/modules/filesystem/dom_file_system.h" #include "third_party/blink/renderer/modules/filesystem/file_system_callbacks.h" -#include "third_party/blink/renderer/modules/filesystem/file_system_client.h" #include "third_party/blink/renderer/modules/filesystem/file_system_dispatcher.h" #include "third_party/blink/renderer/platform/wtf/functional.h" #include "third_party/blink/renderer/platform/wtf/std_lib_extras.h" @@ -110,15 +109,26 @@ void LocalFileSystem::RequestFileSystemAccessInternal( ExecutionContext* context, base::OnceCallback<void(bool)> callback) { - if (!context->IsDocument()) { - if (!Client().RequestFileSystemAccessSync(context)) { - std::move(callback).Run(false); - return; + if (context->IsDocument()) { + auto* client = + To<Document>(context)->GetFrame()->GetContentSettingsClient(); + if (!client) { + std::move(callback).Run(true); + } else { + client->RequestFileSystemAccessAsync(std::move(callback)); } - std::move(callback).Run(true); return; } - Client().RequestFileSystemAccessAsync(context, std::move(callback)); + if (context->IsWorkerGlobalScope()) { + auto* client = To<WorkerGlobalScope>(context)->ContentSettingsClient(); + if (!client) { + std::move(callback).Run(true); + } else { + std::move(callback).Run(client->RequestFileSystemAccessSync()); + } + return; + } + NOTREACHED(); } void LocalFileSystem::FileSystemNotAllowedInternal( @@ -167,17 +177,11 @@ } } -LocalFileSystem::LocalFileSystem(LocalFrame& frame, - std::unique_ptr<FileSystemClient> client) - : Supplement<LocalFrame>(frame), client_(std::move(client)) { - DCHECK(client_); -} +LocalFileSystem::LocalFileSystem(LocalFrame& frame) + : Supplement<LocalFrame>(frame) {} -LocalFileSystem::LocalFileSystem(WorkerClients& worker_clients, - std::unique_ptr<FileSystemClient> client) - : Supplement<WorkerClients>(worker_clients), client_(std::move(client)) { - DCHECK(client_); -} +LocalFileSystem::LocalFileSystem(WorkerClients& worker_clients) + : Supplement<WorkerClients>(worker_clients) {} void LocalFileSystem::Trace(blink::Visitor* visitor) { Supplement<LocalFrame>::Trace(visitor); @@ -202,17 +206,13 @@ return file_system; } -void ProvideLocalFileSystemTo(LocalFrame& frame, - std::unique_ptr<FileSystemClient> client) { - frame.ProvideSupplement( - MakeGarbageCollected<LocalFileSystem>(frame, std::move(client))); +void ProvideLocalFileSystemTo(LocalFrame& frame) { + frame.ProvideSupplement(MakeGarbageCollected<LocalFileSystem>(frame)); } -void ProvideLocalFileSystemToWorker(WorkerClients* worker_clients, - std::unique_ptr<FileSystemClient> client) { - Supplement<WorkerClients>::ProvideTo(*worker_clients, - MakeGarbageCollected<LocalFileSystem>( - *worker_clients, std::move(client))); +void ProvideLocalFileSystemToWorker(WorkerClients& worker_clients) { + worker_clients.ProvideSupplement( + MakeGarbageCollected<LocalFileSystem>(worker_clients)); } } // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/local_file_system.h b/third_party/blink/renderer/modules/filesystem/local_file_system.h index 1349c15a..610da55 100644 --- a/third_party/blink/renderer/modules/filesystem/local_file_system.h +++ b/third_party/blink/renderer/modules/filesystem/local_file_system.h
@@ -46,7 +46,6 @@ namespace blink { -class FileSystemClient; class ExecutionContext; class FileSystemCallbacks; class KURL; @@ -63,8 +62,8 @@ static const char kSupplementName[]; - LocalFileSystem(LocalFrame&, std::unique_ptr<FileSystemClient>); - LocalFileSystem(WorkerClients&, std::unique_ptr<FileSystemClient>); + explicit LocalFileSystem(LocalFrame&); + explicit LocalFileSystem(WorkerClients&); ~LocalFileSystem(); void ResolveURL(ExecutionContext*, @@ -77,8 +76,6 @@ std::unique_ptr<FileSystemCallbacks>, SynchronousType sync_type); - FileSystemClient& Client() const { return *client_; } - static LocalFileSystem* From(ExecutionContext&); void Trace(blink::Visitor*) override; @@ -110,11 +107,12 @@ std::unique_ptr<ResolveURICallbacks>, SynchronousType sync_type); - const std::unique_ptr<FileSystemClient> client_; - DISALLOW_COPY_AND_ASSIGN(LocalFileSystem); }; +void ProvideLocalFileSystemTo(LocalFrame&); +void ProvideLocalFileSystemToWorker(WorkerClients&); + } // namespace blink #endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_H_
diff --git a/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc b/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc deleted file mode 100644 index 0a0c5ea..0000000 --- a/third_party/blink/renderer/modules/filesystem/local_file_system_client.cc +++ /dev/null
@@ -1,84 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#include "third_party/blink/renderer/modules/filesystem/local_file_system_client.h" - -#include <memory> -#include <utility> - -#include "base/memory/ptr_util.h" -#include "third_party/blink/public/platform/web_content_settings_client.h" -#include "third_party/blink/renderer/core/dom/document.h" -#include "third_party/blink/renderer/core/frame/local_frame.h" -#include "third_party/blink/renderer/core/workers/worker_global_scope.h" -#include "third_party/blink/renderer/platform/weborigin/security_origin.h" -#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" - -namespace blink { - -LocalFileSystemClient::~LocalFileSystemClient() = default; - -bool LocalFileSystemClient::RequestFileSystemAccessSync( - ExecutionContext* context) { - DCHECK(context); - if (IsA<Document>(context)) { - // TODO(dcheng): Why is this NOTREACHED and handled? - NOTREACHED(); - return false; - } - - WebContentSettingsClient* content_settings_client = - To<WorkerGlobalScope>(context)->ContentSettingsClient(); - if (!content_settings_client) - return true; - return content_settings_client->RequestFileSystemAccessSync(); -} - -void LocalFileSystemClient::RequestFileSystemAccessAsync( - ExecutionContext* context, - base::OnceCallback<void(bool)> callback) { - DCHECK(context); - auto* document = DynamicTo<Document>(context); - if (!document) { - // TODO(dcheng): Why is this NOTREACHED and handled? - NOTREACHED(); - return; - } - - if (auto* client = document->GetFrame()->GetContentSettingsClient()) { - client->RequestFileSystemAccessAsync(std::move(callback)); - } else { - std::move(callback).Run(true); - } -} - -LocalFileSystemClient::LocalFileSystemClient() = default; - -} // namespace blink
diff --git a/third_party/blink/renderer/modules/filesystem/local_file_system_client.h b/third_party/blink/renderer/modules/filesystem/local_file_system_client.h deleted file mode 100644 index a601dc0..0000000 --- a/third_party/blink/renderer/modules/filesystem/local_file_system_client.h +++ /dev/null
@@ -1,54 +0,0 @@ -/* - * Copyright (C) 2013 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. - */ - -#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_ -#define THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_ - -#include <memory> -#include "base/callback.h" -#include "third_party/blink/renderer/modules/filesystem/file_system_client.h" -#include "third_party/blink/renderer/modules/modules_export.h" -#include "third_party/blink/renderer/platform/wtf/forward.h" - -namespace blink { - -class LocalFileSystemClient final : public FileSystemClient { - public: - LocalFileSystemClient(); - ~LocalFileSystemClient() override; - - bool RequestFileSystemAccessSync(ExecutionContext*) override; - void RequestFileSystemAccessAsync(ExecutionContext*, - base::OnceCallback<void(bool)>) override; -}; - -} // namespace blink - -#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_FILESYSTEM_LOCAL_FILE_SYSTEM_CLIENT_H_
diff --git a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc index 69e9535..bb6aa0a 100644 --- a/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc +++ b/third_party/blink/renderer/modules/mediarecorder/video_track_recorder.cc
@@ -263,11 +263,9 @@ frame = media::WrapAsI420VideoFrame(video_frame); } else { frame = media::VideoFrame::WrapVideoFrame( - *video_frame, video_frame->format(), video_frame->visible_rect(), + video_frame, video_frame->format(), video_frame->visible_rect(), video_frame->natural_size()); } - frame->AddDestructionObserver(ConvertToBaseOnceCallback(CrossThreadBindOnce( - [](scoped_refptr<VideoFrame> video_frame) {}, std::move(video_frame)))); } frame->AddDestructionObserver(media::BindToCurrentLoop( WTF::Bind(&VideoTrackRecorder::Counter::DecreaseCount,
diff --git a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc index 8508564ed..676dacd7 100644 --- a/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc +++ b/third_party/blink/renderer/modules/mediastream/media_stream_video_track.cc
@@ -35,10 +35,6 @@ // |callback| will be deleted when this exits. } -// Empty method used for keeping a reference to the original media::VideoFrame. -// The reference to |frame| is kept in the closure that calls this method. -void ReleaseOriginalFrame(scoped_refptr<media::VideoFrame> frame) {} - } // namespace // MediaStreamVideoTrack::FrameDeliverer is a helper class used for registering @@ -230,13 +226,11 @@ // Wrap |black_frame_| so we get a fresh timestamp we can modify. Frames // returned from this function may still be in use. scoped_refptr<media::VideoFrame> wrapped_black_frame = - media::VideoFrame::WrapVideoFrame(*black_frame_, black_frame_->format(), + media::VideoFrame::WrapVideoFrame(black_frame_, black_frame_->format(), black_frame_->visible_rect(), black_frame_->natural_size()); if (!wrapped_black_frame) return nullptr; - wrapped_black_frame->AddDestructionObserver(ConvertToBaseOnceCallback( - CrossThreadBindOnce(&ReleaseOriginalFrame, black_frame_))); wrapped_black_frame->set_timestamp(reference_frame.timestamp()); base::TimeTicks reference_time;
diff --git a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc index 5b993e5..f0cc162 100644 --- a/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc +++ b/third_party/blink/renderer/modules/mediastream/video_track_adapter.cc
@@ -71,11 +71,6 @@ base::TimeTicks last_update_timestamp; }; -// Empty method used for keeping a reference to the original media::VideoFrame -// in VideoFrameResolutionAdapter::DeliverFrame if cropping is needed. -// The reference to |frame| is kept in the closure that calls this method. -void TrackReleaseOriginalFrame(scoped_refptr<media::VideoFrame> frame) {} - int ClampToValidDimension(int dimension) { return std::min(static_cast<int>(media::limits::kMaxDimension), std::max(0, dimension)); @@ -337,15 +332,13 @@ media::ComputeLetterboxRegion(frame->visible_rect(), desired_size); video_frame = media::VideoFrame::WrapVideoFrame( - *frame, frame->format(), region_in_frame, desired_size); + frame, frame->format(), region_in_frame, desired_size); if (!video_frame) { PostFrameDroppedToMainTaskRunner( media::VideoCaptureFrameDropReason:: kResolutionAdapterWrappingFrameForCroppingFailed); return; } - video_frame->AddDestructionObserver(ConvertToBaseOnceCallback( - CrossThreadBindOnce(&TrackReleaseOriginalFrame, frame))); DVLOG(3) << "desired size " << desired_size.ToString() << " output natural size "
diff --git a/third_party/blink/renderer/modules/modules_idl_files.gni b/third_party/blink/renderer/modules/modules_idl_files.gni index 1b94e1b..ea6a6e5 100644 --- a/third_party/blink/renderer/modules/modules_idl_files.gni +++ b/third_party/blink/renderer/modules/modules_idl_files.gni
@@ -468,6 +468,7 @@ "webgpu/gpu_compute_pass_encoder.idl", "webgpu/gpu_compute_pipeline.idl", "webgpu/gpu_device.idl", + "webgpu/gpu_device_lost_info.idl", "webgpu/gpu_fence.idl", "webgpu/gpu_out_of_memory_error.idl", "webgpu/gpu_pipeline_layout.idl", @@ -841,7 +842,7 @@ "webgpu/gpu_command_buffer_descriptor.idl", "webgpu/gpu_buffer_copy_view.idl", "webgpu/gpu_buffer_descriptor.idl", - "webgpu/gpu_color.idl", + "webgpu/gpu_color_dict.idl", "webgpu/gpu_color_state_descriptor.idl", "webgpu/gpu_command_encoder_descriptor.idl", "webgpu/gpu_compute_pipeline_descriptor.idl",
diff --git a/third_party/blink/renderer/modules/modules_initializer.cc b/third_party/blink/renderer/modules/modules_initializer.cc index 40aca4e4..5b16e25 100644 --- a/third_party/blink/renderer/modules/modules_initializer.cc +++ b/third_party/blink/renderer/modules/modules_initializer.cc
@@ -50,7 +50,7 @@ #include "third_party/blink/renderer/modules/event_target_modules_names.h" #include "third_party/blink/renderer/modules/exported/web_embedded_worker_impl.h" #include "third_party/blink/renderer/modules/filesystem/dragged_isolated_file_system_impl.h" -#include "third_party/blink/renderer/modules/filesystem/local_file_system_client.h" +#include "third_party/blink/renderer/modules/filesystem/local_file_system.h" #include "third_party/blink/renderer/modules/gamepad/navigator_gamepad.h" #include "third_party/blink/renderer/modules/image_downloader/image_downloader_impl.h" #include "third_party/blink/renderer/modules/indexed_db_names.h" @@ -182,7 +182,7 @@ ProvidePushMessagingClientTo( frame, MakeGarbageCollected<PushMessagingClient>(frame)); ProvideUserMediaTo(frame); - ProvideLocalFileSystemTo(frame, std::make_unique<LocalFileSystemClient>()); + ProvideLocalFileSystemTo(frame); ScreenOrientationControllerImpl::ProvideTo(frame); if (RuntimeEnabledFeatures::PresentationEnabled()) @@ -200,8 +200,7 @@ void ModulesInitializer::ProvideLocalFileSystemToWorker( WorkerClients& worker_clients) const { - ::blink::ProvideLocalFileSystemToWorker( - &worker_clients, std::make_unique<LocalFileSystemClient>()); + ::blink::ProvideLocalFileSystemToWorker(worker_clients); } MediaControls* ModulesInitializer::CreateMediaControls(
diff --git a/third_party/blink/renderer/modules/webgpu/BUILD.gn b/third_party/blink/renderer/modules/webgpu/BUILD.gn index 0837d1e3..ef46d40 100644 --- a/third_party/blink/renderer/modules/webgpu/BUILD.gn +++ b/third_party/blink/renderer/modules/webgpu/BUILD.gn
@@ -35,6 +35,8 @@ "gpu_compute_pipeline.h", "gpu_device.cc", "gpu_device.h", + "gpu_device_lost_info.cc", + "gpu_device_lost_info.h", "gpu_fence.cc", "gpu_fence.h", "gpu_out_of_memory_error.cc",
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc b/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc index 66b9acf..95d65905 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc +++ b/third_party/blink/renderer/modules/webgpu/dawn_conversions.cc
@@ -6,7 +6,7 @@ #include <dawn/dawn.h> -#include "third_party/blink/renderer/modules/webgpu/gpu_color.h" +#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h" #include "third_party/blink/renderer/modules/webgpu/gpu_extent_3d.h" #include "third_party/blink/renderer/modules/webgpu/gpu_origin_3d.h" #include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_stage_descriptor.h" @@ -702,7 +702,19 @@ return DAWN_ERROR_FILTER_FORCE32; } -DawnColor AsDawnType(const GPUColor* webgpu_color) { +DawnColor AsDawnColor(const Vector<double>& webgpu_color) { + DCHECK_EQ(webgpu_color.size(), 4UL); + + DawnColor dawn_color = {}; + dawn_color.r = webgpu_color[0]; + dawn_color.g = webgpu_color[1]; + dawn_color.b = webgpu_color[2]; + dawn_color.a = webgpu_color[3]; + + return dawn_color; +} + +DawnColor AsDawnType(const GPUColorDict* webgpu_color) { DCHECK(webgpu_color); DawnColor dawn_color = {}; @@ -714,6 +726,19 @@ return dawn_color; } +DawnColor AsDawnType(const DoubleSequenceOrGPUColorDict* webgpu_color) { + DCHECK(webgpu_color); + + if (webgpu_color->IsDoubleSequence()) { + return AsDawnColor(webgpu_color->GetAsDoubleSequence()); + } else if (webgpu_color->IsGPUColorDict()) { + return AsDawnType(webgpu_color->GetAsGPUColorDict()); + } + NOTREACHED(); + DawnColor dawn_color = {}; + return dawn_color; +} + DawnExtent3D AsDawnType(const GPUExtent3D* webgpu_extent) { DCHECK(webgpu_extent);
diff --git a/third_party/blink/renderer/modules/webgpu/dawn_conversions.h b/third_party/blink/renderer/modules/webgpu/dawn_conversions.h index b86fa80..af37c95 100644 --- a/third_party/blink/renderer/modules/webgpu/dawn_conversions.h +++ b/third_party/blink/renderer/modules/webgpu/dawn_conversions.h
@@ -19,7 +19,8 @@ namespace blink { -class GPUColor; +class DoubleSequenceOrGPUColorDict; +class GPUColorDict; class GPUExtent3D; class GPUOrigin3D; class GPUPipelineStageDescriptor; @@ -37,7 +38,9 @@ // These conversions are used multiple times and are declared here. Conversions // used only once, for example for object construction, are defined // individually. -DawnColor AsDawnType(const GPUColor*); +DawnColor AsDawnColor(const Vector<double>&); +DawnColor AsDawnType(const GPUColorDict*); +DawnColor AsDawnType(const DoubleSequenceOrGPUColorDict*); DawnExtent3D AsDawnType(const GPUExtent3D*); DawnOrigin3D AsDawnType(const GPUOrigin3D*);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu.idl b/third_party/blink/renderer/modules/webgpu/gpu.idl index b4fd120..affb266 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu.idl
@@ -5,6 +5,7 @@ // https://gpuweb.github.io/gpuweb/ typedef unsigned long long GPUBufferSize; +typedef (sequence<double> or GPUColorDict) GPUColor; [ RuntimeEnabled=WebGPU
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color.idl b/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl similarity index 63% copy from third_party/blink/renderer/modules/webgpu/gpu_color.idl copy to third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl index 3055ed71..1759ca4 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_color.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_color_dict.idl
@@ -4,9 +4,9 @@ // https://gpuweb.github.io/gpuweb/ -dictionary GPUColor { - required float r; - required float g; - required float b; - required float a; +dictionary GPUColorDict { + required double r; + required double g; + required double b; + required double a; };
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc index c9306b0..cd374b0 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.cc
@@ -4,6 +4,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h" +#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h" #include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h" #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h" #include "third_party/blink/renderer/modules/webgpu/gpu_buffer_copy_view.h" @@ -39,8 +40,14 @@ const WTF::String& gpuLoadOp = webgpu_desc->loadValue().GetAsGPULoadOp(); dawn_desc.loadOp = AsDawnEnum<DawnLoadOp>(gpuLoadOp); - } else if (webgpu_desc->loadValue().IsGPUColor()) { - GPUColor* gpuColor = webgpu_desc->loadValue().GetAsGPUColor(); + } else if (webgpu_desc->loadValue().IsDoubleSequence()) { + const Vector<double>& gpuColor = + webgpu_desc->loadValue().GetAsDoubleSequence(); + dawn_desc.loadOp = DAWN_LOAD_OP_CLEAR; + dawn_desc.clearColor = AsDawnColor(gpuColor); + + } else if (webgpu_desc->loadValue().IsGPUColorDict()) { + const GPUColorDict* gpuColor = webgpu_desc->loadValue().GetAsGPUColorDict(); dawn_desc.loadOp = DAWN_LOAD_OP_CLEAR; dawn_desc.clearColor = AsDawnType(gpuColor); @@ -171,12 +178,27 @@ } GPURenderPassEncoder* GPUCommandEncoder::beginRenderPass( - const GPURenderPassDescriptor* descriptor) { + const GPURenderPassDescriptor* descriptor, + ExceptionState& exception_state) { DCHECK(descriptor); uint32_t color_attachment_count = static_cast<uint32_t>(descriptor->colorAttachments().size()); + // Check loadValue color is correctly formatted before further processing. + for (wtf_size_t i = 0; i < color_attachment_count; ++i) { + const GPURenderPassColorAttachmentDescriptor* color_attachment = + descriptor->colorAttachments()[i]; + const GPULoadOpOrDoubleSequenceOrGPUColorDict load_value = + color_attachment->loadValue(); + + if (load_value.IsDoubleSequence() && + load_value.GetAsDoubleSequence().size() != 4) { + exception_state.ThrowRangeError("loadValue color size must be 4"); + return nullptr; + } + } + DawnRenderPassDescriptor dawn_desc = {}; dawn_desc.colorAttachmentCount = color_attachment_count; dawn_desc.colorAttachments = nullptr;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h index 486f7e68..8b83c2b 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h
@@ -6,6 +6,7 @@ #define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_COMMAND_ENCODER_H_ #include "third_party/blink/renderer/modules/webgpu/dawn_object.h" +#include "third_party/blink/renderer/platform/bindings/exception_state.h" namespace blink { @@ -34,7 +35,8 @@ // gpu_command_encoder.idl GPURenderPassEncoder* beginRenderPass( - const GPURenderPassDescriptor* descriptor); + const GPURenderPassDescriptor* descriptor, + ExceptionState& exception_state); GPUComputePassEncoder* beginComputePass( const GPUComputePassDescriptor* descriptor); void copyBufferToBuffer(GPUBuffer* src,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl index f5a048c..e3d5970 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_command_encoder.idl
@@ -7,7 +7,7 @@ [ RuntimeEnabled=WebGPU ] interface GPUCommandEncoder { - GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); + [RaisesException] GPURenderPassEncoder beginRenderPass(GPURenderPassDescriptor descriptor); GPUComputePassEncoder beginComputePass(optional GPUComputePassDescriptor descriptor); void copyBufferToBuffer(
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.cc b/third_party/blink/renderer/modules/webgpu/gpu_device.cc index f8d3a993..2c506bc 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.cc
@@ -18,6 +18,7 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_command_encoder.h" #include "third_party/blink/renderer/modules/webgpu/gpu_compute_pipeline.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device_descriptor.h" +#include "third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h" #include "third_party/blink/renderer/modules/webgpu/gpu_pipeline_layout.h" #include "third_party/blink/renderer/modules/webgpu/gpu_queue.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.h" @@ -50,6 +51,9 @@ dawn_control_client->GetInterface()->GetDefaultDevice()), adapter_(adapter), queue_(GPUQueue::Create(this, GetProcs().deviceCreateQueue(GetHandle()))), + lost_property_(MakeGarbageCollected<LostProperty>(execution_context, + this, + LostProperty::kLost)), error_callback_( BindRepeatingDawnCallback(&GPUDevice::OnUncapturedError, WrapWeakPersistent(this), @@ -78,6 +82,13 @@ execution_context->AddConsoleMessage(console_message); } + // TODO: Use device lost callback instead of uncaptured error callback. + if (errorType == DAWN_ERROR_TYPE_DEVICE_LOST && + lost_property_->GetState() == ScriptPromisePropertyBase::kPending) { + GPUDeviceLostInfo* device_lost_info = GPUDeviceLostInfo::Create(message); + lost_property_->Resolve(device_lost_info); + } + GPUUncapturedErrorEventInit* init = GPUUncapturedErrorEventInit::Create(); if (errorType == DAWN_ERROR_TYPE_VALIDATION) { GPUValidationError* error = GPUValidationError::Create(message); @@ -99,6 +110,10 @@ return adapter_; } +ScriptPromise GPUDevice::lost(ScriptState* script_state) { + return lost_property_->Promise(script_state->World()); +} + GPUBuffer* GPUDevice::createBuffer(const GPUBufferDescriptor* descriptor) { return GPUBuffer::Create(this, descriptor); } @@ -276,6 +291,7 @@ void GPUDevice::Trace(blink::Visitor* visitor) { visitor->Trace(adapter_); visitor->Trace(queue_); + visitor->Trace(lost_property_); ContextClient::Trace(visitor); EventTargetWithInlineData::Trace(visitor); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.h b/third_party/blink/renderer/modules/webgpu/gpu_device.h index 48836ea6..7a6fbb1f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.h
@@ -7,6 +7,7 @@ #include "base/memory/scoped_refptr.h" #include "third_party/blink/renderer/bindings/core/v8/script_promise.h" +#include "third_party/blink/renderer/bindings/core/v8/script_promise_property.h" #include "third_party/blink/renderer/core/dom/events/event_target.h" #include "third_party/blink/renderer/core/execution_context/execution_context.h" #include "third_party/blink/renderer/modules/webgpu/dawn_callback.h" @@ -28,6 +29,7 @@ class GPUComputePipeline; class GPUComputePipelineDescriptor; class GPUDeviceDescriptor; +class GPUDeviceLostInfo; class GPUPipelineLayout; class GPUPipelineLayoutDescriptor; class GPUQueue; @@ -66,6 +68,7 @@ // gpu_device.idl GPUAdapter* adapter() const; + ScriptPromise lost(ScriptState* script_state); GPUBuffer* createBuffer(const GPUBufferDescriptor* descriptor); HeapVector<ScriptValue> createBufferMapped( @@ -110,6 +113,10 @@ ExecutionContext* GetExecutionContext() const override; private: + using LostProperty = ScriptPromiseProperty<Member<GPUDevice>, + Member<GPUDeviceLostInfo>, + ToV8UndefinedGenerator>; + void OnUncapturedError(ExecutionContext* execution_context, DawnErrorType errorType, const char* message); @@ -120,6 +127,7 @@ Member<GPUAdapter> adapter_; Member<GPUQueue> queue_; + Member<LostProperty> lost_property_; std::unique_ptr< DawnCallback<base::RepeatingCallback<void(DawnErrorType, const char*)>>> error_callback_;
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device.idl b/third_party/blink/renderer/modules/webgpu/gpu_device.idl index f5c58eb2..608877d 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_device.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_device.idl
@@ -8,6 +8,7 @@ RuntimeEnabled=WebGPU ] interface GPUDevice : EventTarget { readonly attribute GPUAdapter adapter; + [CallWith=ScriptState] readonly attribute Promise<GPUDeviceLostInfo> lost; GPUBuffer createBuffer(GPUBufferDescriptor descriptor); [CallWith=ScriptState, RaisesException] GPUMappedBuffer createBufferMapped(GPUBufferDescriptor descriptor);
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc new file mode 100644 index 0000000..3a6f102 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.cc
@@ -0,0 +1,22 @@ +// Copyright 2019 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/modules/webgpu/gpu_device_lost_info.h" + +namespace blink { + +// static +GPUDeviceLostInfo* GPUDeviceLostInfo::Create(const String& message) { + return MakeGarbageCollected<GPUDeviceLostInfo>(message); +} + +GPUDeviceLostInfo::GPUDeviceLostInfo(const String& message) { + message_ = message; +} + +const String& GPUDeviceLostInfo::message() const { + return message_; +} + +} // namespace blink
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h new file mode 100644 index 0000000..db6b214 --- /dev/null +++ b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.h
@@ -0,0 +1,31 @@ +// Copyright 2019 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_MODULES_WEBGPU_GPU_DEVICE_LOST_INFO_H_ +#define THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_LOST_INFO_H_ + +#include "third_party/blink/renderer/platform/bindings/script_wrappable.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" + +namespace blink { + +class GPUDeviceLostInfo : public ScriptWrappable { + DEFINE_WRAPPERTYPEINFO(); + + public: + static GPUDeviceLostInfo* Create(const String& message); + GPUDeviceLostInfo(const String& message); + + // gpu_device_lost_info.idl + const String& message() const; + + private: + String message_; + + DISALLOW_COPY_AND_ASSIGN(GPUDeviceLostInfo); +}; + +} // namespace blink + +#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_WEBGPU_GPU_DEVICE_LOST_INFO_H_
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_color.idl b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl similarity index 65% rename from third_party/blink/renderer/modules/webgpu/gpu_color.idl rename to third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl index 3055ed71..44fd3a1 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_color.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_device_lost_info.idl
@@ -4,9 +4,9 @@ // https://gpuweb.github.io/gpuweb/ -dictionary GPUColor { - required float r; - required float g; - required float b; - required float a; +[ + RuntimeEnabled=WebGPU +] interface GPUDeviceLostInfo { + readonly attribute DOMString message; }; +
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc index 4dfd498..56b8c4f 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_bundle_encoder.cc
@@ -7,7 +7,6 @@ #include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h" #include "third_party/blink/renderer/modules/webgpu/gpu_bind_group.h" #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h" -#include "third_party/blink/renderer/modules/webgpu/gpu_color.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle_descriptor.h"
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc index 4378f95b..8f32e35 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.cc
@@ -4,10 +4,10 @@ #include "third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h" +#include "third_party/blink/renderer/bindings/modules/v8/double_sequence_or_gpu_color_dict.h" #include "third_party/blink/renderer/modules/webgpu/dawn_conversions.h" #include "third_party/blink/renderer/modules/webgpu/gpu_bind_group.h" #include "third_party/blink/renderer/modules/webgpu/gpu_buffer.h" -#include "third_party/blink/renderer/modules/webgpu/gpu_color.h" #include "third_party/blink/renderer/modules/webgpu/gpu_device.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_bundle.h" #include "third_party/blink/renderer/modules/webgpu/gpu_render_pipeline.h" @@ -61,8 +61,14 @@ GetProcs().renderPassEncoderSetPipeline(GetHandle(), pipeline->GetHandle()); } -void GPURenderPassEncoder::setBlendColor(GPUColor* color) { - DawnColor dawn_color = AsDawnType(color); +void GPURenderPassEncoder::setBlendColor(DoubleSequenceOrGPUColorDict& color, + ExceptionState& exception_state) { + if (color.IsDoubleSequence() && color.GetAsDoubleSequence().size() != 4) { + exception_state.ThrowRangeError("color size must be 4"); + return; + } + + DawnColor dawn_color = AsDawnType(&color); GetProcs().renderPassEncoderSetBlendColor(GetHandle(), &dawn_color); }
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h index f270ea8d..aceb574 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.h
@@ -12,7 +12,7 @@ class GPUBindGroup; class GPUBuffer; -class GPUColor; +class DoubleSequenceOrGPUColorDict; class GPURenderBundle; class GPURenderPipeline; @@ -36,7 +36,8 @@ void insertDebugMarker(String markerLabel); void setPipeline(GPURenderPipeline* pipeline); - void setBlendColor(GPUColor* color); + void setBlendColor(DoubleSequenceOrGPUColorDict& color, + ExceptionState& exception_state); void setStencilReference(uint32_t reference); void setViewport(float x, float y,
diff --git a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl index 28bff157..6409ee8 100644 --- a/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl +++ b/third_party/blink/renderer/modules/webgpu/gpu_render_pass_encoder.idl
@@ -17,7 +17,7 @@ void setPipeline(GPURenderPipeline pipeline); - void setBlendColor(GPUColor color); + [RaisesException] void setBlendColor(GPUColor color); void setStencilReference(unsigned long reference); void setViewport(float x, float y, float width, float height,
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.cc b/third_party/blink/renderer/modules/xr/xr_reference_space.cc index a9a045f..c1f1fa3 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.cc +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.cc
@@ -50,12 +50,18 @@ XRSpace* other_space, const TransformationMatrix* mojo_from_viewer) { if (type_ == Type::kTypeViewer) { - std::unique_ptr<TransformationMatrix> offsetspace_from_viewer = + std::unique_ptr<TransformationMatrix> other_offsetspace_from_viewer = other_space->SpaceFromViewerWithDefaultAndOffset(mojo_from_viewer); - if (!offsetspace_from_viewer) { + if (!other_offsetspace_from_viewer) { return nullptr; } - return MakeGarbageCollected<XRPose>(*offsetspace_from_viewer, + + auto viewer_from_offset = OriginOffsetMatrix(); + + auto other_offsetspace_from_offset = + *other_offsetspace_from_viewer * viewer_from_offset; + + return MakeGarbageCollected<XRPose>(other_offsetspace_from_offset, session()->EmulatedPosition()); } else { return XRSpace::getPose(other_space, mojo_from_viewer);
diff --git a/third_party/blink/renderer/modules/xr/xr_reference_space.h b/third_party/blink/renderer/modules/xr/xr_reference_space.h index ca80609..fec8220 100644 --- a/third_party/blink/renderer/modules/xr/xr_reference_space.h +++ b/third_party/blink/renderer/modules/xr/xr_reference_space.h
@@ -35,7 +35,7 @@ ~XRReferenceSpace() override; XRPose* getPose(XRSpace* other_space, - const TransformationMatrix* base_pose_matrix) override; + const TransformationMatrix* mojo_from_viewer) override; std::unique_ptr<TransformationMatrix> DefaultViewerPose() override; std::unique_ptr<TransformationMatrix> SpaceFromMojo( const TransformationMatrix& mojo_from_viewer) override;
diff --git a/third_party/blink/renderer/platform/bindings/script_promise_properties.h b/third_party/blink/renderer/platform/bindings/script_promise_properties.h index ef9e174..e622475 100644 --- a/third_party/blink/renderer/platform/bindings/script_promise_properties.h +++ b/third_party/blink/renderer/platform/bindings/script_promise_properties.h
@@ -11,6 +11,7 @@ P(ScriptPromise, kClosed##__VA_ARGS__) \ P(ScriptPromise, kFinished##__VA_ARGS__) \ P(ScriptPromise, kLoaded##__VA_ARGS__) \ + P(ScriptPromise, kLost##__VA_ARGS__) \ P(ScriptPromise, kReleased##__VA_ARGS__) \ P(ScriptPromise, kResponseReady##__VA_ARGS__) \ P(ScriptPromise, kUserChoice##__VA_ARGS__) \
diff --git a/third_party/blink/renderer/platform/fonts/font_description.cc b/third_party/blink/renderer/platform/fonts/font_description.cc index 6745aa4f..6f20525 100644 --- a/third_party/blink/renderer/platform/fonts/font_description.cc +++ b/third_party/blink/renderer/platform/fonts/font_description.cc
@@ -373,6 +373,42 @@ return SkFontStyle(skia_weight, skia_width, slant); } +void FontDescription::UpdateFromSkiaFontStyle(const SkFontStyle& font_style) { + SetWeight(FontSelectionValue(font_style.weight())); + + switch (font_style.width()) { + case (SkFontStyle::kUltraCondensed_Width): + SetStretch(UltraCondensedWidthValue()); + break; + case (SkFontStyle::kExtraCondensed_Width): + SetStretch(ExtraCondensedWidthValue()); + break; + case (SkFontStyle::kCondensed_Width): + SetStretch(CondensedWidthValue()); + break; + case (SkFontStyle::kSemiCondensed_Width): + SetStretch(SemiCondensedWidthValue()); + break; + case (SkFontStyle::kSemiExpanded_Width): + SetStretch(SemiExpandedWidthValue()); + break; + case (SkFontStyle::kExpanded_Width): + SetStretch(ExpandedWidthValue()); + break; + case (SkFontStyle::kExtraExpanded_Width): + SetStretch(ExtraExpandedWidthValue()); + break; + case (SkFontStyle::kUltraExpanded_Width): + SetStretch(UltraExpandedWidthValue()); + break; + } + + if (font_style.slant() == SkFontStyle::kOblique_Slant) + SetStyle(ItalicSlopeValue()); + else + SetStyle(NormalSlopeValue()); +} + int FontDescription::MinimumPrefixWidthToHyphenate() const { // If the maximum width available for the prefix before the hyphen is small, // then it is very unlikely that an hyphenation opportunity exists, so do not
diff --git a/third_party/blink/renderer/platform/fonts/font_description.h b/third_party/blink/renderer/platform/fonts/font_description.h index 35bc593..8d19bd68 100644 --- a/third_party/blink/renderer/platform/fonts/font_description.h +++ b/third_party/blink/renderer/platform/fonts/font_description.h
@@ -350,6 +350,8 @@ SkFontStyle SkiaFontStyle() const; + void UpdateFromSkiaFontStyle(const SkFontStyle& font_style); + int MinimumPrefixWidthToHyphenate() const; String ToString() const;
diff --git a/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc b/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc index c4f8f562..0f25432e 100644 --- a/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc +++ b/third_party/blink/renderer/platform/fonts/win/font_cache_skia_win.cc
@@ -336,16 +336,23 @@ // traversing the language tag stack but only processes the most important // one, so we use FallbackLocaleForCharacter() to determine what locale to // choose to achieve the best possible result. - AtomicString family(GetOutOfProcessFallbackFamily( - codepoint, font_description.GenericFamily(), - fallback_locale->LocaleForSkFontMgr(), fallback_priority, service_)); - if (family.IsEmpty()) + String fallback_family; + SkFontStyle fallback_style; + if (!GetOutOfProcessFallbackFamily( + codepoint, font_description.GenericFamily(), + fallback_locale->LocaleForSkFontMgr(), fallback_priority, service_, + &fallback_family, &fallback_style)) return nullptr; - FontFaceCreationParams create_by_family(family); - FontPlatformData* data = - GetFontPlatformData(font_description, create_by_family); + if (fallback_family.IsEmpty()) + return nullptr; + + FontFaceCreationParams create_by_family((AtomicString(fallback_family))); + FontDescription fallback_updated_font_description(font_description); + fallback_updated_font_description.UpdateFromSkiaFontStyle(fallback_style); + FontPlatformData* data = GetFontPlatformData( + fallback_updated_font_description, create_by_family); if (!data || !data->FontContainsCharacter(codepoint)) return nullptr; return FontDataFromFontPlatformData(data, kDoNotRetain);
diff --git a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc index 927f5c16..591c693d 100644 --- a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc +++ b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
@@ -548,12 +548,14 @@ return family; } -const String GetOutOfProcessFallbackFamily( +bool GetOutOfProcessFallbackFamily( UChar32 character, FontDescription::GenericFamilyType generic_family, String bcp47_language_tag, FontFallbackPriority, - const mojo::Remote<mojom::blink::DWriteFontProxy>& service) { + const mojo::Remote<mojom::blink::DWriteFontProxy>& service, + String* fallback_family, + SkFontStyle* fallback_style) { String base_family_name_approximation; switch (generic_family) { case FontDescription::kMonospaceFamily: @@ -565,11 +567,19 @@ default: base_family_name_approximation = kTimesNewRoman; } - String fallback_family_name; - service->FallbackFamilyNameForCodepoint(base_family_name_approximation, - bcp47_language_tag, character, - &fallback_family_name); - return fallback_family_name; + + mojom::blink::FallbackFamilyAndStylePtr fallback_family_and_style; + bool mojo_result = service->FallbackFamilyAndStyleForCodepoint( + base_family_name_approximation, bcp47_language_tag, character, + &fallback_family_and_style); + + SECURITY_DCHECK(fallback_family); + SECURITY_DCHECK(fallback_style); + *fallback_family = fallback_family_and_style->fallback_family_name; + *fallback_style = SkFontStyle( + fallback_family_and_style->weight, fallback_family_and_style->width, + static_cast<SkFontStyle::Slant>(fallback_family_and_style->slant)); + return mojo_result; } } // namespace blink
diff --git a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h index 2761648..e50bc818 100644 --- a/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h +++ b/third_party/blink/renderer/platform/fonts/win/font_fallback_win.h
@@ -39,6 +39,8 @@ #include "third_party/blink/renderer/platform/fonts/font_description.h" #include "third_party/blink/renderer/platform/fonts/font_fallback_priority.h" #include "third_party/blink/renderer/platform/platform_export.h" +#include "third_party/blink/renderer/platform/wtf/text/wtf_string.h" +#include "third_party/skia/include/core/SkFontStyle.h" class SkFontMgr; @@ -60,12 +62,14 @@ // that characters belong to by performing an out of process lookup and using // system fallback API based on IDWriteTextLayout. This method is only to be // used on pre Windows 8.1, as otherwise IDWriteFontFallback API is available. -PLATFORM_EXPORT const String GetOutOfProcessFallbackFamily( +PLATFORM_EXPORT bool GetOutOfProcessFallbackFamily( UChar32 character, FontDescription::GenericFamilyType, String bcp47_language_tag, FontFallbackPriority, - const mojo::Remote<mojom::blink::DWriteFontProxy>& font_proxy); + const mojo::Remote<mojom::blink::DWriteFontProxy>& font_proxy, + String* fallback_family, + SkFontStyle* fallback_style); } // namespace blink
diff --git a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc index 95788af..8fa9bf3 100644 --- a/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc +++ b/third_party/blink/renderer/platform/peerconnection/webrtc_video_track_source.cc
@@ -159,17 +159,11 @@ frame_adaptation_params.scale_to_height); // Soft-apply the new (combined) cropping and scaling. scoped_refptr<media::VideoFrame> video_frame = - media::VideoFrame::WrapVideoFrame(*frame, frame->format(), + media::VideoFrame::WrapVideoFrame(frame, frame->format(), cropped_visible_rect, adapted_size); if (!video_frame) return; - // Attach shared ownership of the wrapped |frame| to the wrapping - // |video_frame|. - video_frame->AddDestructionObserver( - base::BindOnce(base::DoNothing::Once<scoped_refptr<media::VideoFrame>>(), - std::move(frame))); - // If no scaling is needed, return a wrapped version of |frame| directly. // The soft-applied cropping will be taken into account by the remainder // of the pipeline.
diff --git a/third_party/blink/web_tests/NeverFixTests b/third_party/blink/web_tests/NeverFixTests index 00a6bff..ffe3ba3 100644 --- a/third_party/blink/web_tests/NeverFixTests +++ b/third_party/blink/web_tests/NeverFixTests
@@ -409,6 +409,7 @@ external/wpt/media-source/mediasource-invalid-codec.html [ WontFix ] # CSS Text features that are not planned to implement. +external/wpt/css/css-text/text-justify/text-justify-006.html [ WontFix ] external/wpt/css/css-text/text-transform/text-transform-full-size-kana-001.html [ WontFix ] external/wpt/css/css-text/text-transform/text-transform-full-size-kana-002.html [ WontFix ] external/wpt/css/css-text/text-transform/text-transform-full-size-kana-003.html [ WontFix ] @@ -416,6 +417,11 @@ external/wpt/css/css-text/text-transform/text-transform-full-size-kana-005.html [ WontFix ] external/wpt/css/css-text/text-transform/text-transform-full-size-kana-006.html [ WontFix ] external/wpt/css/css-text/text-transform/text-transform-full-size-kana-007.html [ WontFix ] +external/wpt/css/css-text/text-transform/text-transform-fullwidth-008.html [ WontFix ] +external/wpt/css/css-text/text-transform/text-transform-fullwidth-009.html [ WontFix ] + +# Undefined behavior without any implementations. +external/wpt/css/css-text/white-space/seg-break-transformation-019.html [ WontFix ] external/wpt/css/CSS2/linebox/inline-formatting-context-010b.xht [ WontFix ] external/wpt/css/CSS2/normal-flow/inline-block-replaced-height-008.xht [ WontFix ]
diff --git a/third_party/blink/web_tests/TestExpectations b/third_party/blink/web_tests/TestExpectations index 9addb5e..40c76f4 100644 --- a/third_party/blink/web_tests/TestExpectations +++ b/third_party/blink/web_tests/TestExpectations
@@ -1560,7 +1560,6 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before-following-content.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/insert-spanner-pseudo-before.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/relpos-becomes-static-has-abspos.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-abspos-next-to-spanner.html [ Crash Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-after-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-before-spanner.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/dynamic/remove-and-insert-block-between-spanners.html [ Failure ] @@ -1803,12 +1802,9 @@ crbug.com/591099 virtual/layout_ng_experimental/fast/multicol/widows.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/abspos-after-forced-break.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/auto-scrollbar-shrink-to-fit.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/avoid-break-inside-first-child.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/avoid-break-inside-first-child-nested.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-lines.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/become-unfragmented-with-unbreakable-blocks.html [ Crash Pass ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/block-after-float-first-child.html [ Failure ] -crbug.com/591099 virtual/layout_ng_experimental/fragmentation/break-inside-avoid-with-forced-break.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-block-float-2.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-block-float.html [ Failure ] crbug.com/591099 virtual/layout_ng_experimental/fragmentation/change-fragmentainer-height-inline-float.html [ Failure ] @@ -2426,6 +2422,10 @@ crbug.com/972992 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-001.html [ Failure ] crbug.com/972992 external/wpt/css/css-text/white-space/white-space-pre-wrap-trailing-spaces-003.html [ Failure ] +crbug.com/1008029 [ Mac ] external/wpt/css/css-text/white-space/pre-wrap-018.html [ Failure ] +crbug.com/1008029 external/wpt/css/css-text/white-space/pre-wrap-019.html [ Failure ] +crbug.com/1008029 external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html [ Failure ] +crbug.com/1008029 external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html [ Failure ] # Handling of trailing other spaces is not implemented yet. crbug.com/991413 external/wpt/css/css-text/white-space/trailing-other-space-separators-001.html [ Skip ] @@ -3228,33 +3228,11 @@ # ====== New tests from wpt-importer added here ====== crbug.com/626703 [ Win10 ] external/wpt/css/css-text/line-breaking/line-breaking-021.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/text-justify/text-justify-006.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/text-justify/text-justify-006.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/text-justify/text-justify-006.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch.html [ Timeout ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/seg-break-transformation-019.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/seg-break-transformation-019.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/seg-break-transformation-019.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-009.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-009.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-009.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-inherit_child-none_touch.html [ Timeout ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-008.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-008.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/text-transform/text-transform-fullwidth-008.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-keep-all-008.html [ Failure ] crbug.com/626703 [ Win ] external/wpt/css/css-text/word-break/word-break-keep-all-007.html [ Failure ] crbug.com/626703 [ Mac10.11 ] external/wpt/shape-detection/idlharness.https.any.sharedworker.html [ Failure Timeout ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-013.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/pre-wrap-018.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/pre-wrap-019.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/pre-wrap-019.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/pre-wrap-019.html [ Failure ] -crbug.com/626703 [ Linux ] external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html [ Failure ] -crbug.com/626703 [ Mac ] external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html [ Failure ] -crbug.com/626703 [ Win ] external/wpt/css/css-text/white-space/textarea-pre-wrap-012.html [ Failure ] crbug.com/626703 [ Win7 ] external/wpt/pointerevents/pointerevent_touch-action-pan-y-css_touch.html [ Timeout ] crbug.com/626703 [ Win10 ] external/wpt/payment-request/payment-request-hasenrolledinstrument-method.tentative.https.html [ Failure Timeout ] crbug.com/626703 [ Linux ] external/wpt/css/motion/offset-path-ray-contain-003.html [ Failure ]
diff --git a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json index f52da55..58b1147e 100644 --- a/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json +++ b/third_party/blink/web_tests/external/WPT_BASE_MANIFEST_6.json
@@ -52403,6 +52403,90 @@ {} ] ], + "css/css-grid/subgrid/repeat-auto-fill-001.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-001.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-002.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-002.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-003.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-003.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-001-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-004.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-004.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-005.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-005.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-005-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-006.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-006.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-005-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-grid/subgrid/repeat-auto-fill-007.html": [ + [ + "css/css-grid/subgrid/repeat-auto-fill-007.html", + [ + [ + "/css/css-grid/subgrid/repeat-auto-fill-007-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-grid/subgrid/subgrid-item-block-size-001.html": [ [ "css/css-grid/subgrid/subgrid-item-block-size-001.html", @@ -138268,6 +138352,18 @@ "css/css-grid/subgrid/orthogonal-writing-mode-004-ref.html": [ [] ], + "css/css-grid/subgrid/repeat-auto-fill-001-ref.html": [ + [] + ], + "css/css-grid/subgrid/repeat-auto-fill-004-ref.html": [ + [] + ], + "css/css-grid/subgrid/repeat-auto-fill-005-ref.html": [ + [] + ], + "css/css-grid/subgrid/repeat-auto-fill-007-ref.html": [ + [] + ], "css/css-grid/subgrid/subgrid-item-block-size-001-ref.html": [ [] ], @@ -163930,6 +164026,9 @@ "native-file-system/script-tests/FileSystemDirectoryHandle-getDirectory.js": [ [] ], + "native-file-system/script-tests/FileSystemDirectoryHandle-getEntries.js": [ + [] + ], "native-file-system/script-tests/FileSystemDirectoryHandle-getFile.js": [ [] ], @@ -203705,6 +203804,12 @@ {} ] ], + "css/css-color/animation/opacity-interpolation.html": [ + [ + "css/css-color/animation/opacity-interpolation.html", + {} + ] + ], "css/css-color/color-function-parsing.html": [ [ "css/css-color/color-function-parsing.html", @@ -204013,6 +204118,12 @@ {} ] ], + "css/css-flexbox/animation/order-interpolation.html": [ + [ + "css/css-flexbox/animation/order-interpolation.html", + {} + ] + ], "css/css-flexbox/display_flex_exist.html": [ [ "css/css-flexbox/display_flex_exist.html", @@ -208685,6 +208796,12 @@ {} ] ], + "css/css-overflow/overflow-codependent-scrollbars.html": [ + [ + "css/css-overflow/overflow-codependent-scrollbars.html", + {} + ] + ], "css/css-overflow/overflow-inline-transform-relative.html": [ [ "css/css-overflow/overflow-inline-transform-relative.html", @@ -258870,6 +258987,31 @@ } ] ], + "native-file-system/native_FileSystemDirectoryHandle-getEntries.tentative.https.manual.window.js": [ + [ + "native-file-system/native_FileSystemDirectoryHandle-getEntries.tentative.https.manual.window.html", + { + "script_metadata": [ + [ + "script", + "/resources/testdriver.js" + ], + [ + "script", + "resources/test-helpers.js" + ], + [ + "script", + "resources/native-fs-test-helpers.js" + ], + [ + "script", + "script-tests/FileSystemDirectoryHandle-getEntries.js" + ] + ] + } + ] + ], "native-file-system/native_FileSystemDirectoryHandle-getFile.tentative.https.manual.window.js": [ [ "native-file-system/native_FileSystemDirectoryHandle-getFile.tentative.https.manual.window.html", @@ -258985,6 +259127,46 @@ } ] ], + "native-file-system/sandboxed_FileSystemDirectoryHandle-getEntries.tentative.https.any.js": [ + [ + "native-file-system/sandboxed_FileSystemDirectoryHandle-getEntries.tentative.https.any.html", + { + "script_metadata": [ + [ + "script", + "resources/test-helpers.js" + ], + [ + "script", + "resources/sandboxed-fs-test-helpers.js" + ], + [ + "script", + "script-tests/FileSystemDirectoryHandle-getEntries.js" + ] + ] + } + ], + [ + "native-file-system/sandboxed_FileSystemDirectoryHandle-getEntries.tentative.https.any.worker.html", + { + "script_metadata": [ + [ + "script", + "resources/test-helpers.js" + ], + [ + "script", + "resources/sandboxed-fs-test-helpers.js" + ], + [ + "script", + "script-tests/FileSystemDirectoryHandle-getEntries.js" + ] + ] + } + ] + ], "native-file-system/sandboxed_FileSystemDirectoryHandle-getFile.tentative.https.any.js": [ [ "native-file-system/sandboxed_FileSystemDirectoryHandle-getFile.tentative.https.any.html", @@ -308704,6 +308886,12 @@ {} ] ], + "webxr/xrReferenceSpace_originOffset_viewer.https.html": [ + [ + "webxr/xrReferenceSpace_originOffset_viewer.https.html", + {} + ] + ], "webxr/xrRigidTransform_constructor.https.html": [ [ "webxr/xrRigidTransform_constructor.https.html", @@ -355932,6 +356120,10 @@ "4b39fdcf796083ace917f0a021a697c6e4eb7214", "testharness" ], + "css/css-color/animation/opacity-interpolation.html": [ + "ce26a8c79939e1d35f5ea35686fc272aad765914", + "testharness" + ], "css/css-color/blacktext-ref.html": [ "ddfa9100cbef6094375df8b40eeb9673e690d4f7", "support" @@ -359044,6 +359236,10 @@ "da69a06891ee2d16f91db5d839e14aa2d876b604", "testharness" ], + "css/css-flexbox/animation/order-interpolation.html": [ + "8096fc3db661078029f991a45f789f439108849c", + "testharness" + ], "css/css-flexbox/anonymous-flex-item-001.html": [ "3e749d43f76981a5cc0b372c7ba0c364c350b6b2", "reftest" @@ -373672,6 +373868,50 @@ "4a0edd7e6d5aefe06fc0d9989c84d3871ea61a14", "reftest" ], + "css/css-grid/subgrid/repeat-auto-fill-001-ref.html": [ + "bbf5d374589b29c9c0dcb04b941160a94130b3a1", + "support" + ], + "css/css-grid/subgrid/repeat-auto-fill-001.html": [ + "643cde377e66416dbc4047124d1157b0679eb8f5", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-002.html": [ + "38d0bea0d08e6e1b1691a595ac9a1c2dfea59adb", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-003.html": [ + "b58799bd86bd1ad1f7875a6c9da7e8247136e6f8", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-004-ref.html": [ + "07ba960200b1fe9ba69448da8e5e9ff1ebf547fd", + "support" + ], + "css/css-grid/subgrid/repeat-auto-fill-004.html": [ + "beacff588a2c6209ee89b8715eccd374b1847ba8", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-005-ref.html": [ + "95976e8216d8be0cb14e57fa4d9d06600c82c98f", + "support" + ], + "css/css-grid/subgrid/repeat-auto-fill-005.html": [ + "0cf16d47a27e1105d12ef595e8864d46793e2790", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-006.html": [ + "4a16d8e4a9b9c476fce6b8e2bb653dcb59431029", + "reftest" + ], + "css/css-grid/subgrid/repeat-auto-fill-007-ref.html": [ + "9bc2eeff1c7dd57873058439c9072eaa16f9d441", + "support" + ], + "css/css-grid/subgrid/repeat-auto-fill-007.html": [ + "949d8296fef40637101cb8bdb24f18710e4e3854", + "reftest" + ], "css/css-grid/subgrid/subgrid-item-block-size-001-ref.html": [ "d264a3455a6c580976d2519ab4e0eb206b1164bf", "support" @@ -378780,6 +379020,10 @@ "2ed8d2687a33608e0e70884ad2ea59330d2b09e3", "reftest" ], + "css/css-overflow/overflow-codependent-scrollbars.html": [ + "eb0e4f5ea2ed9a97c0931c2c53de5e62e72ba1dd", + "testharness" + ], "css/css-overflow/overflow-inline-transform-relative.html": [ "4df7b6389432cc6c65bae3fe3b5b9c2f00ba7bde", "testharness" @@ -452569,7 +452813,7 @@ "support" ], "interfaces/entries-api.idl": [ - "548aec13ab70eeedb9ba01ff96e0b3cb1d783510", + "52693138a4cd9d86f9a48a8e5300a8006298defb", "support" ], "interfaces/event-timing.idl": [ @@ -452889,7 +453133,7 @@ "support" ], "interfaces/web-bluetooth.idl": [ - "f515dda1a814ee1121623033684b3020c355f9ec", + "ec7a8e71ca09c7648801e6f2bb91c711c857fe34", "support" ], "interfaces/web-nfc.idl": [ @@ -458948,6 +459192,10 @@ "cfe729cd1f1dd4b53f00b3b13cd53f64f84ca409", "testharness" ], + "native-file-system/native_FileSystemDirectoryHandle-getEntries.tentative.https.manual.window.js": [ + "f27a44d12459cccbbe7192fe13104d77c68795ae", + "testharness" + ], "native-file-system/native_FileSystemDirectoryHandle-getFile.tentative.https.manual.window.js": [ "0455cb800919ee353b7f2e87bf47b76ba075519b", "testharness" @@ -458976,6 +459224,10 @@ "6fcf566e31fbf061e7545280198562d9e41cad11", "testharness" ], + "native-file-system/sandboxed_FileSystemDirectoryHandle-getEntries.tentative.https.any.js": [ + "da620e2a3b17a97bc4db3872484f217a3fa2c582", + "testharness" + ], "native-file-system/sandboxed_FileSystemDirectoryHandle-getFile.tentative.https.any.js": [ "65ae891cd44418554800e12801617097f6a72c91", "testharness" @@ -458992,6 +459244,10 @@ "c2c128f5eded06f440e634051fac021e20061e0d", "support" ], + "native-file-system/script-tests/FileSystemDirectoryHandle-getEntries.js": [ + "571683ccfd1182631a0398017a9f67fa04bb255c", + "support" + ], "native-file-system/script-tests/FileSystemDirectoryHandle-getFile.js": [ "4d8ee96c3d033130f5940306d6f09737db7b0e9c", "support" @@ -479637,7 +479893,7 @@ "support" ], "resources/chromium/mock-barcodedetection.js": [ - "2558bbda58913ec51c36bdce28e0f84a1aea32e7", + "703db425590d8a8450f285878abb025a42a15122", "support" ], "resources/chromium/mock-barcodedetection.js.headers": [ @@ -479645,7 +479901,7 @@ "support" ], "resources/chromium/mock-facedetection.js": [ - "1275e4dd2f5e24988e723a728dbf5bb4acc4c6cb", + "01306a2a0c7f470f56d746aa68dff3fe3636c575", "support" ], "resources/chromium/mock-facedetection.js.headers": [ @@ -504801,7 +505057,7 @@ "support" ], "webxr/resources/webxr_test_asserts.js": [ - "24b5274bc23d4e601e94eebd93968d9c30942b08", + "863b994572441d0efdbe92dbd8aec29f9152069f", "support" ], "webxr/resources/webxr_test_constants.js": [ @@ -504940,6 +505196,10 @@ "cfa3cc7ca2fe7cfbd656d9164b0d1ab3dd60ca41", "testharness" ], + "webxr/xrReferenceSpace_originOffset_viewer.https.html": [ + "2f93914e851ed55d5f9e60cc131316132e7ca226", + "testharness" + ], "webxr/xrRigidTransform_constructor.https.html": [ "15a7f2b5771a78dba2036ec46933e826c9a54355", "testharness"
diff --git a/third_party/blink/web_tests/external/wpt/compression/decompression-bad-chunks.any.js b/third_party/blink/web_tests/external/wpt/compression/decompression-bad-chunks.any.js index 8f44ffd..b8954905 100644 --- a/third_party/blink/web_tests/external/wpt/compression/decompression-bad-chunks.any.js +++ b/third_party/blink/web_tests/external/wpt/compression/decompression-bad-chunks.any.js
@@ -34,20 +34,16 @@ { name: 'shared Uint8Array', get value() { - new Uint8Array(new SharedArrayBuffer()) + return new Uint8Array(new SharedArrayBuffer()) } }, { name: 'invalid deflate bytes', - get value() { - new Uint8Array([0, 156, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 48, 173, 6, 36]) - } + value: new Uint8Array([0, 156, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 48, 173, 6, 36]) }, { name: 'invalid gzip bytes', - get value() { - new Uint8Array([0, 139, 8, 0, 0, 0, 0, 0, 0, 3, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 176, 1, 57, 179, 15, 0, 0, 0]) - } + value: new Uint8Array([0, 139, 8, 0, 0, 0, 0, 0, 0, 3, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 176, 1, 57, 179, 15, 0, 0, 0]) }, ];
diff --git a/third_party/blink/web_tests/external/wpt/compression/decompression-empty-input.any.js b/third_party/blink/web_tests/external/wpt/compression/decompression-empty-input.any.js new file mode 100644 index 0000000..ff4cff52 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/compression/decompression-empty-input.any.js
@@ -0,0 +1,30 @@ +// META: global=worker + +'use strict'; + +const gzipEmptyValue = new Uint8Array([31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0]); +const deflateEmptyValue = new Uint8Array([120, 156, 3, 0, 0, 0, 0, 1]); + +promise_test(async t => { + const ds = new DecompressionStream('gzip'); + const reader = ds.readable.getReader(); + const writer = ds.writable.getWriter(); + const writePromise = writer.write(gzipEmptyValue); + writer.close(); + const { value, done } = await reader.read(); + assert_true(done, "read() should set done"); + assert_equals(value, undefined, "value should be undefined"); + await writePromise; +}, 'decompressing gzip empty input should work'); + +promise_test(async t => { + const ds = new DecompressionStream('deflate'); + const reader = ds.readable.getReader(); + const writer = ds.writable.getWriter(); + const writePromise = writer.write(deflateEmptyValue); + writer.close(); + const { value, done } = await reader.read(); + assert_true(done, "read() should set done"); + assert_equals(value, undefined, "value should be undefined"); + await writePromise; +}, 'decompressing deflate empty input should work');
diff --git a/third_party/blink/web_tests/external/wpt/compression/decompression-split-chunk.any.js b/third_party/blink/web_tests/external/wpt/compression/decompression-split-chunk.any.js new file mode 100644 index 0000000..a5454165 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/compression/decompression-split-chunk.any.js
@@ -0,0 +1,44 @@ +// META: global=worker + +'use strict'; + +const compressedBytesWithDeflate = new Uint8Array([120, 156, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 48, 173, 6, 36]); +const compressedBytesWithGzip = new Uint8Array([31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 176, 1, 57, 179, 15, 0, 0, 0]); +const expectedChunkValue = new TextEncoder().encode('expected output'); + +async function decompressArrayBuffer(input, format, chunkSize) { + const ds = new DecompressionStream(format); + const reader = ds.readable.getReader(); + const writer = ds.writable.getWriter(); + for (let beginning = 0; beginning < input.length; beginning += chunkSize) { + writer.write(input.slice(beginning, beginning + chunkSize)); + } + writer.close(); + const out = []; + let totalSize = 0; + while (true) { + const { value, done } = await reader.read(); + if (done) break; + out.push(value); + totalSize += value.byteLength; + } + const concatenated = new Uint8Array(totalSize); + let offset = 0; + for (const array of out) { + concatenated.set(array, offset); + offset += array.byteLength; + } + return concatenated; +} + +for (let chunkSize = 1; chunkSize < 16; ++chunkSize) { + promise_test(async t => { + const decompressedData = await decompressArrayBuffer(compressedBytesWithDeflate, 'deflate', chunkSize); + assert_array_equals(decompressedData, expectedChunkValue, "value should match"); + }, `decompressing splitted chunk into pieces of size ${chunkSize} should work in deflate`); + + promise_test(async t => { + const decompressedData = await decompressArrayBuffer(compressedBytesWithGzip, 'gzip', chunkSize); + assert_array_equals(decompressedData, expectedChunkValue, "value should match"); + }, `decompressing splitted chunk into pieces of size ${chunkSize} should work in gzip`); +}
diff --git a/third_party/blink/web_tests/external/wpt/compression/decompression-uint8array-output.any.js b/third_party/blink/web_tests/external/wpt/compression/decompression-uint8array-output.any.js new file mode 100644 index 0000000..06c421a8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/compression/decompression-uint8array-output.any.js
@@ -0,0 +1,26 @@ +// META: global=worker + +'use strict'; + +const deflateChunkValue = new Uint8Array([120, 156, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 48, 173, 6, 36]); +const gzipChunkValue = new Uint8Array([31, 139, 8, 0, 0, 0, 0, 0, 0, 3, 75, 173, 40, 72, 77, 46, 73, 77, 81, 200, 47, 45, 41, 40, 45, 1, 0, 176, 1, 57, 179, 15, 0, 0, 0]); + +promise_test(async t => { + const ds = new DecompressionStream('deflate'); + const reader = ds.readable.getReader(); + const writer = ds.writable.getWriter(); + const writePromise = writer.write(deflateChunkValue); + const { value } = await reader.read(); + assert_equals(value.constructor, Uint8Array, "type should match"); + await writePromise; +}, 'decompressing deflated output should give Uint8Array chunks'); + +promise_test(async t => { + const ds = new DecompressionStream('gzip'); + const reader = ds.readable.getReader(); + const writer = ds.writable.getWriter(); + const writePromise = writer.write(gzipChunkValue); + const { value } = await reader.read(); + assert_equals(value.constructor, Uint8Array, "type should match"); + await writePromise; +}, 'decompressing gzip output should give Uint8Array chunks');
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001-ref.html new file mode 100644 index 0000000..bbf5d37 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001-ref.html
@@ -0,0 +1,362 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: repeat(auto-fill, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-template-columns: subgrid; + grid-column: 3 / span 4; + grid-auto-rows: 8px; + background: grey; +} + +.subgrid > :nth-child(2n) { background: black; } +.subgrid > :nth-child(2n+1) { background: pink; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0e"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0f"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0g"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0h"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0i"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0j"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:2"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1e"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-5"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> +</div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001.html new file mode 100644 index 0000000..643cde3 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-001.html
@@ -0,0 +1,394 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-001-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-column: 3 / span 4; + grid-auto-rows: 8px; + background: grey; +} + +.fill-0a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] [z] } /* [z] [z] [z] [z] [z] */ +.fill-0b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [x] [z] [z] [z] [z] */ +.fill-0c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [x] [z] [z] [z] */ +.fill-0d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [z] [z] */ +.fill-0e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [z] */ +.fill-0f { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ +.fill-0g { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0h { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0i { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [x] */ +.fill-0j { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ + +.fill-1a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [y] [z] [z] [z] [z] */ +.fill-1b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [y] [z] [z] [z] */ +.fill-1c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [y] [z] [z] */ +.fill-1d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [y] [z] */ +.fill-1e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [y] */ + +.fill-2a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] } /* [y] [y] [z] [z] [z] */ +.fill-2b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [y] [y] [z] [z] */ +.fill-2c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [y] [y] [z] */ +.fill-2d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [y] [y] */ + +.fill-3a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] } /* [y] [y] [y] [z] [z] */ +.fill-3b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] } /* [x] [y] [y] [y] [z] */ +.fill-3c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [y] [y] [y] */ + +.fill-4a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] } /* [y] [y] [y] [y] [z] */ +.fill-4b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) } /* [x] [y] [y] [y] [y] */ + +.fill-5 { grid-template-columns: subgrid repeat(auto-fill, [y]) } /* [y] [y] [y] [y] [y] */ + +.subgrid > :nth-child(2n) { background: black; } +.subgrid > :nth-child(2n+1) { background: pink; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0b"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0c"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0d"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0e"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0f"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0g"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0h"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0i"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0j"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1a"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1b"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1c"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1d"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1e"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2a"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2b"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2c"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2d"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3a"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3b"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3c"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4a"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4b"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-5"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-002.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-002.html new file mode 100644 index 0000000..38d0bea0 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-002.html
@@ -0,0 +1,397 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill, line-names) in parent subgrid</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-001-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-template-columns: subgrid; + grid-column: 3 / span 4; + grid-auto-rows: 8px; + background: grey; +} +.grid > .subgrid { grid-template-rows: auto; } +.grid > .subgrid > .subgrid { grid-column: 1 / span 4; } + +.fill-0a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] [z] } /* [z] [z] [z] [z] [z] */ +.fill-0b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [x] [z] [z] [z] [z] */ +.fill-0c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [x] [z] [z] [z] */ +.fill-0d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [z] [z] */ +.fill-0e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [z] */ +.fill-0f { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ +.fill-0g { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0h { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0i { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [x] */ +.fill-0j { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ + +.fill-1a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [y] [z] [z] [z] [z] */ +.fill-1b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [y] [z] [z] [z] */ +.fill-1c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [y] [z] [z] */ +.fill-1d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [y] [z] */ +.fill-1e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [y] */ + +.fill-2a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] } /* [y] [y] [z] [z] [z] */ +.fill-2b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [y] [y] [z] [z] */ +.fill-2c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [y] [y] [z] */ +.fill-2d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [y] [y] */ + +.fill-3a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] } /* [y] [y] [y] [z] [z] */ +.fill-3b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] } /* [x] [y] [y] [y] [z] */ +.fill-3c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [y] [y] [y] */ + +.fill-4a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] } /* [y] [y] [y] [y] [z] */ +.fill-4b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) } /* [x] [y] [y] [y] [y] */ + +.fill-5 { grid-template-columns: subgrid repeat(auto-fill, [y]) } /* [y] [y] [y] [y] [y] */ + +.subgrid > .subgrid > :nth-child(2n) { background: black; } +.subgrid > .subgrid > :nth-child(2n+1) { background: pink; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0e"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0f"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0g"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0h"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0i"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0j"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1e"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-5"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-003.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-003.html new file mode 100644 index 0000000..b58799b --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-003.html
@@ -0,0 +1,403 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill, line-names) in orthogonal parent subgrid</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-001-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-template-columns: subgrid; + grid-column: 3 / span 4; + background: grey; +} +.grid > .subgrid > .subgrid { + writing-mode: vertical-lr; + grid-template-rows: subgrid; + grid-template-columns: initial; + grid-column: 1 / span 4; + grid-auto-columns: 8px; + grid-auto-flow: column; +} + +.fill-0a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] [z] } /* [z] [z] [z] [z] [z] */ +.fill-0b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [x] [z] [z] [z] [z] */ +.fill-0c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [x] [z] [z] [z] */ +.fill-0d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [z] [z] */ +.fill-0e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [z] */ +.fill-0f { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ +.fill-0g { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0h { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0i { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [x] */ +.fill-0j { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ + +.fill-1a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [y] [z] [z] [z] [z] */ +.fill-1b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [y] [z] [z] [z] */ +.fill-1c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [y] [z] [z] */ +.fill-1d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [y] [z] */ +.fill-1e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [y] */ + +.fill-2a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] } /* [y] [y] [z] [z] [z] */ +.fill-2b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [y] [y] [z] [z] */ +.fill-2c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [y] [y] [z] */ +.fill-2d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [y] [y] */ + +.fill-3a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] } /* [y] [y] [y] [z] [z] */ +.fill-3b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] } /* [x] [y] [y] [y] [z] */ +.fill-3c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [y] [y] [y] */ + +.fill-4a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] } /* [y] [y] [y] [y] [z] */ +.fill-4b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) } /* [x] [y] [y] [y] [y] */ + +.fill-5 { grid-template-columns: subgrid repeat(auto-fill, [y]) } /* [y] [y] [y] [y] [y] */ + +.subgrid > .subgrid > :nth-child(2n) { background: black; } +.subgrid > .subgrid > :nth-child(2n+1) { background: pink; } +.subgrid > .subgrid > * { writing-mode: horizontal-tb; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0b"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0c"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0d"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0e"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0f"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0g"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0h"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0i"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0j"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1a"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1b"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1c"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1d"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1e"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2a"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2b"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2c"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2d"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3a"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3b"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3c"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4a"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4b"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-5"><div class="subgrid"> + <div style="grid-row:y 5"></div> + <div style="grid-row:y 4"></div> + <div style="grid-row:y 3"></div> + <div style="grid-row:y 2"></div> + <div style="grid-row:y 1"></div> + <div style="grid-row:y -1"></div> + <div style="grid-row:y -2"></div> + <div style="grid-row:y -3"></div> + <div style="grid-row:y -4"></div> + <div style="grid-row:y -5"></div> +</div></div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004-ref.html new file mode 100644 index 0000000..07ba9602 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004-ref.html
@@ -0,0 +1,362 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: repeat(auto-fill, line-names) in RTL/LTR subgrids</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-template-columns: subgrid; + grid-column: 3 / span 4; + grid-auto-rows: 8px; + background: grey; +} + +.subgrid > :nth-child(2n) { background: black; } +.subgrid > :nth-child(2n+1) { background: pink; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0e"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0f"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0g"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0h"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0i"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-0j"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:2"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-1e"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-2d"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-3c"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4a"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-4b"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:1"></div> +</div></div> + +<div class="grid"><div class="subgrid fill-5"> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> + <div style="grid-column:4"></div> + <div style="grid-column:4"></div> + <div style="grid-column:3"></div> + <div style="grid-column:2"></div> + <div style="grid-column:1"></div> +</div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004.html new file mode 100644 index 0000000..beacff5 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-004.html
@@ -0,0 +1,397 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill, line-names) in RTL/LTR subgrids</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-004-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 15px; + border: 1px solid; +} + +.subgrid { + display: grid; + grid-template-columns: subgrid; + grid-column: 3 / span 4; + grid-auto-rows: 8px; + background: grey; +} +.grid > .subgrid { grid-template-rows: auto; direction:rtl; } +.grid > .subgrid > .subgrid { grid-column: 1 / span 4; direction:ltr; } + +.fill-0a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] [z] } /* [z] [z] [z] [z] [z] */ +.fill-0b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [x] [z] [z] [z] [z] */ +.fill-0c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [x] [z] [z] [z] */ +.fill-0d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [z] [z] */ +.fill-0e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [z] */ +.fill-0f { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ +.fill-0g { grid-template-columns: subgrid [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0h { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [x] [x] [x] */ +.fill-0i { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [x] [x] */ +.fill-0j { grid-template-columns: subgrid [x] [x] [x] [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [x] */ + +.fill-1a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] [z] } /* [y] [z] [z] [z] [z] */ +.fill-1b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] [z] } /* [x] [y] [z] [z] [z] */ +.fill-1c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [x] [y] [z] [z] */ +.fill-1d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [x] [y] [z] */ +.fill-1e { grid-template-columns: subgrid [x] [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [x] [y] */ + +.fill-2a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] [z] } /* [y] [y] [z] [z] [z] */ +.fill-2b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] [z] } /* [x] [y] [y] [z] [z] */ +.fill-2c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) [z] } /* [x] [x] [y] [y] [z] */ +.fill-2d { grid-template-columns: subgrid [x] [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [x] [y] [y] */ + +.fill-3a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] [z] } /* [y] [y] [y] [z] [z] */ +.fill-3b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) [z] } /* [x] [y] [y] [y] [z] */ +.fill-3c { grid-template-columns: subgrid [x] [x] repeat(auto-fill, [y]) } /* [x] [x] [y] [y] [y] */ + +.fill-4a { grid-template-columns: subgrid repeat(auto-fill, [y]) [z] } /* [y] [y] [y] [y] [z] */ +.fill-4b { grid-template-columns: subgrid [x] repeat(auto-fill, [y]) } /* [x] [y] [y] [y] [y] */ + +.fill-5 { grid-template-columns: subgrid repeat(auto-fill, [y]) } /* [y] [y] [y] [y] [y] */ + +.subgrid > .subgrid > :nth-child(2n) { background: black; } +.subgrid > .subgrid > :nth-child(2n+1) { background: pink; } + + </style> +</head> +<body> + +<div class="grid"><div class="subgrid fill-0a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0e"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0f"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0g"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0h"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0i"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-0j"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-1e"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-2d"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-3c"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4a"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-4b"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +<div class="grid"><div class="subgrid fill-5"><div class="subgrid"> + <div style="grid-column:y 5"></div> + <div style="grid-column:y 4"></div> + <div style="grid-column:y 3"></div> + <div style="grid-column:y 2"></div> + <div style="grid-column:y 1"></div> + <div style="grid-column:y -1"></div> + <div style="grid-column:y -2"></div> + <div style="grid-column:y -3"></div> + <div style="grid-column:y -4"></div> + <div style="grid-column:y -5"></div> +</div></div></div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005-ref.html new file mode 100644 index 0000000..95976e8 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005-ref.html
@@ -0,0 +1,165 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: repeat(auto-fill / INTEGER, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 20px; + background: lightgrey; +} + +.subgrid { + display: grid; + grid: auto / subgrid; + grid-column: 2 / span 4; + background: black; +} + +item { + min-width: 0; + min-height: 10px; + background: grey; +} + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:2 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:2 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:3 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:2 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:2 / 3"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-column:1 / 2"></item> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005.html new file mode 100644 index 0000000..0cf16d47 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-005.html
@@ -0,0 +1,167 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill / INTEGER, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-005-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 20px; + background: lightgrey; +} + +.subgrid { + display: grid; + grid-column: 2 / span 4; + background: black; +} + +item { + min-width: 0; + min-height: 10px; + grid-column:x -2 / x -1; + background: grey; +} + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [x] [x] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [x] [x] repeat(auto-fill,[x]) [] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [x] [x] repeat(auto-fill,[x]) [x] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(1,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(1,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(1,[]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] repeat(1,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(2,[]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(2,[x]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(2,[x]) repeat(auto-fill,[x]) [] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(3,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(4,[]) repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] [] [] [] repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(auto-fill,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-columns:subgrid repeat(5,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-006.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-006.html new file mode 100644 index 0000000..4a16d8e --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-006.html
@@ -0,0 +1,169 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill / INTEGER, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-005-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 20px; + background: lightgrey; +} + +.subgrid { + display: grid; + grid-column: 2 / span 4; + background: black; + writing-mode: vertical-lr; +} + +item { + min-width: 0; + min-height: 10px; + grid-row:x -2 / x -1; + background: grey; + writing-mode: horizontal-tb; +} + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [x] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[x]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[x]) repeat(auto-fill,[x]) [] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(3,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(4,[]) repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] [] [] repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(auto-fill,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(5,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007-ref.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007-ref.html new file mode 100644 index 0000000..9bc2eeff --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007-ref.html
@@ -0,0 +1,167 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>Reference: repeat(auto-fill / INTEGER, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 20px; + background: lightgrey; +} + +.subgrid { + display: grid; + grid: subgrid / auto; + grid-column: 2 / span 4; + background: black; + writing-mode: vertical-rl; +} + +item { + min-width: 0; + min-height: 10px; + background: grey; + writing-mode: horizontal-tb; +} + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:2 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:2 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:3 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 4"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 2"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:2 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:2 / 3"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 5"></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid"> + <item style="grid-row:1 / 2"></item> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007.html b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007.html new file mode 100644 index 0000000..949d829 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/css/css-grid/subgrid/repeat-auto-fill-007.html
@@ -0,0 +1,169 @@ +<!DOCTYPE HTML> +<!-- + Any copyright is dedicated to the Public Domain. + http://creativecommons.org/publicdomain/zero/1.0/ +--> +<html><head> + <meta charset="utf-8"> + <title>CSS Grid Test: repeat(auto-fill / INTEGER, line-names)</title> + <link rel="author" title="Mats Palmgren" href="mailto:mats@mozilla.com"> + <link rel="help" href="https://drafts.csswg.org/css-grid-2/#subgrid-listing"> + <link rel="match" href="repeat-auto-fill-007-ref.html"> + <style> +html,body { + color:black; background-color:white; font:10px/1 monospace; padding:0; margin:0; +} + +.grid { + display: inline-grid; + grid-auto-columns: 20px; + background: lightgrey; +} + +.subgrid { + display: grid; + grid-column: 2 / span 4; + background: black; + writing-mode: vertical-rl; +} + +item { + min-width: 0; + min-height: 10px; + grid-row:x -2 / x -1; + background: grey; + writing-mode: horizontal-tb; +} + + </style> +</head> +<body> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [x] [x] repeat(auto-fill,[x]) [x] [x] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] repeat(1,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[x]) repeat(auto-fill,[]) [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(2,[x]) repeat(auto-fill,[x]) [] []"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(3,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(4,[]) repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] [] [] [] repeat(auto-fill,[x]) [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(auto-fill,[]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(auto-fill,[x]) [] [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid [] repeat(auto-fill,[x]) [] [] [] [x]"> + <item></item> + </div> +</div> + +<div class="grid"> + <div class="subgrid" style="grid-template-rows:subgrid repeat(5,[]) repeat(auto-fill,[]) [x]"> + <item></item> + </div> +</div> + +</body> +</html>
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/entries-api.idl b/third_party/blink/web_tests/external/wpt/interfaces/entries-api.idl index 548aec13..5269313 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/entries-api.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/entries-api.idl
@@ -18,6 +18,7 @@ callback ErrorCallback = void (DOMException err); +[Exposed=Window] interface FileSystemEntry { readonly attribute boolean isFile; readonly attribute boolean isDirectory; @@ -29,6 +30,7 @@ optional ErrorCallback errorCallback); }; +[Exposed=Window] interface FileSystemDirectoryEntry : FileSystemEntry { FileSystemDirectoryReader createReader(); void getFile(optional USVString? path, @@ -48,18 +50,21 @@ callback FileSystemEntryCallback = void (FileSystemEntry entry); +[Exposed=Window] interface FileSystemDirectoryReader { void readEntries(FileSystemEntriesCallback successCallback, optional ErrorCallback errorCallback); }; callback FileSystemEntriesCallback = void (sequence<FileSystemEntry> entries); +[Exposed=Window] interface FileSystemFileEntry : FileSystemEntry { void file(FileCallback successCallback, optional ErrorCallback errorCallback); }; callback FileCallback = void (File file); +[Exposed=Window] interface FileSystem { readonly attribute USVString name; readonly attribute FileSystemDirectoryEntry root;
diff --git a/third_party/blink/web_tests/external/wpt/interfaces/web-bluetooth.idl b/third_party/blink/web_tests/external/wpt/interfaces/web-bluetooth.idl index f515dda..ec7a8e7 100644 --- a/third_party/blink/web_tests/external/wpt/interfaces/web-bluetooth.idl +++ b/third_party/blink/web_tests/external/wpt/interfaces/web-bluetooth.idl
@@ -60,10 +60,10 @@ [ Exposed=Window, - Constructor(DOMString type, optional ValueEventInit initDict = {}), SecureContext ] interface ValueEvent : Event { + constructor(DOMString type, optional ValueEventInit initDict = {}); readonly attribute any value; }; @@ -95,10 +95,10 @@ }; [ Exposed=Window, - Constructor(DOMString type, BluetoothAdvertisingEventInit init), SecureContext ] interface BluetoothAdvertisingEvent : Event { + constructor(DOMString type, BluetoothAdvertisingEventInit init); [SameObject] readonly attribute BluetoothDevice device; readonly attribute FrozenArray<UUID> uuids;
diff --git a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_asserts.js b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_asserts.js index 24b5274b..863b99457 100644 --- a/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_asserts.js +++ b/third_party/blink/web_tests/external/wpt/webxr/resources/webxr_test_asserts.js
@@ -30,6 +30,31 @@ } }; +// |p1|, |p2| - objects with x, y, z, w components that are floating point numbers +// |epsilon| - float specifying precision +// |prefix| - string used as a prefix for logging +let assert_point_significantly_not_equals = function(p1, p2, epsilon = FLOAT_EPSILON, prefix = "") { + + assert_not_equals(p1, null, prefix + "p1 must be non-null"); + assert_not_equals(p2, null, prefix + "p2 must be non-null"); + + let mismatched_component = null; + for (const v of ['x', 'y', 'z', 'w']) { + if (Math.abs(p1[v] - p2[v]) > epsilon) { + mismatched_component = v; + break; + } + } + + if (mismatched_component === null) { + let error_message = prefix + ' Point comparison failed.\n'; + error_message += ` p1: {x: ${p1.x}, y: ${p1.y}, z: ${p1.z}, w: ${p1.w}}\n`; + error_message += ` p2: {x: ${p2.x}, y: ${p2.y}, z: ${p2.z}, w: ${p2.w}}\n`; + error_message += ` Difference in components did not exceeded the given epsilon.\n`; + assert_unreached(error_message); + } +}; + // |m1|, |m2| - arrays of floating point numbers // |epsilon| - float specifying precision // |prefix| - string used as a prefix for logging
diff --git a/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html new file mode 100644 index 0000000..2f93914 --- /dev/null +++ b/third_party/blink/web_tests/external/wpt/webxr/xrReferenceSpace_originOffset_viewer.https.html
@@ -0,0 +1,54 @@ +<!DOCTYPE html> +<script src="/resources/testharness.js"></script> +<script src="/resources/testharnessreport.js"></script> +<script src="resources/webxr_util.js"></script> +<script src="resources/webxr_test_constants.js"></script> +<script src="resources/webxr_test_asserts.js"></script> +<canvas id="webgl-canvas"></canvas> + +<script> +let testName = "Creating XRReferenceSpace origin offset off of `viewer` space works."; + +let fakeDeviceInitParams = { + supportsImmersive: true, + viewerOrigin: VALID_POSE_TRANSFORM, + views: VALID_VIEWS, + supportedFeatures: ALL_FEATURES +}; + +let originOffsetPosition = new DOMPointReadOnly(0, 0, 1); + +let testFunction = + (session, fakeDeviceController, t) => new Promise((resolve) => { + + session.requestReferenceSpace('local').then( (localSpace) => { + session.requestReferenceSpace('viewer').then( (viewerSpace) => { + + let offsetSpace = viewerSpace.getOffsetReferenceSpace( + new XRRigidTransform(originOffsetPosition)); + + function OnFrame(time, frame) { + let viewerPose = frame.getPose(viewerSpace, localSpace); + let offsetPose = frame.getPose(offsetSpace, localSpace); + + let viewerPose2 = frame.getPose(localSpace ,viewerSpace); + let offsetPose2 = frame.getPose(localSpace, offsetSpace); + + t.step(() => { + assert_point_significantly_not_equals(viewerPose.transform.position, offsetPose.transform.position); + assert_point_significantly_not_equals(viewerPose2.transform.position, offsetPose2.transform.position); + }); + + resolve(); + } + + // Can only request input poses in an xr frame. + session.requestAnimationFrame(OnFrame); + }); + }); + }); + +xr_session_promise_test( + testName, testFunction, fakeDeviceInitParams, 'immersive-vr'); + +</script>
diff --git a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html index 7312192..4db34554 100644 --- a/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html +++ b/third_party/blink/web_tests/fast/peerconnection/RTCPeerConnection-many.html
@@ -3,6 +3,7 @@ <head> <script src="../../resources/testharness.js"></script> <script src="../../resources/testharnessreport.js"></script> +<script src="../../resources/gc.js"></script> </head> <body> <script> @@ -19,16 +20,16 @@ peerConnections.push(new RTCPeerConnection()); } -function cleanUpPeerConnectionsAndGarbageCollect() { +async function cleanUpPeerConnectionsAndGarbageCollect() { // Close all peer connections so that they may be garbage collected. peerConnections.forEach(pc => { pc.close(); }); peerConnections = []; - gc(); + await asyncGC(); } -test(function() { +promise_test(async function() { try { // These many peer connections should be OK to allocate. while (internals.peerConnectionCount() < @@ -45,13 +46,13 @@ // this test regardless of test result or unrelated tests may fail. let totalAllocatedPeerConnections = internals.peerConnectionCount(); let peerConnectionsAllocatedByTest = peerConnections.length; - cleanUpPeerConnectionsAndGarbageCollect(); + await cleanUpPeerConnectionsAndGarbageCollect(); // We cannot assert there are no peer connections since other swarming tests // could have left peer connections in a non-closed state, but we can assert // that at least all |peerConnectionsAllocatedByTest| have been collected. assert_less_than_equal( - totalAllocatedPeerConnections - peerConnectionsAllocatedByTest, - internals.peerConnectionCount()); + internals.peerConnectionCount(), + totalAllocatedPeerConnections - peerConnectionsAllocatedByTest); } }, 'Create and garbage collect many RTCPeerConnections');
diff --git a/third_party/closure_compiler/externs/file_manager_private.js b/third_party/closure_compiler/externs/file_manager_private.js index 5a8a0c8..c4000f9a 100644 --- a/third_party/closure_compiler/externs/file_manager_private.js +++ b/third_party/closure_compiler/externs/file_manager_private.js
@@ -668,19 +668,6 @@ chrome.fileManagerPrivate.removeMount = function(volumeId) {}; /** - * Marks a cache file of Drive as mounted or unmounted. - * Does nothing if the file is not under Drive directory. - * @param {string} sourcePath Mounted source file. Relative file path within - * external file system. - * @param {boolean} isMounted Mark as mounted if true. Mark as unmounted - * otherwise. - * @param {function()} callback Completion callback. runtime.lastError will be - * set if there was an error. - */ -chrome.fileManagerPrivate.markCacheAsMounted = function( - sourcePath, isMounted, callback) {}; - -/** * Get the list of mounted volumes. |callback| * @param {function((!Array<!chrome.fileManagerPrivate.VolumeMetadata>|undefined))} * callback Callback with the list of
diff --git a/third_party/freetype/README.chromium b/third_party/freetype/README.chromium index 722c99a..b50379ce 100644 --- a/third_party/freetype/README.chromium +++ b/third_party/freetype/README.chromium
@@ -1,7 +1,7 @@ Name: FreeType URL: http://www.freetype.org/ -Version: VER-2-10-1-59-g839a02361 -Revision: 839a023619b593b742f62ffab8e7e4f9da8c1593 +Version: VER-2-10-1-61-gc912690d2 +Revision: c912690d22ab16d772328396c27c47075924b012 License: Custom license "inspired by the BSD, Artistic, and IJG (Independent JPEG Group) licenses" License File: src/docs/FTL.TXT
diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index d9e2ac9..06a6929 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml
@@ -36193,6 +36193,10 @@ <histogram name="Enterprise.DevicePolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-02-23"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.DevicePolicyRefresh2. + </obsolete> <owner>bartfab@chromium.org</owner> <summary> Events measuring effectiveness of refreshing device policy when @@ -36202,6 +36206,18 @@ </summary> </histogram> +<histogram name="Enterprise.DevicePolicyRefresh2" + enum="EnterprisePolicyRefresh" expires_after="2020-02-23"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing device policy when + invalidations are received from a service. For each refresh, indicates + whether the policy changed, and whether the policy was invalidated at the + time of the refresh. + </summary> +</histogram> + <histogram name="Enterprise.DMServerRequestSuccess" enum="EnterpriseDMServerRequestSuccess" expires_after="2020-02-23"> <owner>poromov@chromium.org</owner> @@ -36427,6 +36443,10 @@ <histogram name="Enterprise.FCMInvalidationService.DevicePolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.FCMInvalidationService.DevicePolicyRefresh2. + </obsolete> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -36439,6 +36459,20 @@ </summary> </histogram> +<histogram name="Enterprise.FCMInvalidationService.DevicePolicyRefresh2" + enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing device policy when + invalidations are received from a service. For each refresh, indicates + whether the policy changed, and whether the policy was invalidated at the + time of the refresh. Subset of "Enterprise.DevicePolicyRefresh2". + Gets recorded only when FCMInvalidationService is used as + InvalidationService. + </summary> +</histogram> + <histogram name="Enterprise.FCMInvalidationService.PolicyInvalidations" enum="EnterprisePolicyInvalidations" expires_after="2020-03-08"> <owner>askaraitzhan@google.com</owner> @@ -36469,6 +36503,10 @@ <histogram name="Enterprise.FCMInvalidationService.PolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-03-08"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.FCMInvalidationService.PolicyRefresh2. + </obsolete> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -36480,6 +36518,19 @@ </summary> </histogram> +<histogram name="Enterprise.FCMInvalidationService.PolicyRefresh2" + enum="EnterprisePolicyRefresh" expires_after="2020-03-08"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing user policy when invalidations + are received from a service. For each refresh, indicates whether the policy + changed, and whether the policy was invalidated at the time of the refresh. + Subset of "Enterprise.PolicyRefresh2". Gets recorded only when + FCMInvalidationService is used as InvalidationService. + </summary> +</histogram> + <histogram name="Enterprise.HeartbeatSignal" enum="BooleanSuccess" expires_after="2020-04-01"> <owner>ayaelattar@chromium.org</owner> @@ -36695,6 +36746,10 @@ <histogram name="Enterprise.PolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.PolicyRefresh2. + </obsolete> <owner>mnissler@chromium.org</owner> <summary> Events measuring effectiveness of refreshing user policy when invalidations @@ -36703,6 +36758,17 @@ </summary> </histogram> +<histogram name="Enterprise.PolicyRefresh2" enum="EnterprisePolicyRefresh" + expires_after="2020-03-01"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing user policy when invalidations + are received from a service. For each refresh, indicates whether the policy + changed, and whether the policy was invalidated at the time of the refresh. + </summary> +</histogram> + <histogram name="Enterprise.PolicyUpdatePeriod.Device" units="days" expires_after="M84"> <owner>antrim@chromium.org</owner> @@ -36851,6 +36917,10 @@ <histogram name="Enterprise.TiclInvalidationService.DevicePolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.TiclInvalidationService.DevicePolicyRefresh2. + </obsolete> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -36863,6 +36933,20 @@ </summary> </histogram> +<histogram name="Enterprise.TiclInvalidationService.DevicePolicyRefresh2" + enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing device policy when + invalidations are received from a service. For each refresh, indicates + whether the policy changed, and whether the policy was invalidated at the + time of the refresh. Subset of "Enterprise.DevicePolicyRefresh2". + Gets recorded only when TiclInvalidationService is used as + InvalidationService. + </summary> +</histogram> + <histogram name="Enterprise.TiclInvalidationService.PolicyInvalidations" enum="EnterprisePolicyInvalidations" expires_after="2020-03-08"> <owner>askaraitzhan@google.com</owner> @@ -36893,6 +36977,10 @@ <histogram name="Enterprise.TiclInvalidationService.PolicyRefresh" enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <obsolete> + Deprecated 10/2019 because was recorded incorrectly. Superseded by + Enterprise.TiclInvalidationService.PolicyRefresh2. + </obsolete> <owner>askaraitzhan@google.com</owner> <owner>isandrk@chromium.org</owner> <summary> @@ -36904,6 +36992,19 @@ </summary> </histogram> +<histogram name="Enterprise.TiclInvalidationService.PolicyRefresh2" + enum="EnterprisePolicyRefresh" expires_after="2020-03-01"> + <owner>askaraitzhan@google.com</owner> + <owner>isandrk@chromium.org</owner> + <summary> + Events measuring effectiveness of refreshing user policy when invalidations + are received from a service. For each refresh, indicates whether the policy + changed, and whether the policy was invalidated at the time of the refresh. + Subset of "Enterprise.PolicyRefresh2". Recorded only when + TiclInvalidationService was used as InvalidationService. + </summary> +</histogram> + <histogram name="Enterprise.UploadJobSuccess" enum="EnterpriseUploadJobSuccess" expires_after="M82"> <owner>poromov@chromium.org</owner> @@ -46921,7 +47022,7 @@ </histogram> <histogram name="FileBrowser.CrostiniShareDialog" - enum="FileManagerCrostiniShareDialogType" expires_after="2019-10-01"> + enum="FileManagerCrostiniShareDialogType" expires_after="2020-10-01"> <owner>joelhockey@chromium.org</owner> <owner>tbuckley@chromium.org</owner> <summary>Dialog shown when using crostini app to open a file.</summary> @@ -152698,8 +152799,7 @@ <histogram name="V8.TurboFanOptimizeExecute" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the execution phase of TurboFan optimization. Recorded on each @@ -152711,8 +152811,7 @@ <histogram name="V8.TurboFanOptimizeFinalize" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the finalization phase of TurboFan optimization. Recorded on @@ -152724,8 +152823,7 @@ <histogram name="V8.TurboFanOptimizeForOnStackReplacementExecute" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the execution phase of TurboFan optimization for On Stack @@ -152738,8 +152836,7 @@ <histogram name="V8.TurboFanOptimizeForOnStackReplacementFinalize" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the finalization phase of TurboFan optimization for On Stack @@ -152752,8 +152849,7 @@ <histogram name="V8.TurboFanOptimizeForOnStackReplacementPrepare" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the preparation phase of TurboFan optimization for On Stack @@ -152766,8 +152862,7 @@ <histogram name="V8.TurboFanOptimizeForOnStackReplacementTotalTime" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Total time from starting optimizing for On Stack Replacement (OSR) to @@ -152780,8 +152875,7 @@ <histogram name="V8.TurboFanOptimizePrepare" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Time spent in the preparation phase of TurboFan optimization. Recorded on @@ -152793,8 +152887,7 @@ <histogram name="V8.TurboFanOptimizeTotalBackground" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Total time spent on a background thread during TurboFan optimization. @@ -152806,8 +152899,7 @@ <histogram name="V8.TurboFanOptimizeTotalForeground" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Total time spent on the main thread during TurboFan optimization. Recorded @@ -152819,8 +152911,7 @@ <histogram name="V8.TurboFanOptimizeTotalTime" units="microseconds" expires_after="M80"> - <owner>bmeurer@chromium.org</owner> - <owner>jarin@chromium.org</owner> + <owner>neis@chromium.org</owner> <owner>mvstanton@chromium.org</owner> <summary> Total time from starting optimizing to installing the code object. Recorded
diff --git a/tools/perf/expectations.config b/tools/perf/expectations.config index 7d2a03b2..affcbb51 100644 --- a/tools/perf/expectations.config +++ b/tools/perf/expectations.config
@@ -126,7 +126,8 @@ crbug.com/894147 [ android-nexus-5x ] blink_perf.svg/SierpinskiCarpet.html [ Skip ] # Benchmark: jetstream -crbug.com/830600 [ android-nexus-5x android-webview ] jetstream/http://browserbench.org/JetStream/ [ Skip ] +crbug.com/830600 [ android-nexus-5x android-webview ] jetstream/JetStream [ Skip ] +crbug.com/1009843 [ android ] jetstream/JetStream [ Skip ] # Benchmark: loading.desktop crbug.com/723783 [ win ] loading.desktop/Orange_cold [ Skip ]
diff --git a/tools/perf/page_sets/data/jetstream.json b/tools/perf/page_sets/data/jetstream.json index 82cae52..a40abfd 100644 --- a/tools/perf/page_sets/data/jetstream.json +++ b/tools/perf/page_sets/data/jetstream.json
@@ -1,9 +1,9 @@ { "archives": { - "http://browserbench.org/JetStream/": { + "JetStream": { "DEFAULT": "jetstream_000.wprgo" } }, "description": "Describes the Web Page Replay archives for a story set. Don't edit by hand! Use record_wpr for updating.", "platform_specific": true -} \ No newline at end of file +}
diff --git a/tools/perf/page_sets/jetstream_pages.py b/tools/perf/page_sets/jetstream_pages.py index 98206ae..b77c505 100644 --- a/tools/perf/page_sets/jetstream_pages.py +++ b/tools/perf/page_sets/jetstream_pages.py
@@ -8,8 +8,10 @@ from telemetry.util import statistics from telemetry.value import list_of_scalar_values + class JetstreamStory(press_story.PressStory): - URL='http://browserbench.org/JetStream/' + URL = 'http://browserbench.org/JetStream/' + NAME = 'JetStream' def __init__(self, ps): super(JetstreamStory, self).__init__(ps) @@ -50,9 +52,9 @@ all_scores = [] for score_list in all_score_lists: all_scores.append(statistics.GeometricMean(score_list)) - self.AddJavascriptMetricSummaryValue( + self.AddJavascriptMetricValue( list_of_scalar_values.ListOfScalarValues( - None, 'Score', 'score', all_scores)) + self, 'Score', 'score', all_scores)) class JetstreamStorySet(story.StorySet):
diff --git a/ui/display/manager/display_change_observer.cc b/ui/display/manager/display_change_observer.cc index 0b08b11..982dd9f 100644 --- a/ui/display/manager/display_change_observer.cc +++ b/ui/display/manager/display_change_observer.cc
@@ -45,7 +45,7 @@ // Update the list of zoom levels whenever a new device scale factor is added // here. See zoom level list in /ui/display/manager/display_util.cc const DeviceScaleFactorDPIThreshold kThresholdTableForInternal[] = { - {320.f, 2.66667f}, {270.0f, 2.25f}, {230.0f, 2.0f}, {220.0f, 1.77778f}, + {320.f, 2.66666f}, {270.0f, 2.25f}, {230.0f, 2.0f}, {220.0f, 1.77777f}, {180.0f, 1.6f}, {150.0f, 1.25f}, {0.0f, 1.0f}, };
diff --git a/ui/display/manager/display_change_observer_unittest.cc b/ui/display/manager/display_change_observer_unittest.cc index 210318a..26df5d79 100644 --- a/ui/display/manager/display_change_observer_unittest.cc +++ b/ui/display/manager/display_change_observer_unittest.cc
@@ -187,7 +187,7 @@ EXPECT_EQ(1.0f, ComputeDeviceScaleFactor(21.5f, gfx::Rect(1920, 1080))); // 10" 1920x1200 - EXPECT_NEAR(1.77778f, ComputeDeviceScaleFactor(10.f, gfx::Rect(1920, 1200)), + EXPECT_NEAR(1.77777f, ComputeDeviceScaleFactor(10.f, gfx::Rect(1920, 1200)), std::numeric_limits<float>::epsilon()); // 12.1" 1280x800 @@ -215,13 +215,13 @@ EXPECT_EQ(2.25f, ComputeDeviceScaleFactor(12.3f, gfx::Rect(3000, 2000))); // 13.1" 3840x2160 - EXPECT_NEAR(2.66667f, ComputeDeviceScaleFactor(13.1f, gfx::Rect(3840, 2160)), + EXPECT_NEAR(2.66666f, ComputeDeviceScaleFactor(13.1f, gfx::Rect(3840, 2160)), std::numeric_limits<float>::epsilon()); // Erroneous values should still work. EXPECT_EQ(1.0f, DisplayChangeObserver::FindDeviceScaleFactor(-100.0f)); EXPECT_EQ(1.0f, DisplayChangeObserver::FindDeviceScaleFactor(0.0f)); - EXPECT_NEAR(2.66667f, DisplayChangeObserver::FindDeviceScaleFactor(10000.0f), + EXPECT_NEAR(2.66666f, DisplayChangeObserver::FindDeviceScaleFactor(10000.0f), std::numeric_limits<float>::epsilon()); }
diff --git a/ui/display/manager/display_util.cc b/ui/display/manager/display_util.cc index 857b348e..25a4aac 100644 --- a/ui/display/manager/display_util.cc +++ b/ui/display/manager/display_util.cc
@@ -53,11 +53,11 @@ {1.25f, {0.7f, 1.f / 1.25f, 0.85f, 0.9f, 0.95f, 1.f, 1.1f, 1.2f, 1.3f}}, {1.6f, {1.f / 1.6f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.f, 1.15f, 1.3f}}, {1.6f, {1.f / 1.6f, 0.7f, 0.75f, 0.8f, 0.85f, 0.9f, 1.f, 1.15f, 1.3f}}, - {1.77778f, {1.f / 1.77778f, 0.7f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f}}, + {1.77777f, {1.f / 1.77777f, 0.7f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f}}, {2.f, {1.f / 2.f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.1f, 1.25f, 1.5f}}, {2.25f, {1.f / 2.25f, 0.6f, 0.7f, 0.8f, 0.9f, 1.f, 1.15f, 1.3f, 1.5f}}, - {2.66667f, - {1.f / 2.66667f, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}}, + {2.66666f, + {1.f / 2.66666f, 0.5f, 0.6f, 0.8f, 0.9f, 1.f, 1.2f, 1.35f, 1.5f}}, }}; bool WithinEpsilon(float a, float b) {
diff --git a/ui/display/manager/display_utils_unittest.cc b/ui/display/manager/display_utils_unittest.cc index 420e3f9..3468b89 100644 --- a/ui/display/manager/display_utils_unittest.cc +++ b/ui/display/manager/display_utils_unittest.cc
@@ -57,7 +57,7 @@ } TEST_F(DisplayUtilTest, DisplayZoomsWithInternalDsf) { - std::vector<float> kDsfs = {1.25f, 1.6f, 1.77778f, 2.f, 2.25f, 2.66667f}; + std::vector<float> kDsfs = {1.25f, 1.6f, 1.77777f, 2.f, 2.25f, 2.66666f}; for (const auto& dsf : kDsfs) { SCOPED_TRACE(base::StringPrintf("dsf=%f", dsf));
diff --git a/ui/file_manager/file_manager/foreground/css/file_types.css b/ui/file_manager/file_manager/foreground/css/file_types.css index f29e4cc..b86a83c 100644 --- a/ui/file_manager/file_manager/foreground/css/file_types.css +++ b/ui/file_manager/file_manager/foreground/css/file_types.css
@@ -487,7 +487,7 @@ .tree-row:not([selected]) [volume-type-icon='provided'] { /* Third-party icons are not provided with both an active and a non-active version. This filter defines the non-active version of a provided icon. */ - -webkit-filter: contrast(0) brightness(0.7143); + filter: contrast(0) brightness(0.7143); } cr-menu-item[command='#install-new-extension'] .icon.start {
diff --git a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js index 47fe7830..779a1ea 100644 --- a/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js +++ b/ui/file_manager/file_manager/foreground/elements/xf_panel_item.js
@@ -166,6 +166,7 @@ /** * Remove an element from the panel using it's id. + * @return {?Element} * @private */ removePanelElementById_(id) { @@ -173,6 +174,7 @@ if (element) { element.remove(); } + return element; } /** @@ -188,8 +190,14 @@ // Remove the indicators/buttons that can change. this.removePanelElementById_('#indicator'); - this.removePanelElementById_('#primary-action'); - this.removePanelElementById_('#secondary-action'); + let element = this.removePanelElementById_('#primary-action'); + if (element) { + element.onclick = null; + } + element = this.removePanelElementById_('#secondary-action'); + if (element) { + element.onclick = null; + } // Mark the indicator as empty so it recreates on setAttribute. this.setAttribute('indicator', 'empty'); @@ -369,6 +377,16 @@ */ connectedCallback() { this.onclick = this.onClicked_.bind(this); + + // Set click event handler references. + let button = this.shadowRoot.querySelector('#primary-action'); + if (button) { + button.onclick = this.onclick; + } + button = this.shadowRoot.querySelector('#secondary-action'); + if (button) { + button.onclick = this.onclick; + } } /**
diff --git a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js index 688a2e2..d8562cc 100644 --- a/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js +++ b/ui/file_manager/file_manager/foreground/js/file_transfer_controller.js
@@ -453,55 +453,31 @@ const pastePlan = this.preparePaste(clipboardData, opt_destinationEntry, opt_effect); - return util.URLsToEntries(pastePlan.sourceURLs).then(entriesResult => { - const sourceEntries = entriesResult.entries; - const destinationEntry = pastePlan.destinationEntry; - const destinationLocationInfo = - this.volumeManager_.getLocationInfo(destinationEntry); + return FileTransferController.URLsToEntriesWithAccess(pastePlan.sourceURLs) + .then(entriesResult => { + const sourceEntries = entriesResult.entries; - const destinationIsOutsideOfDrive = - VolumeManagerCommon.getVolumeTypeFromRootType( - destinationLocationInfo.rootType) !== - VolumeManagerCommon.VolumeType.DRIVE; - - // Disallow transferring hosted files from Shared Drives to outside of - // Drive. This is because hosted files aren't 'real' files, so it doesn't - // make sense to allow a 'local' copy (e.g. in Downloads, or on a USB), - // where the file can't be accessed offline (or necessarily accessed at - // all) by the person who tries to open it. In future, block this for all - // hosted files, regardless of their source. For now, to maintain - // backwards-compatibility, just block this for hosted files stored in a - // Shared Drive. - if (sourceEntries.some( - entry => - util.isSharedDriveEntry(entry) && FileType.isHosted(entry)) && - destinationIsOutsideOfDrive) { - // For now, just don't execute the paste. - // TODO(sashab): Display a warning message, and disallow drag-drop - // operations. - return null; - } - - if (sourceEntries.length == 0) { - // This can happen when copied files were deleted before pasting them. - // We execute the plan as-is, so as to share the post-copy logic. - // This is basically same as getting empty by filtering same-directory - // entries. - return Promise.resolve(this.executePaste(pastePlan)); - } - const confirmationType = pastePlan.getConfirmationType(sourceEntries); - if (confirmationType == FileTransferController.ConfirmationType.NONE) { - return Promise.resolve(this.executePaste(pastePlan)); - } - const messages = - pastePlan.getConfirmationMessages(confirmationType, sourceEntries); - this.confirmationCallback_(pastePlan.isMove, messages) - .then(userApproved => { - if (userApproved) { - this.executePaste(pastePlan); - } - }); - }); + if (sourceEntries.length == 0) { + // This can happen when copied files were deleted before pasting + // them. We execute the plan as-is, so as to share the post-copy + // logic. This is basically same as getting empty by filtering + // same-directory entries. + return Promise.resolve(this.executePaste(pastePlan)); + } + const confirmationType = pastePlan.getConfirmationType(sourceEntries); + if (confirmationType == + FileTransferController.ConfirmationType.NONE) { + return Promise.resolve(this.executePaste(pastePlan)); + } + const messages = pastePlan.getConfirmationMessages( + confirmationType, sourceEntries); + this.confirmationCallback_(pastePlan.isMove, messages) + .then(userApproved => { + if (userApproved) { + this.executePaste(pastePlan); + } + }); + }); } /** @@ -1238,15 +1214,28 @@ return false; // Unsupported type of content. } - // Copying between different sources requires all files to be available. + const sourceUrls = (clipboardData.getData('fs/sources') || '').split('\n'); if (this.getSourceRootURL_( clipboardData, this.getDragAndDropGlobalData_()) !== - destinationLocationInfo.volumeInfo.fileSystem.root.toURL() && - this.isMissingFileContents_(clipboardData)) { - return false; + destinationLocationInfo.volumeInfo.fileSystem.root.toURL()) { + // Copying between different sources requires all files to be available. + if (this.isMissingFileContents_(clipboardData)) { + return false; + } + + // Block transferring hosted files between different sources in order to + // prevent hosted files from being transferred outside of Drive. This is + // done because hosted files aren't 'real' files, so it doesn't make sense + // to allow a 'local' copy (e.g. in Downloads, or on a USB), where the + // file can't be accessed offline (or necessarily accessed at all) by the + // person who tries to open it. It also blocks copying hosted files to + // other profiles, as the files would need to be shared in Drive first. + if (sourceUrls.some( + source => FileType.getTypeForName(source).type === 'hosted')) { + return false; + } } - const sourceUrls = (clipboardData.getData('fs/sources') || '').split('\n'); // If the destination is sub-tree of any of the sources paste isn't allowed. const destinationUrl = destinationEntry.toURL(); if (sourceUrls.some(source => destinationUrl.startsWith(source))) { @@ -1641,7 +1630,8 @@ * them, which is essential when pasting files from a different profile. * * @param {!Array<string>} urls Urls to be converted. - * @return {Promise<!Array<string>>} + * @return {Promise} Promise fulfilled with the object that has entries property + * and failureUrls property. The promise is never rejected. */ FileTransferController.URLsToEntriesWithAccess = urls => { return new Promise((resolve, reject) => {
diff --git a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js index 102bcaab..54b9eb8 100644 --- a/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js +++ b/ui/file_manager/file_manager/foreground/js/ui/directory_tree.js
@@ -1856,7 +1856,7 @@ let addAt = 0; while (addAt < parentItem.items.length && - parentItem.items[addAt].entry.name < newDirectory.name) { + util.compareName(parentItem.items[addAt].entry, newDirectory) < 0) { addAt++; }
diff --git a/ui/file_manager/integration_tests/file_manager/background.js b/ui/file_manager/integration_tests/file_manager/background.js index b498ea7fc..e0f87c3 100644 --- a/ui/file_manager/integration_tests/file_manager/background.js +++ b/ui/file_manager/integration_tests/file_manager/background.js
@@ -75,6 +75,7 @@ ENTRIES.unsupported, ENTRIES.testDocument, ENTRIES.testSharedDocument, + ENTRIES.testSharedFile, ]; /** @@ -159,6 +160,7 @@ const OFFLINE_ENTRY_SET = [ ENTRIES.testDocument, ENTRIES.testSharedDocument, + ENTRIES.testSharedFile, ]; /** @@ -170,6 +172,7 @@ */ const SHARED_WITH_ME_ENTRY_SET = [ ENTRIES.testSharedDocument, + ENTRIES.testSharedFile, ]; /**
diff --git a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js index 42aa7707..87500ed 100644 --- a/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js +++ b/ui/file_manager/integration_tests/file_manager/directory_tree_context_menu.js
@@ -682,6 +682,62 @@ }; /** + * Tests the creation of new folders from the directory tree from the context + * menu. Creates the new folders in random order to ensure directory tree + * sorting does not break folder renaming. crbug.com/1004717 + */ + testcase.dirCreateMultipleFolders = async () => { + // Open Files app on local downloads. + const appId = + await setupAndWaitUntilReady(RootPath.DOWNLOADS, [ENTRIES.hello], []); + + const createNewFolder = async (name) => { + // Right click on Downloads folder. + await remoteCall.waitAndRightClick(appId, TREEITEM_DOWNLOADS); + + // Wait for context menu to appear and create new folder. + const newFolderMenuItem = '#directory-tree-context-menu:not([hidden])' + + ' [command="#new-folder"]:not([hidden]):not([disabled])'; + await remoteCall.waitAndClickElement(appId, newFolderMenuItem); + + // Rename folder. + const textInput = '#directory-tree .tree-item[renaming] input'; + await remoteCall.waitForElement(appId, textInput); + await remoteCall.callRemoteTestUtil( + 'inputText', appId, [textInput, name]); + await remoteCall.callRemoteTestUtil( + 'fakeKeyDown', appId, [textInput, 'Enter', false, false, false]); + + // Wait for the folder to lose its renaming state. + const renamingItem = '#directory-tree .tree-item[renaming]'; + await remoteCall.waitForElementLost(appId, renamingItem); + }; + + const checkDownloadsSubdirectoriesExist = async (expectedLabels) => { + const directoryItemsQuery = + ['#directory-tree [entry-label="Downloads"] > .tree-children .label']; + const directoryItems = await remoteCall.callRemoteTestUtil( + 'queryAllElements', appId, directoryItemsQuery); + const directoryItemsLabels = directoryItems.map(child => child.text); + chrome.test.assertEq(expectedLabels, directoryItemsLabels); + }; + + // The folders in sorted order would be 111, aaa, bbb. Create these + // folders in random order. crbug.com/1004717 + let names = ['aaa', '111', 'bbb']; + while (names.length) { + const getRandomIndex = () => { + return Math.floor(Math.random() * Math.floor(names.length)); + }; + const name = names.splice(getRandomIndex(), 1); + await createNewFolder(name); + } + + // Check: the new folders should have been created in the right order. + await checkDownloadsSubdirectoriesExist(['111', 'aaa', 'bbb']); + }; + + /** * Tests context menu for Recent root, currently it doesn't show context menu. */ testcase.dirContextMenuRecent = async () => {
diff --git a/ui/file_manager/integration_tests/file_manager/gear_menu.js b/ui/file_manager/integration_tests/file_manager/gear_menu.js index c5b4fe1..2ae6408 100644 --- a/ui/file_manager/integration_tests/file_manager/gear_menu.js +++ b/ui/file_manager/integration_tests/file_manager/gear_menu.js
@@ -47,6 +47,7 @@ ENTRIES.unsupported, ENTRIES.testDocument, ENTRIES.testSharedDocument, + ENTRIES.testSharedFile, ENTRIES.hiddenFile, ]; @@ -79,6 +80,7 @@ ENTRIES.beautiful, ENTRIES.photos, ENTRIES.unsupported, + ENTRIES.testSharedFile, ]; /**
diff --git a/ui/file_manager/integration_tests/file_manager/transfer.js b/ui/file_manager/integration_tests/file_manager/transfer.js index cc29b9c..99d4ab62 100644 --- a/ui/file_manager/integration_tests/file_manager/transfer.js +++ b/ui/file_manager/integration_tests/file_manager/transfer.js
@@ -364,7 +364,7 @@ */ testcase.transferFromSharedToDownloads = () => { return transferBetweenVolumes(new TransferInfo({ - fileToTransfer: ENTRIES.testSharedDocument, + fileToTransfer: ENTRIES.testSharedFile, source: TRANSFER_LOCATIONS.sharedWithMe, destination: TRANSFER_LOCATIONS.downloads, })); @@ -386,7 +386,7 @@ */ testcase.transferFromOfflineToDownloads = () => { return transferBetweenVolumes(new TransferInfo({ - fileToTransfer: ENTRIES.testDocument, + fileToTransfer: ENTRIES.testSharedFile, source: TRANSFER_LOCATIONS.driveOffline, destination: TRANSFER_LOCATIONS.downloads, }));
diff --git a/ui/file_manager/integration_tests/test_util.js b/ui/file_manager/integration_tests/test_util.js index fb90e1e9..508ff1a8 100644 --- a/ui/file_manager/integration_tests/test_util.js +++ b/ui/file_manager/integration_tests/test_util.js
@@ -671,6 +671,19 @@ typeText: 'Google document' }), + testSharedFile: new TestEntryInfo({ + type: EntryType.FILE, + sourceFileName: 'text.txt', + targetPath: 'test.txt', + mimeType: 'text/plain', + sharedOption: SharedOption.SHARED, + lastModifiedTime: 'Mar 20, 2012, 11:40 PM', + nameText: 'test.txt', + sizeText: '51 bytes', + typeText: 'Plain text', + pinned: true + }), + newlyAdded: new TestEntryInfo({ type: EntryType.FILE, sourceFileName: 'music.ogg',
diff --git a/ui/views/controls/menu/menu_controller.cc b/ui/views/controls/menu/menu_controller.cc index cc7418e..3ef62bbe 100644 --- a/ui/views/controls/menu/menu_controller.cc +++ b/ui/views/controls/menu/menu_controller.cc
@@ -1444,7 +1444,7 @@ float raster_scale = ScaleFactorForDragFromWidget(source->GetWidget()); gfx::Canvas canvas(item->size(), raster_scale, false /* opaque */); - item->PaintButton(&canvas, MenuItemView::PB_FOR_DRAG); + item->PaintButton(&canvas, MenuItemView::PaintButtonMode::kForDrag); gfx::ImageSkia image(gfx::ImageSkiaRep(canvas.GetBitmap(), raster_scale)); std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>());
diff --git a/ui/views/controls/menu/menu_item_view.cc b/ui/views/controls/menu/menu_item_view.cc index ed23492..0fcca1e 100644 --- a/ui/views/controls/menu/menu_item_view.cc +++ b/ui/views/controls/menu/menu_item_view.cc
@@ -515,7 +515,7 @@ } void MenuItemView::OnPaint(gfx::Canvas* canvas) { - PaintButton(canvas, PB_NORMAL); + PaintButton(canvas, PaintButtonMode::kNormal); } gfx::Size MenuItemView::CalculatePreferredSize() const { @@ -971,7 +971,7 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) { const MenuConfig& config = MenuConfig::instance(); bool render_selection = - (mode == PB_NORMAL && IsSelected() && + (mode == PaintButtonMode::kNormal && IsSelected() && parent_menu_item_->GetSubmenu()->GetShowSelection(this) && (NonIconChildViewsCount() == 0)); if (forced_visual_selection_.has_value()) @@ -1019,7 +1019,7 @@ gfx::Rect text_bounds(label_start, top_margin, width, available_height); text_bounds.set_x(GetMirroredXForRect(text_bounds)); int flags = GetDrawStringFlags(); - if (mode == PB_FOR_DRAG) + if (mode == PaintButtonMode::kForDrag) flags |= gfx::Canvas::NO_SUBPIXEL_RENDERING; canvas->DrawStringRectWithFlags(title(), style.font_list, style.foreground, text_bounds, flags);
diff --git a/ui/views/controls/menu/menu_item_view.h b/ui/views/controls/menu/menu_item_view.h index 0e97c35..e129bed9 100644 --- a/ui/views/controls/menu/menu_item_view.h +++ b/ui/views/controls/menu/menu_item_view.h
@@ -395,7 +395,7 @@ friend class test::TestMenuItemViewNotShown; // for access to |submenu_|; friend class TestMenuItemView; // For access to AddEmptyMenus(); - enum PaintButtonMode { PB_NORMAL, PB_FOR_DRAG }; + enum class PaintButtonMode { kNormal, kForDrag }; // Calculates all sizes that we can from the OS. // @@ -432,8 +432,8 @@ // necessary. void AdjustBoundsForRTLUI(gfx::Rect* rect) const; - // Actual paint implementation. If mode is PB_FOR_DRAG, portions of the menu - // are not rendered. + // Actual paint implementation. If mode is kForDrag, portions of the menu are + // not rendered. void PaintButton(gfx::Canvas* canvas, PaintButtonMode mode); // Helper function for PaintButton(), draws the background for the button if
diff --git a/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html index 4c5405df..95c07bd 100644 --- a/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html +++ b/ui/webui/resources/cr_components/chromeos/smb_shares/add_smb_share_dialog.html
@@ -77,7 +77,8 @@ placeholder="\\server\share" error-message-allowed update-value-on-input autofocus - show-loading="[[discoveryActive_]]"> + show-loading="[[discoveryActive_]]" + loading-message="[[i18n('smbShareDiscoveryMessage')]]"> </cr-searchable-drop-down> <cr-input id="name" label="[[i18n('smbShareName')]]" value="{{mountName_}}" maxlength="64">
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn index 2f393a1..6a08ae11d 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/BUILD.gn
@@ -14,7 +14,7 @@ deps = [ "//third_party/polymer/v1_0/components-chromium/iron-dropdown:iron-dropdown-extracted", "//third_party/polymer/v1_0/components-chromium/iron-icon:iron-icon-extracted", - "//third_party/polymer/v1_0/components-chromium/paper-progress:paper-progress-extracted", + "//third_party/polymer/v1_0/components-chromium/paper-spinner:paper-spinner-lite-extracted", "//ui/webui/resources/cr_elements/cr_input:cr_input", ] }
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html index e8aefd0..b32e2bd 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
@@ -2,15 +2,16 @@ <link rel="import" href="../cr_input/cr_input.html"> <link rel="import" href="../cr_scrollable_behavior.html"> +<link rel="import" href="../hidden_style_css.html"> <link rel="import" href="../icons.html"> <link rel="import" href="../shared_vars_css.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-dropdown/iron-dropdown.html"> <link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html"> -<link rel="import" href="chrome://resources/polymer/v1_0/paper-progress/paper-progress.html"> +<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner-lite.html"> <dom-module id="cr-searchable-drop-down"> <template> - <style> + <style include="cr-hidden-style"> :host(:not([error-message-allowed])) cr-input { --cr-input-error-display: none; } @@ -79,14 +80,29 @@ width: 100%; } - paper-progress { - --paper-progress-active-color: var(--google-blue-600); - --paper-progress-height: 2px; - bottom: 0; - position: absolute; + #loading-box { + align-items: center; + box-sizing: border-box; + display: flex; + height: 32px; + padding: 0 8px; + text-align: start; width: 100%; } + #loading-box div { + @apply --cr-secondary-text; + font-size: 12px; + padding: 0 16px; + } + + #loading-box paper-spinner-lite { + --paper-spinner-color: var(--google-blue-600); + --paper-spinner-stroke-width: 2px; + height: 16px; + width: 16px; + } + .list-item { background: none; border: none; @@ -121,14 +137,16 @@ <div id="input-overlay" slot="suffix"> <div id="input-box"> <iron-icon id="dropdown-icon" icon="cr:arrow-drop-down"></iron-icon> - <paper-progress id="loading" indeterminate hidden="[[!showLoading]]"> - </paper-progress> </div> <div id="dropdown-box"> <iron-dropdown horizontal-align="left" vertical-align="top" vertical-offset="4" no-cancel-on-outside-click no-cancel-on-esc-key> <div slot="dropdown-content"> + <div id="loading-box" hidden="[[!showLoading]]"> + <paper-spinner-lite active></paper-spinner-lite> + <div>[[loadingMessage]]</div> + </div> <template is="dom-repeat" items="[[items]]" filter="[[filterItems_(searchTerm_)]]"> <button class="list-item" on-click="onSelect_" tabindex="-1">
diff --git a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js index ac77d8d..76da468 100644 --- a/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js +++ b/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js
@@ -41,6 +41,11 @@ */ errorMessage: String, + /** + * Message to display next to the loading spinner. + */ + loadingMessage: String, + placeholder: String, /** @type {!Array<string>} */ @@ -64,7 +69,7 @@ /** @type {boolean} */ updateValueOnInput: Boolean, - /** @private {boolean} */ + /** @type {boolean} */ showLoading: { type: Boolean, value: false,