--- a/.eslintrc.js
+++ b/.eslintrc.js
@@ -63,25 +63,20 @@ module.exports = {
root: true,
// New rules and configurations should generally be added in
// tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js to
// allow external repositories that use the plugin to pick them up as well.
extends: ["plugin:mozilla/recommended"],
plugins: ["mozilla", "import", "json"],
overrides: [
{
- files: [
- // All .eslintrc.js files are in the node environment, so turn that
- // on here.
- // https://github.com/eslint/eslint/issues/13008
- ".eslintrc.js",
- // *.config.js files are generally assumed to be configuration files
- // based for node.
- "*.config.?(m)js",
- ],
+ // All .eslintrc.js files are in the node environment, so turn that
+ // on here.
+ // https://github.com/eslint/eslint/issues/13008
+ files: [".eslintrc.js"],
env: {
node: true,
browser: false,
},
},
{
files: [
"**/*.jsx",
--- a/browser/components/aboutwelcome/.eslintrc.js
+++ b/browser/components/aboutwelcome/.eslintrc.js
@@ -1,26 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = {
// When adding items to this file please check for effects on sub-directories.
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
plugins: ["import", "react", "jsx-a11y"],
settings: {
react: {
version: "16.2.0",
},
},
extends: ["plugin:jsx-a11y/recommended"],
overrides: [
{
- // TODO: Bug 1773467 - Move these to .mjs or figure out a generic way
- // to identify these as modules.
- files: ["tests/unit/**/*.js"],
+ // Only mark the files as modules which are actually modules.
+ files: ["content-src/**", "tests/unit/**"],
parserOptions: {
sourceType: "module",
},
},
{
// These files use fluent-dom to insert content
files: [
"content-src/components/Zap.jsx",
@@ -33,17 +37,17 @@ module.exports = {
rules: {
"jsx-a11y/anchor-has-content": "off",
"jsx-a11y/heading-has-content": "off",
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/no-onchange": "off",
},
},
{
- files: ["content-src/**", "tests/unit/**"],
+ files: ["./*.js", "content-src/**", "tests/unit/**"],
env: {
node: true,
},
},
{
// Use a configuration that's appropriate for modules, workers and
// non-production files.
files: ["modules/*.jsm", "tests/**"],
@@ -51,16 +55,18 @@ module.exports = {
"no-implicit-globals": "off",
},
},
{
files: ["content-src/**", "tests/unit/**"],
rules: {
// Disallow commonjs in these directories.
"import/no-commonjs": 2,
+ // Allow JSX with arrow functions.
+ "react/jsx-no-bind": 0,
},
},
{
// These tests simulate the browser environment.
files: "tests/unit/**",
env: {
browser: true,
mocha: true,
@@ -71,28 +77,26 @@ module.exports = {
sinon: true,
},
},
{
files: "tests/**",
rules: {
"func-name-matching": 0,
"lines-between-class-members": 0,
+ "require-await": 0,
},
},
],
rules: {
"fetch-options/no-fetch-credentials": "error",
"react/jsx-boolean-value": ["error", "always"],
"react/jsx-key": "error",
- "react/jsx-no-bind": [
- "error",
- { allowArrowFunctions: true, allowFunctions: true },
- ],
+ "react/jsx-no-bind": "error",
"react/jsx-no-comment-textnodes": "error",
"react/jsx-no-duplicate-props": "error",
"react/jsx-no-target-blank": "error",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": "error",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/no-access-state-in-setstate": "error",
@@ -118,40 +122,49 @@ module.exports = {
],
"react/require-render-return": "error",
"accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }],
"array-callback-return": "error",
"block-scoped-var": "error",
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
+ "for-direction": "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
+ "handle-callback-err": "error",
+ "lines-between-class-members": "error",
"max-depth": ["error", 4],
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],
"max-statements": ["error", 50],
+ "max-statements-per-line": ["error", { max: 2 }],
"new-cap": ["error", { newIsCap: true, capIsNew: false }],
"no-alert": "error",
+ "no-buffer-constructor": "error",
"no-console": ["error", { allow: ["error"] }],
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-eq-null": "error",
"no-extend-native": "error",
"no-extra-label": "error",
"no-implicit-coercion": ["error", { allow: ["!!"] }],
"no-implicit-globals": "error",
"no-loop-func": "error",
+ "no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-new": "error",
"no-new-func": "error",
+ "no-new-require": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
+ "no-path-concat": "error",
+ "no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-return-assign": ["error", "except-parens"],
"no-script-url": "error",
"no-shadow": "error",
"no-template-curly-in-string": "error",
"no-undef-init": "error",
"no-unmodified-loop-condition": "error",
@@ -172,14 +185,15 @@ module.exports = {
},
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
radix: ["error", "always"],
+ "require-await": "error",
"sort-vars": "error",
"symbol-description": "error",
"vars-on-top": "error",
yoda: ["error", "never"],
},
};
--- a/browser/components/aboutwelcome/content-src/aboutwelcome.jsx
+++ b/browser/components/aboutwelcome/content-src/aboutwelcome.jsx
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import ReactDOM from "react-dom";
-import { AboutWelcomeUtils } from "./lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "./lib/aboutwelcome-utils";
import { MultiStageAboutWelcome } from "./components/MultiStageAboutWelcome";
import { ReturnToAMO } from "./components/ReturnToAMO";
class AboutWelcome extends React.PureComponent {
constructor(props) {
super(props);
this.state = { metricsFlowUri: null };
this.fetchFxAFlowUri = this.fetchFxAFlowUri.bind(this);
--- a/browser/components/aboutwelcome/content-src/components/AddonsPicker.jsx
+++ b/browser/components/aboutwelcome/content-src/components/AddonsPicker.jsx
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
import { Localized } from "./MSLocalized";
export const AddonsPicker = props => {
const { content } = props;
if (!content) {
return null;
}
--- a/browser/components/aboutwelcome/content-src/components/HelpText.jsx
+++ b/browser/components/aboutwelcome/content-src/components/HelpText.jsx
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import { Localized } from "./MSLocalized";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
const MS_STRING_PROP = "string_id";
export const HelpText = props => {
if (!props.text) {
return null;
}
if (props.hasImg) {
--- a/browser/components/aboutwelcome/content-src/components/HeroImage.jsx
+++ b/browser/components/aboutwelcome/content-src/components/HeroImage.jsx
@@ -1,14 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
export const HeroImage = props => {
const { height, url, alt } = props;
if (!url) {
return null;
}
--- a/browser/components/aboutwelcome/content-src/components/LanguageSwitcher.jsx
+++ b/browser/components/aboutwelcome/content-src/components/LanguageSwitcher.jsx
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React, { useState, useEffect } from "react";
import { Localized } from "./MSLocalized";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
/**
* The language switcher implements a hook that should be placed at a higher level
* than the actual language switcher component, as it needs to preemptively fetch
* and install langpacks for the user if there is a language mismatch screen.
*/
export function useLanguageSwitcher(
appAndSystemLocaleInfo,
--- a/browser/components/aboutwelcome/content-src/components/MobileDownloads.jsx
+++ b/browser/components/aboutwelcome/content-src/components/MobileDownloads.jsx
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import { Localized } from "./MSLocalized";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
export const MarketplaceButtons = props => {
return (
<ul className="mobile-download-buttons">
{props.buttons.includes("ios") ? (
<li className="ios">
<button
data-l10n-id={"spotlight-ios-marketplace-button"}
--- a/browser/components/aboutwelcome/content-src/components/MultiStageAboutWelcome.jsx
+++ b/browser/components/aboutwelcome/content-src/components/MultiStageAboutWelcome.jsx
@@ -1,19 +1,22 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React, { useState, useEffect, useRef } from "react";
import { Localized } from "./MSLocalized";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
import { MultiStageProtonScreen } from "./MultiStageProtonScreen";
import { useLanguageSwitcher } from "./LanguageSwitcher";
import { SubmenuButton } from "./SubmenuButton";
-import { BASE_PARAMS, addUtmParams } from "../lib/addUtmParams.mjs";
+import {
+ BASE_PARAMS,
+ addUtmParams,
+} from "asrouter/content-src/templates/FirstRun/addUtmParams";
// Amount of milliseconds for all transitions to complete (including delays).
const TRANSITION_OUT_TIME = 1000;
const LANGUAGE_MISMATCH_SCREEN_ID = "AW_LANGUAGE_MISMATCH";
export const MultiStageAboutWelcome = props => {
let { defaultScreens } = props;
const didFilter = useRef(false);
--- a/browser/components/aboutwelcome/content-src/components/MultiStageProtonScreen.jsx
+++ b/browser/components/aboutwelcome/content-src/components/MultiStageProtonScreen.jsx
@@ -1,15 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React, { useEffect, useState } from "react";
import { Localized } from "./MSLocalized";
-import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "../lib/aboutwelcome-utils";
import { MobileDownloads } from "./MobileDownloads";
import { MultiSelect } from "./MultiSelect";
import { Themes } from "./Themes";
import {
SecondaryCTA,
StepsIndicator,
ProgressBar,
} from "./MultiStageAboutWelcome";
--- a/browser/components/aboutwelcome/content-src/components/ReturnToAMO.jsx
+++ b/browser/components/aboutwelcome/content-src/components/ReturnToAMO.jsx
@@ -1,19 +1,19 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import React from "react";
import {
AboutWelcomeUtils,
DEFAULT_RTAMO_CONTENT,
-} from "../lib/aboutwelcome-utils.mjs";
+} from "../lib/aboutwelcome-utils";
import { MultiStageProtonScreen } from "./MultiStageProtonScreen";
-import { BASE_PARAMS } from "../lib/addUtmParams.mjs";
+import { BASE_PARAMS } from "asrouter/content-src/templates/FirstRun/addUtmParams";
export class ReturnToAMO extends React.PureComponent {
constructor(props) {
super(props);
this.fetchFlowParams = this.fetchFlowParams.bind(this);
this.handleAction = this.handleAction.bind(this);
}
rename from browser/components/aboutwelcome/content-src/lib/aboutwelcome-utils.mjs
rename to browser/components/aboutwelcome/content-src/lib/aboutwelcome-utils.js
--- a/browser/components/aboutwelcome/content/aboutwelcome.bundle.js
+++ b/browser/components/aboutwelcome/content/aboutwelcome.bundle.js
@@ -16,167 +16,172 @@ module.exports = React;
/***/ }),
/* 2 */
/***/ ((module) => {
module.exports = ReactDOM;
/***/ }),
/* 3 */
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AboutWelcomeUtils": () => (/* binding */ AboutWelcomeUtils),
/* harmony export */ "DEFAULT_RTAMO_CONTENT": () => (/* binding */ DEFAULT_RTAMO_CONTENT)
/* harmony export */ });
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
// If the container has a "page" data attribute, then this is
// a Spotlight modal or Feature Callout. Otherwise, this is
// about:welcome and we should return the current page.
-const page =
- document.querySelector(
- "#multi-stage-message-root.onboardingContainer[data-page]"
- )?.dataset.page || document.location.href;
-
+const page = document.querySelector("#multi-stage-message-root.onboardingContainer[data-page]")?.dataset.page || document.location.href;
const AboutWelcomeUtils = {
handleUserAction(action) {
return window.AWSendToParent("SPECIAL_ACTION", action);
},
sendImpressionTelemetry(messageId, context) {
window.AWSendEventTelemetry?.({
event: "IMPRESSION",
event_context: {
...context,
- page,
+ page
},
- message_id: messageId,
+ message_id: messageId
});
},
sendActionTelemetry(messageId, elementId, eventName = "CLICK_BUTTON") {
const ping = {
event: eventName,
event_context: {
source: elementId,
- page,
+ page
},
- message_id: messageId,
+ message_id: messageId
};
window.AWSendEventTelemetry?.(ping);
},
sendDismissTelemetry(messageId, elementId) {
// Don't send DISMISS telemetry in spotlight modals since they already send
// their own equivalent telemetry.
if (page !== "spotlight") {
this.sendActionTelemetry(messageId, elementId, "DISMISS");
}
},
async fetchFlowParams(metricsFlowUri) {
let flowParams;
try {
const response = await fetch(metricsFlowUri, {
- credentials: "omit",
+ credentials: "omit"
});
if (response.status === 200) {
- const { deviceId, flowId, flowBeginTime } = await response.json();
- flowParams = { deviceId, flowId, flowBeginTime };
+ const {
+ deviceId,
+ flowId,
+ flowBeginTime
+ } = await response.json();
+ flowParams = {
+ deviceId,
+ flowId,
+ flowBeginTime
+ };
} else {
console.error("Non-200 response", response);
}
} catch (e) {
flowParams = null;
}
return flowParams;
},
sendEvent(type, detail) {
- document.dispatchEvent(
- new CustomEvent(`AWPage:${type}`, {
- bubbles: true,
- detail,
- })
- );
+ document.dispatchEvent(new CustomEvent(`AWPage:${type}`, {
+ bubbles: true,
+ detail
+ }));
},
getLoadingStrategyFor(url) {
return url?.startsWith("http") ? "lazy" : "eager";
- },
+ }
};
-
const DEFAULT_RTAMO_CONTENT = {
template: "return_to_amo",
utm_term: "rtamo",
content: {
position: "split",
- title: { string_id: "mr1-return-to-amo-subtitle" },
+ title: {
+ string_id: "mr1-return-to-amo-subtitle"
+ },
has_noodles: false,
subtitle: {
- string_id: "mr1-return-to-amo-addon-title",
+ string_id: "mr1-return-to-amo-addon-title"
},
- backdrop:
- "var(--mr-welcome-background-color) var(--mr-welcome-background-gradient)",
- background:
- "url('chrome://activity-stream/content/data/content/assets/mr-rtamo-background-image.svg') no-repeat center",
+ backdrop: "var(--mr-welcome-background-color) var(--mr-welcome-background-gradient)",
+ background: "url('chrome://activity-stream/content/data/content/assets/mr-rtamo-background-image.svg') no-repeat center",
progress_bar: true,
primary_button: {
- label: { string_id: "mr1-return-to-amo-add-extension-label" },
+ label: {
+ string_id: "mr1-return-to-amo-add-extension-label"
+ },
source_id: "ADD_EXTENSION_BUTTON",
action: {
type: "INSTALL_ADDON_FROM_URL",
- data: { url: null, telemetrySource: "rtamo" },
- },
+ data: {
+ url: null,
+ telemetrySource: "rtamo"
+ }
+ }
},
secondary_button: {
label: {
- string_id: "onboarding-not-now-button-label",
+ string_id: "onboarding-not-now-button-label"
},
source_id: "RTAMO_START_BROWSING_BUTTON",
action: {
- type: "OPEN_AWESOME_BAR",
- },
+ type: "OPEN_AWESOME_BAR"
+ }
},
secondary_button_top: {
label: {
- string_id: "mr1-onboarding-sign-in-button-label",
+ string_id: "mr1-onboarding-sign-in-button-label"
},
source_id: "RTAMO_FXA_SIGNIN_BUTTON",
action: {
data: {
entrypoint: "activity-stream-firstrun",
- where: "tab",
+ where: "tab"
},
type: "SHOW_FIREFOX_ACCOUNTS",
- addFlowParams: true,
- },
- },
- },
+ addFlowParams: true
+ }
+ }
+ }
};
-
/***/ }),
/* 4 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "MultiStageAboutWelcome": () => (/* binding */ MultiStageAboutWelcome),
/* harmony export */ "SecondaryCTA": () => (/* binding */ SecondaryCTA),
/* harmony export */ "StepsIndicator": () => (/* binding */ StepsIndicator),
/* harmony export */ "ProgressBar": () => (/* binding */ ProgressBar),
/* harmony export */ "WelcomeScreen": () => (/* binding */ WelcomeScreen)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(6);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(10);
/* harmony import */ var _SubmenuButton__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(15);
-/* harmony import */ var _lib_addUtmParams_mjs__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19);
+/* harmony import */ var asrouter_content_src_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(19);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -217,17 +222,17 @@ const MultiStageAboutWelcome = props =>
didFilter.current = true;
const screenInitials = filteredScreens.map(({
id
}) => id?.split("_")[1]?.[0]).join("");
// Send impression ping when respective screen first renders
filteredScreens.forEach((screen, order) => {
if (index === order) {
const messageId = `${props.message_id}_${order}_${screen.id}_${screenInitials}`;
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(messageId, {
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(messageId, {
screen_family: props.message_id,
screen_index: order,
screen_id: screen.id,
screen_initials: screenInitials
});
window.AWAddScreenImpression?.(screen);
}
});
@@ -244,17 +249,17 @@ const MultiStageAboutWelcome = props =>
const [flowParams, setFlowParams] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null);
const {
metricsFlowUri
} = props;
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
(async () => {
if (metricsFlowUri) {
- setFlowParams(await _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.fetchFlowParams(metricsFlowUri));
+ setFlowParams(await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.fetchFlowParams(metricsFlowUri));
}
})();
}, [metricsFlowUri]);
// Allow "in" style to render to actually transition towards regular state,
// which also makes using browser back/forward navigation skip transitions.
const [transition, setTransition] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(props.transitions ? "in" : "");
(0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => {
@@ -463,43 +468,43 @@ class WelcomeScreen extends (react__WEBP
}
handleOpenURL(action, flowParams, UTMTerm) {
let {
type,
data
} = action;
if (type === "SHOW_FIREFOX_ACCOUNTS") {
let params = {
- ..._lib_addUtmParams_mjs__WEBPACK_IMPORTED_MODULE_6__.BASE_PARAMS,
+ ...asrouter_content_src_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_6__.BASE_PARAMS,
utm_term: `${UTMTerm}-screen`
};
if (action.addFlowParams && flowParams) {
params = {
...params,
...flowParams
};
}
data = {
...data,
extraParams: params
};
} else if (type === "OPEN_URL") {
let url = new URL(data.args);
- (0,_lib_addUtmParams_mjs__WEBPACK_IMPORTED_MODULE_6__.addUtmParams)(url, `${UTMTerm}-screen`);
+ (0,asrouter_content_src_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_6__.addUtmParams)(url, `${UTMTerm}-screen`);
if (action.addFlowParams && flowParams) {
url.searchParams.append("device_id", flowParams.deviceId);
url.searchParams.append("flow_id", flowParams.flowId);
url.searchParams.append("flow_begin_time", flowParams.flowBeginTime);
}
data = {
...data,
args: url.toString()
};
}
- return _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction({
+ return _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction({
type,
data
});
}
async handleAction(event) {
let {
props
} = this;
@@ -510,44 +515,44 @@ class WelcomeScreen extends (react__WEBP
targetContent = {
action: event.action
};
}
if (!(targetContent && targetContent.action)) {
return;
}
// Send telemetry before waiting on actions
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, source, event.name);
// Send additional telemetry if a messaging surface like feature callout is
// dismissed via the dismiss button. Other causes of dismissal will be
// handled separately by the messaging surface's own code.
if (value === "dismiss_button" && !event.name) {
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendDismissTelemetry(props.messageId, source);
}
let {
action
} = targetContent;
action = JSON.parse(JSON.stringify(action));
if (action.collectSelect) {
this.setMultiSelectActions(action);
}
let actionResult;
if (["OPEN_URL", "SHOW_FIREFOX_ACCOUNTS"].includes(action.type)) {
actionResult = await this.handleOpenURL(action, props.flowParams, props.UTMTerm);
} else if (action.type) {
- actionResult = await _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(action);
+ actionResult = await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.handleUserAction(action);
if (action.type === "FXA_SIGNIN_FLOW") {
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, actionResult ? "sign_in" : "sign_in_cancel", "FXA_SIGNIN_FLOW");
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, actionResult ? "sign_in" : "sign_in_cancel", "FXA_SIGNIN_FLOW");
}
// Wait until migration closes to complete the action
const hasMigrate = a => a.type === "SHOW_MIGRATION_WIZARD" || a.type === "MULTI_ACTION" && a.data?.actions?.some(hasMigrate);
if (hasMigrate(action)) {
await window.AWWaitForMigrationClose();
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, "migrate_close");
}
}
// A special tiles.action.theme value indicates we should use the event's value vs provided value.
if (action.theme) {
let themeToUse = action.theme === "<event>" ? event.currentTarget.value : this.props.initialTheme || action.theme;
this.props.setActiveTheme(themeToUse);
window.AWSelectTheme(themeToUse);
@@ -604,17 +609,17 @@ class WelcomeScreen extends (react__WEBP
}
if (checkboxAction) {
multiSelectActions.push(checkboxAction);
}
}
action.data.actions.unshift(...multiSelectActions);
// Send telemetry with selected checkbox ids
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, props.activeMultiSelect, "SELECT_CHECKBOX");
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(props.messageId, props.activeMultiSelect, "SELECT_CHECKBOX");
}
render() {
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_3__.MultiStageProtonScreen, {
content: this.props.content,
id: this.props.id,
order: this.props.order,
previousOrder: this.props.previousOrder,
activeTheme: this.props.activeTheme,
@@ -758,17 +763,17 @@ const Localized = ({
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "MultiStageProtonScreen": () => (/* binding */ MultiStageProtonScreen),
/* harmony export */ "ProtonScreenActionButtons": () => (/* binding */ ProtonScreenActionButtons),
/* harmony export */ "ProtonScreen": () => (/* binding */ ProtonScreen)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _MobileDownloads__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
/* harmony import */ var _MultiSelect__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(8);
/* harmony import */ var _Themes__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(9);
/* harmony import */ var _MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(4);
/* harmony import */ var _LanguageSwitcher__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(10);
/* harmony import */ var _CTAParagraph__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(11);
/* harmony import */ var _HeroImage__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(12);
/* harmony import */ var _OnboardingVideo__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(13);
@@ -953,17 +958,17 @@ class ProtonScreen extends (react__WEBPA
width,
height,
marginBlock,
marginInline,
className = "logo-container"
}) {
function getLoadingStrategy() {
for (let url of [imageURL, darkModeImageURL, reducedMotionImageURL, darkModeReducedMotionImageURL]) {
- if (_lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(url) === "lazy") {
+ if (_lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(url) === "lazy") {
return "lazy";
}
}
return "eager";
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("picture", {
className: className,
style: {
@@ -1184,17 +1189,17 @@ class ProtonScreen extends (react__WEBPA
background: content.background && isCenterPosition ? content.background : null,
width: content.width && content.position !== "split" ? content.width : null
}
}, content.logo ? this.renderPicture(content.logo) : null, isRtamo ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "rtamo-icon"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", {
className: `${isTheme ? "rtamo-theme-icon" : "brand-logo"}`,
src: this.props.iconURL,
- loading: _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(this.props.iconURL),
+ loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(this.props.iconURL),
alt: "",
role: "presentation"
})) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "main-content-inner"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: `welcome-text ${content.title_style || ""}`
}, content.title ? this.renderTitle(content) : null, content.subtitle ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: content.subtitle
@@ -1230,17 +1235,17 @@ class ProtonScreen extends (react__WEBPA
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "MarketplaceButtons": () => (/* binding */ MarketplaceButtons),
/* harmony export */ "MobileDownloads": () => (/* binding */ MobileDownloads)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const MarketplaceButtons = props => {
@@ -1267,17 +1272,17 @@ const MobileDownloads = props => {
const showEmailLink = props.data.email && window.AWSendToDeviceEmailsSupported();
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "mobile-downloads"
}, QRCode ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", {
"data-l10n-id": QRCode.alt_text.string_id ? QRCode.alt_text.string_id : null,
className: "qr-code-image",
alt: typeof QRCode.alt_text === "string" ? QRCode.alt_text : "",
src: QRCode.image_url,
- loading: _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(QRCode.image_url)
+ loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.getLoadingStrategyFor(QRCode.image_url)
}) : null, showEmailLink ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: props.data.email.link_text
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", {
className: "email-link",
value: "email_link",
onClick: props.handleAction
}))) : null, props.data.marketplace_buttons ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(MarketplaceButtons, {
buttons: props.data.marketplace_buttons,
@@ -1443,17 +1448,17 @@ const Themes = props => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "useLanguageSwitcher": () => (/* binding */ useLanguageSwitcher),
/* harmony export */ "LanguageSwitcher": () => (/* binding */ LanguageSwitcher)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(5);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -1667,17 +1672,17 @@ function LanguageSwitcher(props) {
})))), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
style: {
display: showReadyScreen ? "block" : "none"
}
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", {
className: "primary",
value: "primary_button",
onClick: () => {
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(messageId, "download_langpack");
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendActionTelemetry(messageId, "download_langpack");
setIsAwaitingLangpack(true);
}
}, content.languageSwitcher.switch ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement(_MSLocalized__WEBPACK_IMPORTED_MODULE_1__.Localized, {
text: content.languageSwitcher.switch
}) :
// This is the localized name from the Intl.DisplayNames API.
negotiatedLanguage?.langPackDisplayName)), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("button", {
type: "button",
@@ -1742,17 +1747,17 @@ const CTAParagraph = props => {
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "HeroImage": () => (/* binding */ HeroImage)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
const HeroImage = props => {
const {
@@ -1765,17 +1770,17 @@ const HeroImage = props => {
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "hero-image"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("img", {
style: height ? {
height
} : null,
src: url,
- loading: _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.getLoadingStrategyFor(url),
+ loading: _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.getLoadingStrategyFor(url),
alt: alt || "",
role: alt ? null : "presentation"
}));
};
/***/ }),
/* 13 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
@@ -2078,17 +2083,17 @@ const EmbeddedMigrationWizard = ({
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "AddonsPicker": () => (/* binding */ AddonsPicker)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _MSLocalized__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(5);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -2111,21 +2116,21 @@ const AddonsPicker = props => {
type,
data
} = action;
if (type === "INSTALL_ADDON_FROM_URL") {
if (!data) {
return;
}
}
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({
type,
data
});
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id);
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id);
}
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_0___default().createElement("div", {
className: "addons-picker-container"
}, content.tiles.data.map(({
id,
install_label,
name,
type,
@@ -2212,34 +2217,34 @@ const LinkParagraph = props => {
// must pass in tabIndex when no href is provided
,
tabIndex: "0"
}, " "))));
};
/***/ }),
/* 19 */
-/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
+/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "BASE_PARAMS": () => (/* binding */ BASE_PARAMS),
/* harmony export */ "addUtmParams": () => (/* binding */ addUtmParams)
/* harmony export */ });
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/**
* BASE_PARAMS keys/values can be modified from outside this file
*/
const BASE_PARAMS = {
utm_source: "activity-stream",
utm_campaign: "firstrun",
- utm_medium: "referral",
+ utm_medium: "referral"
};
/**
* Takes in a url as a string or URL object and returns a URL object with the
* utm_* parameters added to it. If a URL object is passed in, the paraemeters
* are added to it (the return value can be ignored in that case as it's the
* same object).
*/
@@ -2252,30 +2257,29 @@ function addUtmParams(url, utmTerm) {
if (!returnUrl.searchParams.has(key)) {
returnUrl.searchParams.append(key, value);
}
}
returnUrl.searchParams.append("utm_term", utmTerm);
return returnUrl;
}
-
/***/ }),
/* 20 */
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "ReturnToAMO": () => (/* binding */ ReturnToAMO)
/* harmony export */ });
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(3);
/* harmony import */ var _MultiStageProtonScreen__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6);
-/* harmony import */ var _lib_addUtmParams_mjs__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(19);
+/* harmony import */ var asrouter_content_src_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(19);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -2283,17 +2287,17 @@ class ReturnToAMO extends (react__WEBPAC
constructor(props) {
super(props);
this.fetchFlowParams = this.fetchFlowParams.bind(this);
this.handleAction = this.handleAction.bind(this);
}
async fetchFlowParams() {
if (this.props.metricsFlowUri) {
this.setState({
- flowParams: await _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.fetchFlowParams(this.props.metricsFlowUri)
+ flowParams: await _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.fetchFlowParams(this.props.metricsFlowUri)
});
}
}
componentDidUpdate() {
this.fetchFlowParams();
}
handleAction(event) {
const {
@@ -2316,35 +2320,35 @@ class ReturnToAMO extends (react__WEBPAC
}
// Set add-on url in action.data.url property from JSON
data = {
...data,
url
};
} else if (type === "SHOW_FIREFOX_ACCOUNTS") {
let params = {
- ..._lib_addUtmParams_mjs__WEBPACK_IMPORTED_MODULE_3__.BASE_PARAMS,
+ ...asrouter_content_src_templates_FirstRun_addUtmParams__WEBPACK_IMPORTED_MODULE_3__.BASE_PARAMS,
utm_term: `aboutwelcome-${utm_term}-screen`
};
if (action.addFlowParams && this.state.flowParams) {
params = {
...params,
...this.state.flowParams
};
}
data = {
...data,
extraParams: params
};
}
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.handleUserAction({
type,
data
});
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id);
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.AboutWelcomeUtils.sendActionTelemetry(message_id, source_id);
}
render() {
const {
content,
type
} = this.props;
if (!content) {
return null;
@@ -2370,17 +2374,17 @@ class ReturnToAMO extends (react__WEBPAC
isSingleScreen: true,
autoAdvance: this.props.auto_advance,
iconURL: type.includes("theme") ? this.props.themeScreenshots[0]?.url : this.props.iconURL,
addonName: this.props.name,
handleAction: this.handleAction
}));
}
}
-ReturnToAMO.defaultProps = _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_RTAMO_CONTENT;
+ReturnToAMO.defaultProps = _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_1__.DEFAULT_RTAMO_CONTENT;
/***/ })
/******/ ]);
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
@@ -2449,17 +2453,17 @@ ReturnToAMO.defaultProps = _lib_aboutwel
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
(() => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(2);
/* harmony import */ var react_dom__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(react_dom__WEBPACK_IMPORTED_MODULE_1__);
-/* harmony import */ var _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
+/* harmony import */ var _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(3);
/* harmony import */ var _components_MultiStageAboutWelcome__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(4);
/* harmony import */ var _components_ReturnToAMO__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(20);
function _extends() { _extends = Object.assign ? Object.assign.bind() : function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@@ -2486,17 +2490,17 @@ class AboutWelcome extends (react__WEBPA
}
if (document.location.href === "about:welcome") {
// Record impression with performance data after allowing the page to load
const recordImpression = domState => {
const {
domComplete,
domInteractive
} = performance.getEntriesByType("navigation").pop();
- _lib_aboutwelcome_utils_mjs__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(this.props.messageId, {
+ _lib_aboutwelcome_utils__WEBPACK_IMPORTED_MODULE_2__.AboutWelcomeUtils.sendImpressionTelemetry(this.props.messageId, {
domComplete,
domInteractive,
mountStart: performance.getEntriesByName("mount").pop().startTime,
domState,
source: this.props.UTMTerm
});
};
if (document.readyState === "complete") {
--- a/browser/components/aboutwelcome/karma.mc.config.js
+++ b/browser/components/aboutwelcome/karma.mc.config.js
@@ -78,17 +78,17 @@ module.exports = function (config) {
branches: 66,
overrides: {
"modules/*.jsm": {
statements: 0,
lines: 0,
functions: 0,
branches: 0,
},
- "content-src/lib/aboutwelcome-utils.mjs": {
+ "content-src/lib/aboutwelcome-utils.js": {
statements: 50,
lines: 50,
functions: 50,
branches: 0,
},
"content-src/components/LanguageSwitcher.jsx": {
// This file is covered by the mochitest: browser_aboutwelcome_multistage_languageSwitcher.js
statements: 0,
@@ -247,17 +247,17 @@ module.exports = function (config) {
},
},
{
test: /\.md$/,
use: "raw-loader",
},
{
enforce: "post",
- test: /\.m?js[mx]?$/,
+ test: /\.js[mx]?$/,
loader: "@jsdevtools/coverage-istanbul-loader",
options: { esModules: true },
include: [path.resolve("content-src"), path.resolve("modules")],
exclude: [path.resolve("tests"), path.resolve("../newtab")],
},
],
},
},
--- a/browser/components/aboutwelcome/tests/unit/MultiStageAboutWelcome.test.jsx
+++ b/browser/components/aboutwelcome/tests/unit/MultiStageAboutWelcome.test.jsx
@@ -5,17 +5,17 @@ import {
StepsIndicator,
ProgressBar,
WelcomeScreen,
} from "content-src/components/MultiStageAboutWelcome";
import { Themes } from "content-src/components/Themes";
import React from "react";
import { shallow, mount } from "enzyme";
import { AboutWelcomeDefaults } from "modules/AboutWelcomeDefaults.sys.mjs";
-import { AboutWelcomeUtils } from "content-src/lib/aboutwelcome-utils.mjs";
+import { AboutWelcomeUtils } from "content-src/lib/aboutwelcome-utils";
describe("MultiStageAboutWelcome module", () => {
let globals;
let sandbox;
const DEFAULT_PROPS = {
defaultScreens: AboutWelcomeDefaults.getDefaults().screens,
metricsFlowUri: "http://localhost/",
--- a/browser/components/asrouter/.eslintrc.js
+++ b/browser/components/asrouter/.eslintrc.js
@@ -1,32 +1,36 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = {
// When adding items to this file please check for effects on sub-directories.
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
plugins: ["import", "react", "jsx-a11y"],
settings: {
react: {
version: "16.2.0",
},
},
extends: ["plugin:jsx-a11y/recommended"],
overrides: [
{
- // TODO: Bug 1773467 - Move these to .mjs or figure out a generic way
- // to identify these as modules.
- files: ["content-src/**/*.js", "tests/unit/**/*.js"],
+ // Only mark the files as modules which are actually modules.
+ files: ["content-src/**", "tests/unit/**"],
parserOptions: {
sourceType: "module",
},
},
{
- files: ["bin/**", "content-src/**", "tests/unit/**"],
+ files: ["bin/**", "./*.js", "content-src/**", "tests/unit/**"],
env: {
node: true,
},
},
{
// Use a configuration that's appropriate for modules, workers and
// non-production files.
files: ["tests/**", "modules/**"],
@@ -34,16 +38,18 @@ module.exports = {
"no-implicit-globals": "off",
},
},
{
files: ["content-src/**", "tests/unit/**"],
rules: {
// Disallow commonjs in these directories.
"import/no-commonjs": 2,
+ // Allow JSX with arrow functions.
+ "react/jsx-no-bind": 0,
},
},
{
// These tests simulate the browser environment.
files: "tests/unit/**",
env: {
browser: true,
mocha: true,
@@ -54,28 +60,26 @@ module.exports = {
sinon: true,
},
},
{
files: "tests/**",
rules: {
"func-name-matching": 0,
"lines-between-class-members": 0,
+ "require-await": 0,
},
},
],
rules: {
"fetch-options/no-fetch-credentials": "error",
"react/jsx-boolean-value": ["error", "always"],
"react/jsx-key": "error",
- "react/jsx-no-bind": [
- "error",
- { allowArrowFunctions: true, allowFunctions: true },
- ],
+ "react/jsx-no-bind": "error",
"react/jsx-no-comment-textnodes": "error",
"react/jsx-no-duplicate-props": "error",
"react/jsx-no-target-blank": "error",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": "error",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/no-access-state-in-setstate": "error",
@@ -88,40 +92,49 @@ module.exports = {
"react/no-unknown-property": "error",
"react/require-render-return": "error",
"accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }],
"array-callback-return": "error",
"block-scoped-var": "error",
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
+ "for-direction": "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
+ "handle-callback-err": "error",
+ "lines-between-class-members": "error",
"max-depth": ["error", 4],
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],
"max-statements": ["error", 50],
+ "max-statements-per-line": ["error", { max: 2 }],
"new-cap": ["error", { newIsCap: true, capIsNew: false }],
"no-alert": "error",
+ "no-buffer-constructor": "error",
"no-console": ["error", { allow: ["error"] }],
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-eq-null": "error",
"no-extend-native": "error",
"no-extra-label": "error",
"no-implicit-coercion": ["error", { allow: ["!!"] }],
"no-implicit-globals": "error",
"no-loop-func": "error",
+ "no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-new": "error",
"no-new-func": "error",
+ "no-new-require": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
+ "no-path-concat": "error",
+ "no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-return-assign": ["error", "except-parens"],
"no-script-url": "error",
"no-shadow": "error",
"no-template-curly-in-string": "error",
"no-undef-init": "error",
"no-unmodified-loop-condition": "error",
@@ -142,14 +155,15 @@ module.exports = {
},
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
radix: ["error", "always"],
+ "require-await": "error",
"sort-vars": "error",
"symbol-description": "error",
"vars-on-top": "error",
yoda: ["error", "never"],
},
};
--- a/browser/components/asrouter/content-src/components/ASRouterAdmin/ASRouterAdmin.jsx
+++ b/browser/components/asrouter/content-src/components/ASRouterAdmin/ASRouterAdmin.jsx
@@ -502,32 +502,34 @@ export class ASRouterAdminInner extends
>
{isBlocked ? "Unblock" : "Block"}
</button>
{
// eslint-disable-next-line no-nested-ternary
isBlocked ? null : isModified ? (
<button
className="button restore"
+ // eslint-disable-next-line react/jsx-no-bind
onClick={e => this.resetJSON(msg)}
>
Reset
</button>
) : (
<button
className="button show"
onClick={this.handleOverride(msg.id)}
>
Show
</button>
)
}
{isBlocked ? null : (
<button
className="button modify"
+ // eslint-disable-next-line react/jsx-no-bind
onClick={e => this.modifyJson(msg)}
>
Modify
</button>
)}
{aboutMessagePreviewSupported ? (
<CopyButton
transformer={text =>
@@ -552,16 +554,17 @@ export class ASRouterAdminInner extends
)}
<tr>
<pre className={isCollapsed ? "collapsed" : "expanded"}>
<textarea
id={`${msg.id}-textarea`}
name={msg.id}
className="general-textarea"
disabled={isBlocked}
+ // eslint-disable-next-line react/jsx-no-bind
onChange={e => this.handleChange(msg.id)}
>
{JSON.stringify(msg, null, 2)}
</textarea>
</pre>
</tr>
</td>
</tr>
@@ -693,16 +696,17 @@ export class ASRouterAdminInner extends
message.provider === this.state.messageFilter &&
message.template !== "pb_newtab"
);
return (
<div>
<button
className="ASRouterButton slim"
+ // eslint-disable-next-line react/jsx-no-bind
onClick={e => this.toggleAllMessages(messagesToShow)}
>
Collapse/Expand All
</button>
<p className="helpLink">
<span className="icon icon-small-spacer icon-info" />{" "}
<span>
To modify a message, change the JSON and click 'Modify' to see your
@@ -1302,16 +1306,17 @@ export class ASRouterAdminInner extends
id={`clear radio`}
name="PB_message_radio"
value="clearPBMessage"
style={{ display: "none" }}
/>
<h2>Messages</h2>
<button
className="ASRouterButton slim button"
+ // eslint-disable-next-line react/jsx-no-bind
onClick={e => this.toggleAllMessages(messagesToShow)}
>
Collapse/Expand All
</button>
{this.renderPBMessages()}
</div>
</div>
);
new file mode 100644
--- /dev/null
+++ b/browser/components/asrouter/content-src/template-utils.js
@@ -0,0 +1,22 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+export function safeURI(url) {
+ if (!url) {
+ return "";
+ }
+ const { protocol } = new URL(url);
+ const isAllowed = [
+ "http:",
+ "https:",
+ "data:",
+ "resource:",
+ "chrome:",
+ ].includes(protocol);
+ if (!isAllowed) {
+ // eslint-disable-next-line no-console
+ console.warn(`The protocol ${protocol} is not allowed for template URLs.`);
+ }
+ return isAllowed ? url : "";
+}
rename from browser/components/aboutwelcome/content-src/lib/addUtmParams.mjs
rename to browser/components/asrouter/content-src/templates/FirstRun/addUtmParams.js
--- a/browser/components/asrouter/content/asrouter-admin.bundle.js
+++ b/browser/components/asrouter/content/asrouter-admin.bundle.js
@@ -1424,39 +1424,45 @@ class ASRouterAdminInner extends (react_
})), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
className: "button-column"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
className: `button ${isBlocked ? "" : " primary"}`,
onClick: isBlocked ? this.handleUnblock(msg) : this.handleBlock(msg)
}, isBlocked ? "Unblock" : "Block"),
// eslint-disable-next-line no-nested-ternary
isBlocked ? null : isModified ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
- className: "button restore",
+ className: "button restore"
+ // eslint-disable-next-line react/jsx-no-bind
+ ,
onClick: e => this.resetJSON(msg)
}, "Reset") : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
className: "button show",
onClick: this.handleOverride(msg.id)
}, "Show"), isBlocked ? null : /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
- className: "button modify",
+ className: "button modify"
+ // eslint-disable-next-line react/jsx-no-bind
+ ,
onClick: e => this.modifyJson(msg)
}, "Modify"), aboutMessagePreviewSupported ? /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement(_CopyButton__WEBPACK_IMPORTED_MODULE_4__.CopyButton, {
transformer: text => `about:messagepreview?json=${encodeURIComponent(btoa(text))}`,
label: "Share",
copiedLabel: "Copied!",
inputSelector: `#${msg.id}-textarea`,
className: "button share"
}) : null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("br", null), "(", impressions, " impressions)"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("td", {
className: "message-summary"
}, isBlocked && /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, "Block reason:", isBlockedByGroup && " Blocked by group", isProviderExcluded && " Excluded by provider", isMessageBlocked && " Message blocked"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tr", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("pre", {
className: isCollapsed ? "collapsed" : "expanded"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("textarea", {
id: `${msg.id}-textarea`,
name: msg.id,
className: "general-textarea",
- disabled: isBlocked,
+ disabled: isBlocked
+ // eslint-disable-next-line react/jsx-no-bind
+ ,
onChange: e => this.handleChange(msg.id)
}, JSON.stringify(msg, null, 2))))));
}
selectPBMessage(msgId) {
if (msgId === "clear") {
this.setState({
selectedPBMessage: ""
});
@@ -1536,17 +1542,19 @@ class ASRouterAdminInner extends (react_
}
}
renderMessages() {
if (!this.state.messages) {
return null;
}
const messagesToShow = this.state.messageFilter === "all" ? this.state.messages : this.state.messages.filter(message => message.provider === this.state.messageFilter && message.template !== "pb_newtab");
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("div", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
- className: "ASRouterButton slim",
+ className: "ASRouterButton slim"
+ // eslint-disable-next-line react/jsx-no-bind
+ ,
onClick: e => this.toggleAllMessages(messagesToShow)
}, "Collapse/Expand All"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("p", {
className: "helpLink"
}, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", {
className: "icon icon-small-spacer icon-info"
}), " ", /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("span", null, "To modify a message, change the JSON and click 'Modify' to see your changes. Click 'Reset' to restore the JSON to the original. Click 'Share' to copy a link to the clipboard that can be used to preview the message by opening the link in Nightly/local builds.")), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("table", null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("tbody", null, messagesToShow.map(msg => this.renderMessageItem(msg)))));
}
renderMessagesByGroup() {
@@ -1838,17 +1846,19 @@ class ASRouterAdminInner extends (react_
type: "radio",
id: `clear radio`,
name: "PB_message_radio",
value: "clearPBMessage",
style: {
display: "none"
}
}), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Messages"), /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("button", {
- className: "ASRouterButton slim button",
+ className: "ASRouterButton slim button"
+ // eslint-disable-next-line react/jsx-no-bind
+ ,
onClick: e => this.toggleAllMessages(messagesToShow)
}, "Collapse/Expand All"), this.renderPBMessages()));
}
getSection() {
const [section] = this.props.location.routes;
switch (section) {
case "private":
return /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement((react__WEBPACK_IMPORTED_MODULE_1___default().Fragment), null, /*#__PURE__*/react__WEBPACK_IMPORTED_MODULE_1___default().createElement("h2", null, "Private Browsing Messages"), this.renderPBTab());
rename from browser/components/aboutwelcome/tests/unit/addUtmParams.test.js
rename to browser/components/asrouter/tests/unit/addUtmParams.test.js
--- a/browser/components/aboutwelcome/tests/unit/addUtmParams.test.js
+++ b/browser/components/asrouter/tests/unit/addUtmParams.test.js
@@ -1,9 +1,12 @@
-import { addUtmParams, BASE_PARAMS } from "content-src/lib/addUtmParams.mjs";
+import {
+ addUtmParams,
+ BASE_PARAMS,
+} from "content-src/templates/FirstRun/addUtmParams";
describe("addUtmParams", () => {
it("should convert a string URL", () => {
const result = addUtmParams("https://foo.com", "foo");
assert.equal(result.hostname, "foo.com");
});
it("should add all base params", () => {
assert.match(
new file mode 100644
--- /dev/null
+++ b/browser/components/asrouter/tests/unit/template-utils.test.js
@@ -0,0 +1,31 @@
+import { safeURI } from "content-src/template-utils";
+
+describe("safeURI", () => {
+ let warnStub;
+ beforeEach(() => {
+ warnStub = sinon.stub(console, "warn");
+ });
+ afterEach(() => {
+ warnStub.restore();
+ });
+ it("should allow http: URIs", () => {
+ assert.equal(safeURI("http://foo.com"), "http://foo.com");
+ });
+ it("should allow https: URIs", () => {
+ assert.equal(safeURI("https://foo.com"), "https://foo.com");
+ });
+ it("should allow data URIs", () => {
+ assert.equal(
+ safeURI("data:image/png;base64,iVBO"),
+ "data:image/png;base64,iVBO"
+ );
+ });
+ it("should not allow javascript: URIs", () => {
+ assert.equal(safeURI("javascript:foo()"), ""); // eslint-disable-line no-script-url
+ assert.calledOnce(warnStub);
+ });
+ it("should not warn if the URL is falsey ", () => {
+ assert.equal(safeURI(), "");
+ assert.notCalled(warnStub);
+ });
+});
--- a/browser/components/newtab/.eslintrc.js
+++ b/browser/components/newtab/.eslintrc.js
@@ -1,30 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
module.exports = {
// When adding items to this file please check for effects on sub-directories.
+ parserOptions: {
+ ecmaFeatures: {
+ jsx: true,
+ },
+ },
plugins: ["import", "react", "jsx-a11y"],
settings: {
react: {
version: "16.2.0",
},
},
extends: ["plugin:jsx-a11y/recommended"],
overrides: [
{
- // TODO: Bug 1773467 - Move these to .mjs or figure out a generic way
- // to identify these as modules.
- files: [
- "content-src/**/*.js",
- "test/schemas/**/*.js",
- "test/unit/**/*.js",
- ],
+ // Only mark the files as modules which are actually modules.
+ files: ["content-src/**", "test/schemas/**", "test/unit/**"],
parserOptions: {
sourceType: "module",
},
},
{
// These files use fluent-dom to insert content
files: [
"content-src/asrouter/templates/OnboardingMessage/**",
@@ -42,16 +42,17 @@ module.exports = {
"jsx-a11y/label-has-associated-control": "off",
"jsx-a11y/no-onchange": "off",
},
},
{
files: [
"bin/**",
"content-src/**",
+ "./*.js",
"loaders/**",
"tools/**",
"test/unit/**",
],
env: {
node: true,
},
},
@@ -63,16 +64,18 @@ module.exports = {
"no-implicit-globals": "off",
},
},
{
files: ["content-src/**", "test/unit/**"],
rules: {
// Disallow commonjs in these directories.
"import/no-commonjs": 2,
+ // Allow JSX with arrow functions.
+ "react/jsx-no-bind": 0,
},
},
{
// These tests simulate the browser environment.
files: "test/unit/**",
env: {
browser: true,
mocha: true,
@@ -83,28 +86,26 @@ module.exports = {
sinon: true,
},
},
{
files: "test/**",
rules: {
"func-name-matching": 0,
"lines-between-class-members": 0,
+ "require-await": 0,
},
},
],
rules: {
"fetch-options/no-fetch-credentials": "error",
"react/jsx-boolean-value": ["error", "always"],
"react/jsx-key": "error",
- "react/jsx-no-bind": [
- "error",
- { allowArrowFunctions: true, allowFunctions: true },
- ],
+ "react/jsx-no-bind": "error",
"react/jsx-no-comment-textnodes": "error",
"react/jsx-no-duplicate-props": "error",
"react/jsx-no-target-blank": "error",
"react/jsx-no-undef": "error",
"react/jsx-pascal-case": "error",
"react/jsx-uses-react": "error",
"react/jsx-uses-vars": "error",
"react/no-access-state-in-setstate": "error",
@@ -117,40 +118,49 @@ module.exports = {
"react/no-unknown-property": "error",
"react/require-render-return": "error",
"accessor-pairs": ["error", { setWithoutGet: true, getWithoutSet: false }],
"array-callback-return": "error",
"block-scoped-var": "error",
"consistent-this": ["error", "use-bind"],
eqeqeq: "error",
+ "for-direction": "error",
"func-name-matching": "error",
"getter-return": "error",
"guard-for-in": "error",
+ "handle-callback-err": "error",
+ "lines-between-class-members": "error",
"max-depth": ["error", 4],
"max-nested-callbacks": ["error", 4],
"max-params": ["error", 6],
"max-statements": ["error", 50],
+ "max-statements-per-line": ["error", { max: 2 }],
"new-cap": ["error", { newIsCap: true, capIsNew: false }],
"no-alert": "error",
+ "no-buffer-constructor": "error",
"no-console": ["error", { allow: ["error"] }],
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-eq-null": "error",
"no-extend-native": "error",
"no-extra-label": "error",
"no-implicit-coercion": ["error", { allow: ["!!"] }],
"no-implicit-globals": "error",
"no-loop-func": "error",
+ "no-mixed-requires": "error",
"no-multi-assign": "error",
"no-multi-str": "error",
"no-new": "error",
"no-new-func": "error",
+ "no-new-require": "error",
"no-octal-escape": "error",
"no-param-reassign": "error",
+ "no-path-concat": "error",
+ "no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-return-assign": ["error", "except-parens"],
"no-script-url": "error",
"no-shadow": "error",
"no-template-curly-in-string": "error",
"no-undef-init": "error",
"no-unmodified-loop-condition": "error",
@@ -171,14 +181,15 @@ module.exports = {
},
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "error",
"prefer-rest-params": "error",
"prefer-spread": "error",
"prefer-template": "error",
radix: ["error", "always"],
+ "require-await": "error",
"sort-vars": "error",
"symbol-description": "error",
"vars-on-top": "error",
yoda: ["error", "never"],
},
};
--- a/browser/components/newtab/content-src/components/Search/Search.jsx
+++ b/browser/components/newtab/content-src/components/Search/Search.jsx
@@ -1,13 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals ContentSearchUIController, ContentSearchHandoffUIController */
+"use strict";
import {
actionCreators as ac,
actionTypes as at,
} from "common/Actions.sys.mjs";
import { connect } from "react-redux";
import { IS_NEWTAB } from "content-src/lib/constants";
import React from "react";
--- a/browser/components/newtab/data/content/activity-stream.bundle.js
+++ b/browser/components/newtab/data/content/activity-stream.bundle.js
@@ -8878,16 +8878,17 @@ const NEWTAB_DARK_THEME = {
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/* globals ContentSearchUIController, ContentSearchHandoffUIController */
+
class _Search extends (external_React_default()).PureComponent {
constructor(props) {
super(props);
this.onSearchClick = this.onSearchClick.bind(this);
this.onSearchHandoffClick = this.onSearchHandoffClick.bind(this);
this.onSearchHandoffPaste = this.onSearchHandoffPaste.bind(this);
this.onSearchHandoffDrop = this.onSearchHandoffDrop.bind(this);
this.onInputMount = this.onInputMount.bind(this);
--- a/browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/ImpressionStats.test.jsx
+++ b/browser/components/newtab/test/unit/content-src/components/DiscoveryStreamComponents/ImpressionStats.test.jsx
@@ -1,8 +1,10 @@
+"use strict";
+
import {
ImpressionStats,
INTERSECTION_RATIO,
} from "content-src/components/DiscoveryStreamImpressionStats/ImpressionStats";
import { actionTypes as at } from "common/Actions.sys.mjs";
import React from "react";
import { shallow } from "enzyme";
--- a/browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx
+++ b/browser/components/newtab/test/unit/content-src/components/TopSites/TopSiteImpressionWrapper.test.jsx
@@ -1,8 +1,10 @@
+"use strict";
+
import {
TopSiteImpressionWrapper,
INTERSECTION_RATIO,
} from "content-src/components/TopSites/TopSiteImpressionWrapper";
import { actionTypes as at } from "common/Actions.sys.mjs";
import React from "react";
import { shallow } from "enzyme";
--- a/browser/components/pocket/webpack.config.js
+++ b/browser/components/pocket/webpack.config.js
@@ -1,11 +1,12 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* eslint-env node */
module.exports = {
mode: "production",
entry: {
main: "./content/panels/js/main.js",
},
output: {
filename: "[name].bundle.js",
--- a/browser/components/storybook/custom-elements-manifest.config.mjs
+++ b/browser/components/storybook/custom-elements-manifest.config.mjs
@@ -5,18 +5,18 @@
/**
* Custom element manifest analyzer plugin to remove static and private
* properties from custom-elements.json that we don't want to document in our
* Storybook props tables.
*/
function removePrivateAndStaticFields() {
return {
packageLinkPhase({ customElementsManifest }) {
- customElementsManifest?.modules?.forEach(m => {
- m?.declarations?.forEach(declaration => {
+ customElementsManifest?.modules?.forEach(module => {
+ module?.declarations?.forEach(declaration => {
if (declaration.members != null) {
declaration.members = declaration.members.filter(member => {
return (
!member.kind === "field" ||
(!member.static && !member.name.startsWith("#"))
);
});
}
--- a/devtools/client/debugger/babel.config.js
+++ b/devtools/client/debugger/babel.config.js
@@ -1,14 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
"use strict";
+/* global __dirname */
+
/**
* NOTE: This file does not apply to builds in MC. This config is used for
* our Jest tests and for webpack bundle builds.
*/
module.exports = {
sourceType: "unambiguous",
overrides: [
{
--- a/devtools/client/debugger/jest-test.config.js
+++ b/devtools/client/debugger/jest-test.config.js
@@ -1,14 +1,16 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
"use strict";
+/* global __dirname */
+
const sharedJestConfig = require(`${__dirname}/../shared/test-helpers/shared-jest.config`);
module.exports = {
testEnvironment: "jsdom",
testPathIgnorePatterns: [
"/node_modules/",
"/helpers/",
"/fixtures/",
--- a/devtools/client/debugger/jest.config.js
+++ b/devtools/client/debugger/jest.config.js
@@ -1,13 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at <http://mozilla.org/MPL/2.0/>. */
"use strict";
+/* global __dirname */
+
const { resolve } = require("path");
const rootDir = resolve(__dirname);
module.exports = {
rootDir,
reporters: ["default"],
projects: ["<rootDir>/jest-test.config.js"],
};
--- a/devtools/client/shared/sourceeditor/webpack.config.js
+++ b/devtools/client/shared/sourceeditor/webpack.config.js
@@ -1,14 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
+/* global __dirname */
const path = require("path");
module.exports = (env, argv) => {
return {
bail: true,
entry: [
"./codemirror/addon/dialog/dialog.js",
"./codemirror/addon/search/searchcursor.js",
--- a/devtools/client/shared/test-helpers/shared-jest.config.js
+++ b/devtools/client/shared/test-helpers/shared-jest.config.js
@@ -1,14 +1,15 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
+/* global __dirname */
const fixturesDir = `${__dirname}/jest-fixtures`;
module.exports = {
verbose: true,
moduleNameMapper: {
// Custom name mappers for modules that require m-c specific API.
"^devtools/shared/generate-uuid": `${fixturesDir}/generate-uuid`,
"^devtools/shared/DevToolsUtils": `${fixturesDir}/devtools-utils`,
--- a/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
+++ b/tools/lint/eslint/eslint-plugin-mozilla/lib/configs/recommended.js
@@ -5,21 +5,16 @@
"use strict";
/**
* The configuration is based on eslint:recommended config. The details for all
* the ESLint rules, and which ones are in the recommended configuration can
* be found here:
*
* https://eslint.org/docs/rules/
- *
- * Rules that we've explicitly decided not to enable:
- *
- * require-await - bug 1381030.
- * no-prototype-builtins - bug 1551829.
*/
module.exports = {
env: {
browser: true,
es2022: true,
"mozilla/privileged": true,
"mozilla/specific": true,
},
@@ -53,40 +48,46 @@ module.exports = {
"mozilla/reject-mixing-eager-and-lazy": "error",
"mozilla/reject-top-level-await": "error",
// TODO: Bug 1575506 turn `builtinGlobals` on here.
// We can enable builtinGlobals for jsms due to their scopes.
"no-redeclare": ["error", { builtinGlobals: false }],
},
},
{
- files: ["**/*.mjs", "**/*.jsx", "**/*.jsm", "**/?(*.)worker.?(m)js"],
+ files: ["**/*.mjs", "**/*.jsm", "**/?(*.)worker.?(m)js"],
rules: {
// Modules and workers are far easier to check for no-unused-vars on a
// global scope, than our content files. Hence we turn that on here.
"no-unused-vars": [
"error",
{
args: "none",
vars: "all",
},
],
},
},
{
+ files: ["**/*.sys.mjs"],
+ rules: {
+ "mozilla/use-static-import": "error",
+ },
+ },
+ {
excludedFiles: ["**/*.sys.mjs"],
files: ["**/*.mjs"],
rules: {
"mozilla/reject-import-system-module-from-non-system": "error",
"mozilla/reject-lazy-imports-into-globals": "error",
"no-shadow": ["error", { allow: ["event"], builtinGlobals: true }],
},
},
{
- files: ["**/*.mjs", "**/*.jsx"],
+ files: ["**/*.mjs"],
parserOptions: {
sourceType: "module",
},
rules: {
"mozilla/use-static-import": "error",
// This rule defaults to not allowing "use strict" in module files since
// they are always loaded in strict mode.
strict: "error",